{"openapi":"3.1.0","info":{"title":"MRV Solution Integration API","version":"1.3.0","summary":"Read-only access to farmer-confirmed field boundaries, land cover and certified reports for Arla Foods' Salesforce integration.","description":"Pull the data farmers have entered in MRV Solution (fields, boundaries,\nland-cover composition, certified per-farm reports) into an external\nsystem on a schedule, using date-windowed, keyset-paginated reads.\n\nAuthentication is a single long-lived service token sent as\n`Authorization: Bearer <token>`. Every response is JSON with snake_case\nkeys, ISO 8601 UTC timestamps, hectares for areas and GeoJSON (EPSG:4326)\nfor geometry. Errors always use the `Error` envelope.\n\nThe full narrative reference, sync-strategy guidance and Apex example\nlive in `docs/integration-api.md` in the application repository.","contact":{"name":"DigiFarm","url":"https://digifarm.io"}},"servers":[{"url":"https://arla-fields.digifarm.io/api/v1","description":"Production (live farmer data)."},{"url":"https://{host}/api/v1","description":"Development / UAT — an Amplify branch deployment reading the separate `development` data set. Hostname supplied by DigiFarm; not intended for Arla's production sync.","variables":{"host":{"default":"arla-fields.digifarm.io","description":"Deployment hostname for the non-production branch."}}}],"tags":[{"name":"Meta","description":"Token introspection and this document."},{"name":"Farms","description":"Per-farm roll-ups of the fields below."},{"name":"Fields","description":"Individual farmer fields with boundaries and land cover."},{"name":"Reports","description":"Certified per-farm submission reports (PDF + snapshot)."}],"security":[{"bearerAuth":[]}],"paths":{"/me":{"get":{"operationId":"getMe","tags":["Meta"],"summary":"Introspect the calling token","description":"Returns the token's own metadata, which environment (data set) the server is serving, and the server clock. Any scope is sufficient. Use it as a connectivity/credential smoke test.","responses":{"200":{"description":"Token accepted.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"$ref":"#/components/schemas/Me"}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/Internal"}}}},"/farms":{"get":{"operationId":"listFarms","tags":["Farms"],"summary":"List farms that have at least one field","description":"One item per Salesforce Farm that has at least one field in MRV Solution (farms with zero fields are excluded, exactly like the weekly submission report). The date window applies to the farm's `last_field_updated_at` — the most recent `updated_at` across its fields — so a farm appears whenever any of its fields changed in the window; the response's `window.applied_to` is `\"last_field_updated_at\"`. Requires scope `fields:read`.","parameters":[{"$ref":"#/components/parameters/UpdatedSince"},{"$ref":"#/components/parameters/UpdatedUntil"},{"$ref":"#/components/parameters/Limit"},{"$ref":"#/components/parameters/Cursor"},{"$ref":"#/components/parameters/FarmIdFilter"},{"$ref":"#/components/parameters/LegalEntityId"},{"$ref":"#/components/parameters/Country"},{"$ref":"#/components/parameters/FarmStatus"},{"$ref":"#/components/parameters/FarmSubmissionSource"}],"responses":{"200":{"description":"A page of farms ordered by (`last_field_updated_at`, `farm_id`) ascending.","content":{"application/json":{"schema":{"type":"object","required":["data","page","window","generated_at"],"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Farm"}},"page":{"$ref":"#/components/schemas/Page"},"window":{"allOf":[{"$ref":"#/components/schemas/Window"}],"description":"The effective date window after defaults were applied; `applied_to` is always `\"last_field_updated_at\"` here."},"generated_at":{"type":"string","format":"date-time","description":"Server time at which this page was produced. Use it (minus an overlap) as the next sync run's `since`."}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/Internal"}}}},"/farms/{farm_id}":{"parameters":[{"$ref":"#/components/parameters/FarmIdPath"}],"get":{"operationId":"getFarm","tags":["Farms"],"summary":"Get one farm","description":"The same item shape as the list, for one Salesforce Farm.Id. Not date-windowed. 404 `not_found` when the farm has no fields in MRV Solution (or is unknown). Requires scope `fields:read`.","responses":{"200":{"description":"The farm.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"$ref":"#/components/schemas/Farm"}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/Internal"}}}},"/farms/{farm_id}/fields":{"parameters":[{"$ref":"#/components/parameters/FarmIdPath"}],"get":{"operationId":"listFarmFields","tags":["Farms","Fields"],"summary":"List one farm's fields","description":"Identical to `GET /fields` with the `farm_id` filter fixed to the path parameter (any `farm_id` query values are ignored). All other field-list query parameters apply. A farm with no fields yields an empty page, not a 404. Requires scope `fields:read`.","parameters":[{"$ref":"#/components/parameters/UpdatedSince"},{"$ref":"#/components/parameters/UpdatedUntil"},{"$ref":"#/components/parameters/Limit"},{"$ref":"#/components/parameters/Cursor"},{"$ref":"#/components/parameters/LegalEntityId"},{"$ref":"#/components/parameters/Country"},{"$ref":"#/components/parameters/FieldStatus"},{"$ref":"#/components/parameters/Source"},{"$ref":"#/components/parameters/SubmissionSource"},{"$ref":"#/components/parameters/Include"},{"$ref":"#/components/parameters/Format"}],"responses":{"200":{"description":"A page of fields.","content":{"application/json":{"schema":{"oneOf":[{"type":"object","required":["data","page","window","generated_at"],"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Field"}},"page":{"$ref":"#/components/schemas/Page"},"window":{"allOf":[{"$ref":"#/components/schemas/Window"}],"description":"The effective date window after defaults were applied; `applied_to` is always `\"updated_at\"` here."},"generated_at":{"type":"string","format":"date-time","description":"Server time at which this page was produced. Use it (minus an overlap) as the next sync run's `since`."}}},{"$ref":"#/components/schemas/FieldFeatureCollection"}],"description":"The JSON envelope by default; the FeatureCollection form with `format=geojson`."}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/Internal"}}}},"/farms/{farm_id}/report":{"parameters":[{"$ref":"#/components/parameters/FarmIdPath"}],"get":{"operationId":"getFarmReport","tags":["Farms"],"summary":"Get one farm's report (farm + summary + all fields)","description":"One JSON document per farm for downstream storage or rendering: the `Farm` object, a `summary` computed over EVERY field of the farm (counts, the productive / non-productive / unclassified area partition, land cover summed across fields in the active scheme, counts by `origin` and by `land_cover.status`), the full list of `Field` objects (not windowed, not paginated — a farm has tens of fields at most), and the `latest_report` pointer. Available for any farm with at least one field, not only fully submitted ones; 404 `not_found` when the farm has no fields. `include=geometry` is the only query parameter — it adds each field's boundary to `fields[]` (omitted by default). Requires scope `fields:read`.","parameters":[{"$ref":"#/components/parameters/Include"}],"responses":{"200":{"description":"The farm report.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"$ref":"#/components/schemas/FarmReport"}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/Internal"}}}},"/fields":{"get":{"operationId":"listFields","tags":["Fields"],"summary":"List fields changed in a date window","description":"Keyset-paginated fields, ordered by (`updated_at`, `id`) ascending, filtered to the window on `updated_at`. `geometry` is omitted by default to keep pages small — pass `include=geometry` to embed it, or `format=geojson` to receive a GeoJSON FeatureCollection instead of the JSON envelope. Requires scope `fields:read`.","parameters":[{"$ref":"#/components/parameters/FarmIdFilter"},{"$ref":"#/components/parameters/UpdatedSince"},{"$ref":"#/components/parameters/UpdatedUntil"},{"$ref":"#/components/parameters/Limit"},{"$ref":"#/components/parameters/Cursor"},{"$ref":"#/components/parameters/LegalEntityId"},{"$ref":"#/components/parameters/Country"},{"$ref":"#/components/parameters/FieldStatus"},{"$ref":"#/components/parameters/Source"},{"$ref":"#/components/parameters/SubmissionSource"},{"$ref":"#/components/parameters/Include"},{"$ref":"#/components/parameters/Format"}],"responses":{"200":{"description":"A page of fields. With `format=geojson` the body is a FeatureCollection whose `page`, `window` and `generated_at` are top-level foreign members.","content":{"application/json":{"schema":{"oneOf":[{"type":"object","required":["data","page","window","generated_at"],"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Field"}},"page":{"$ref":"#/components/schemas/Page"},"window":{"allOf":[{"$ref":"#/components/schemas/Window"}],"description":"The effective date window after defaults were applied; `applied_to` is always `\"updated_at\"` here."},"generated_at":{"type":"string","format":"date-time","description":"Server time at which this page was produced. Use it (minus an overlap) as the next sync run's `since`."}}},{"$ref":"#/components/schemas/FieldFeatureCollection"}],"description":"The JSON envelope by default; the FeatureCollection form with `format=geojson`."}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/Internal"}}}},"/fields/{id}":{"parameters":[{"$ref":"#/components/parameters/FieldIdPath"}],"get":{"operationId":"getField","tags":["Fields"],"summary":"Get one field (always with geometry)","description":"The full Field object. Unlike the list, `geometry` is always present, and `cadastral_parcel_match.geometry` / `digifarm_boundary_match.geometry` are included when those matches exist. Requires scope `fields:read`.","responses":{"200":{"description":"The field.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"$ref":"#/components/schemas/Field"}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/Internal"}}}},"/fields/{id}/land-cover-geometry":{"parameters":[{"$ref":"#/components/parameters/FieldIdPath"}],"get":{"operationId":"getFieldLandCoverGeometry","tags":["Fields"],"summary":"Get a field's per-class land-cover polygons","description":"The dissolved per-land-cover-class polygons inside the field's boundary (one Feature per class present, each carrying `{ code }`), as computed by the land-cover pipeline. This can be large and is only produced for fields whose composition has been computed — 404 `not_found` otherwise. Requires scope `fields:read`.","responses":{"200":{"description":"The land-cover geometry.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"$ref":"#/components/schemas/LandCoverGeometry"}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/Internal"}}}},"/reports":{"get":{"operationId":"listReports","tags":["Reports"],"summary":"List certified reports generated in a date window","description":"Certified per-farm submission reports, ordered by (`generated_at`, `id`) ascending, windowed on `generated_at`. Reports are immutable and versioned — each farm submission inserts a new row and nothing is ever updated — so a report seen once never changes. Requires scope `reports:read`.","parameters":[{"$ref":"#/components/parameters/GeneratedSince"},{"$ref":"#/components/parameters/GeneratedUntil"},{"$ref":"#/components/parameters/UpdatedSinceAlias"},{"$ref":"#/components/parameters/UpdatedUntilAlias"},{"$ref":"#/components/parameters/Limit"},{"$ref":"#/components/parameters/Cursor"},{"$ref":"#/components/parameters/FarmIdFilter"},{"$ref":"#/components/parameters/LegalEntityId"},{"$ref":"#/components/parameters/ReportCountry"},{"$ref":"#/components/parameters/ReportSubmissionSource"}],"responses":{"200":{"description":"A page of reports.","content":{"application/json":{"schema":{"type":"object","required":["data","page","window","generated_at"],"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Report"}},"page":{"$ref":"#/components/schemas/Page"},"window":{"allOf":[{"$ref":"#/components/schemas/Window"}],"description":"The effective date window after defaults were applied; `applied_to` is always `\"generated_at\"` here."},"generated_at":{"type":"string","format":"date-time","description":"Server time at which this page was produced. Use it (minus an overlap) as the next sync run's `since`."}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/Internal"}}}},"/reports/{id}":{"parameters":[{"$ref":"#/components/parameters/ReportIdPath"}],"get":{"operationId":"getReport","tags":["Reports"],"summary":"Get one report with its immutable snapshot","description":"The list item plus `report_data`: the raw facts the certificate was generated (and signed) from, passed through verbatim. Requires scope `reports:read`.","responses":{"200":{"description":"The report.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"$ref":"#/components/schemas/ReportDetail"}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/Internal"}}}},"/reports/{id}/pdf":{"parameters":[{"$ref":"#/components/parameters/ReportIdPath"}],"get":{"operationId":"getReportPdf","tags":["Reports"],"summary":"Download the certified report PDF","description":"Streams the certificate PDF (`Content-Type: application/pdf`, `Content-Length`, `Content-Disposition: inline; filename=\"<farm label>.pdf\"`, `Cache-Control: private, no-store`), re-rendered from the certified snapshot exactly as the public verify page does, falling back to the copy stored at submission time (`X-Report-Render: fallback`). 404 for an unknown id or a row whose tamper-evidence signature fails; 503 `not_configured` when the server has no report storage configured; 502 `unavailable` when the PDF can neither be rendered nor read from storage. Requires scope `reports:read`.","responses":{"200":{"description":"The PDF bytes.","content":{"application/pdf":{"schema":{"type":"string","format":"binary"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/Internal"},"502":{"description":"The PDF could neither be rendered nor read from storage; retry later.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"$ref":"#/components/responses/NotConfigured"}}}},"/openapi.json":{"get":{"operationId":"getOpenApiDocument","tags":["Meta"],"summary":"This document","description":"The OpenAPI 3.1 description of this API. Public — no token required. Cached for 5 minutes (`Cache-Control: public, max-age=300`).","security":[],"responses":{"200":{"description":"The OpenAPI document.","content":{"application/json":{"schema":{"type":"object","description":"An OpenAPI 3.1 document."}}}}}}}},"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"mrv_<live|dev>_<43 base64url chars>","description":"A service token issued by DigiFarm, sent as `Authorization: Bearer <token>`. Tokens carry scopes (`fields:read`, `reports:read`), may have an expiry, and can be revoked or rotated at any time. A missing, malformed, unknown, expired or revoked token is always `401 unauthorized` (the reasons are deliberately not distinguished); a valid token lacking the scope an endpoint needs is `403 forbidden`."}},"headers":{"X-RateLimit-Limit":{"description":"The per-token request budget for the rate-limit window (requests per minute by default; `600` unless the server is configured otherwise). Only sent on a 429 response.","schema":{"type":"integer","example":600}},"Retry-After":{"description":"Seconds to wait before retrying (always `60` on a 429).","schema":{"type":"integer","example":60}}},"parameters":{"UpdatedSince":{"name":"updated_since","in":"query","description":"Start of the window (inclusive) on `updated_at`. ISO 8601; a date-only value (`2026-09-01`) means 00:00:00 UTC that day, and a date-time without a zone designator is read as UTC. Default: `updated_until − 14 days`.","schema":{"type":"string","format":"date-time"}},"UpdatedUntil":{"name":"updated_until","in":"query","description":"End of the window (inclusive) on `updated_at`. ISO 8601; date-only accepted. Default: now. Must be ≥ `updated_since`; the window may span at most 366 days.","schema":{"type":"string","format":"date-time"}},"GeneratedSince":{"name":"generated_since","in":"query","description":"Start of the window (inclusive) on `generated_at`. Same syntax and defaults as `updated_since`.","schema":{"type":"string","format":"date-time"}},"GeneratedUntil":{"name":"generated_until","in":"query","description":"End of the window on `generated_at`. Same syntax and defaults as `updated_until`.","schema":{"type":"string","format":"date-time"}},"UpdatedSinceAlias":{"name":"updated_since","in":"query","description":"Alias of `generated_since`, accepted so one generic client can drive every list endpoint the same way. Ignored when `generated_since` is also present.","schema":{"type":"string","format":"date-time"}},"UpdatedUntilAlias":{"name":"updated_until","in":"query","description":"Alias of `generated_until`.","schema":{"type":"string","format":"date-time"}},"Limit":{"name":"limit","in":"query","description":"Page size. Default 100, maximum 500 — a larger value is silently clamped to 500 (check `page.limit`); a non-integer or a value below 1 is a 400.","schema":{"type":"integer","minimum":1,"maximum":500,"default":100}},"Cursor":{"name":"cursor","in":"query","description":"Opaque keyset cursor copied verbatim from the previous page's `page.next_cursor`. Never construct or modify one. A malformed cursor is a 400.","schema":{"type":"string"}},"FarmIdFilter":{"name":"farm_id","in":"query","description":"Restrict to one or more farms by Salesforce `Farm.Id` (the 15/18-character record id, not the business FarmId). Repeatable (`?farm_id=a&farm_id=b`) and/or comma-separated (`?farm_id=a,b`); at most 200 distinct values per request.","style":"form","explode":true,"schema":{"type":"array","items":{"type":"string"}}},"LegalEntityId":{"name":"legal_entity_id","in":"query","description":"Restrict to farms under this business `LegalEntity.LegalEntityId`.","schema":{"type":"string"}},"Country":{"name":"country","in":"query","description":"Restrict to farms whose master-data country equals this value, compared exactly as stored (e.g. `Denmark`, `DK` — whatever Salesforce supplied).","schema":{"type":"string"}},"ReportCountry":{"name":"country","in":"query","description":"Restrict to reports whose stored country snapshot (the country printed on the certificate at generation time) equals this value exactly. Note this differs from `/farms` and `/fields`, which compare the farm's current master-data country.","schema":{"type":"string"}},"FieldStatus":{"name":"status","in":"query","description":"Restrict to fields with this lifecycle status.","schema":{"type":"string","enum":["draft","submitted"]}},"FarmStatus":{"name":"status","in":"query","description":"Restrict by the farm's roll-up state: `submitted` = every field submitted (the farm is locked); `draft` = at least one field still in draft. (`source` is not applicable to farms and is ignored.)","schema":{"type":"string","enum":["draft","submitted"]}},"Source":{"name":"source","in":"query","description":"Restrict to fields whose boundary came from DigiFarm delineation or from the farmer (drawn/uploaded/cadastral).","schema":{"type":"string","enum":["digifarm","manual"]}},"SubmissionSource":{"name":"submission_source","in":"query","description":"Restrict to fields by who submitted them: `farmer` (the farmer pressed Submit) or `auto` (the system submitted them when the season closed). Draft fields have neither. Not to be confused with `source`, which is where the boundary came from.","schema":{"type":"string","enum":["farmer","auto"]}},"FarmSubmissionSource":{"name":"submission_source","in":"query","description":"Restrict by who submitted the farm: `auto` = at least one field was auto-submitted when the season closed; `farmer` = something was submitted and none of it by the system. Farms with nothing submitted match neither.","schema":{"type":"string","enum":["farmer","auto"]}},"ReportSubmissionSource":{"name":"submission_source","in":"query","description":"Restrict to certified reports by who submitted the farm they certify: `farmer`, or `auto` (generated by the system for a farm it auto-submitted when the season closed).","schema":{"type":"string","enum":["farmer","auto"]}},"Include":{"name":"include","in":"query","description":"`geometry` embeds each field's GeoJSON geometry in the list (omitted by default). A comma-separated list is accepted; `geometry` is the only known value.","schema":{"type":"string","enum":["geometry"]}},"Format":{"name":"format","in":"query","description":"`geojson` returns a GeoJSON FeatureCollection (the field attributes become each Feature's `properties`) instead of the JSON envelope, and implies `include=geometry`. The response `Content-Type` is `application/json` either way.","schema":{"type":"string","enum":["json","geojson"],"default":"json"}},"FarmIdPath":{"name":"farm_id","in":"path","required":true,"description":"Salesforce `Farm.Id`.","schema":{"type":"string"},"example":"a0B5t00000ABCDEFGH"},"FieldIdPath":{"name":"id","in":"path","required":true,"description":"Field id (UUID, app-owned).","schema":{"type":"string","format":"uuid"}},"ReportIdPath":{"name":"id","in":"path","required":true,"description":"Report id (UUID).","schema":{"type":"string","format":"uuid"}}},"responses":{"BadRequest":{"description":"`invalid_request` — a query parameter failed validation (bad date, `since > until`, window over 366 days, non-integer or zero `limit`, more than 200 `farm_id` values, malformed cursor, unknown `status`/`source`/`include`/`format` value). `details` names the offending parameter and value.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":{"code":"invalid_request","message":"updated_since must not be later than updated_until"}}}}},"Unauthorized":{"description":"`unauthorized` — no `Authorization: Bearer` header, or the token is unknown, expired or revoked.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":{"code":"unauthorized","message":"Missing, malformed, unknown, revoked or expired bearer token."}}}}},"Forbidden":{"description":"`forbidden` — the token is valid but lacks the scope this endpoint requires. `details` is `{ required_scope, token_scopes }`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":{"code":"forbidden","message":"This token does not have the \"reports:read\" scope."}}}}},"NotFound":{"description":"`not_found` — no such resource (or, for a farm, no fields exist for it). A path id that is not a well-formed UUID is also `not_found`, not `invalid_request`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":{"code":"not_found","message":"Field not found"}}}}},"RateLimited":{"description":"`rate_limited` — the per-token budget (or the equal-sized per-client budget checked before token lookup) is exhausted. Honour `Retry-After`.","headers":{"Retry-After":{"$ref":"#/components/headers/Retry-After"},"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":{"code":"rate_limited","message":"Rate limit of 600 requests per 60s exceeded."}}}}},"NotConfigured":{"description":"`not_configured` — the server lacks the storage/configuration this endpoint depends on.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":{"code":"not_configured","message":"Report PDF storage is not configured on this deployment"}}}}},"Internal":{"description":"`internal` — unexpected server error. Safe to retry with backoff.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":{"code":"internal","message":"Internal server error"}}}}}},"schemas":{"Error":{"type":"object","description":"The one error envelope every non-2xx JSON response uses.","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","enum":["unauthorized","forbidden","invalid_request","not_found","rate_limited","not_configured","internal"]},"message":{"type":"string","description":"Human-readable, English, not stable — do not parse."},"details":{"description":"Optional machine-readable detail (e.g. validation issues)."}}}},"example":{"error":{"code":"invalid_request","message":"updated_since must be before updated_until"}}},"Page":{"type":"object","description":"Keyset pagination state. Keep requesting with `cursor=next_cursor` until `has_more` is false.","required":["limit","next_cursor","has_more"],"properties":{"limit":{"type":"integer","description":"The effective page size (after clamping to 500)."},"next_cursor":{"type":["string","null"],"description":"Opaque cursor for the next page; `null` on the last page."},"has_more":{"type":"boolean"}}},"Window":{"type":"object","description":"The date window actually applied, after defaults.","required":["since","until","applied_to"],"properties":{"since":{"type":"string","format":"date-time","description":"ISO 8601 timestamp, UTC (`Z` suffix)."},"until":{"type":"string","format":"date-time","description":"ISO 8601 timestamp, UTC (`Z` suffix)."},"applied_to":{"type":"string","enum":["updated_at","last_field_updated_at","generated_at"],"description":"Which timestamp the window filtered on: `updated_at` for fields, `last_field_updated_at` for farms, `generated_at` for reports."}}},"Geometry":{"type":"object","description":"GeoJSON Geometry (RFC 7946), WGS 84 / EPSG:4326, `[longitude, latitude]` order. Field boundaries are `Polygon` or `MultiPolygon`.","required":["type","coordinates"],"properties":{"type":{"type":"string","enum":["Polygon","MultiPolygon"]},"coordinates":{"type":"array","items":{}}},"example":{"type":"Polygon","coordinates":[[[9.9312,56.1567],[9.9351,56.1567],[9.9351,56.1589],[9.9312,56.1589],[9.9312,56.1567]]]}},"Feature":{"type":"object","description":"GeoJSON Feature.","required":["type","geometry","properties"],"properties":{"type":{"type":"string","const":"Feature"},"id":{"type":["string","number"]},"geometry":{"oneOf":[{"$ref":"#/components/schemas/Geometry"},{"type":"null"}]},"properties":{"type":["object","null"],"additionalProperties":true}}},"FeatureCollection":{"type":"object","description":"GeoJSON FeatureCollection.","required":["type","features"],"properties":{"type":{"type":"string","const":"FeatureCollection"},"features":{"type":"array","items":{"$ref":"#/components/schemas/Feature"}}}},"FieldFeatureCollection":{"type":"object","description":"`GET /fields?format=geojson`: a FeatureCollection whose Features carry the Field object (minus `geometry`) as `properties`, plus the same `page`, `window` and `generated_at` as the JSON envelope as top-level foreign members.","required":["type","features","page","window","generated_at"],"properties":{"type":{"type":"string","const":"FeatureCollection"},"features":{"type":"array","items":{"type":"object","required":["type","id","geometry","properties"],"properties":{"type":{"type":"string","const":"Feature"},"id":{"type":"string","format":"uuid"},"geometry":{"$ref":"#/components/schemas/Geometry"},"properties":{"$ref":"#/components/schemas/Field"}}}},"page":{"$ref":"#/components/schemas/Page"},"window":{"$ref":"#/components/schemas/Window"},"generated_at":{"type":"string","format":"date-time","description":"ISO 8601 timestamp, UTC (`Z` suffix)."}}},"LandCoverClass":{"type":"object","description":"One land-cover class present inside the field.","required":["code","label","area_ha","pct"],"properties":{"code":{"type":"integer","description":"Class code in the scheme identified by `land_cover.scheme_id` (ESA WorldCover: 10–100)."},"label":{"type":["string","null"],"description":"English class label from the scheme, or `null` if the code is not in the scheme."},"area_ha":{"type":"number","description":"Area of this class inside the field. Hectares."},"pct":{"type":"integer","description":"Whole-number share of the field's area; the classes of one field sum to 100."}}},"LandCover":{"type":"object","description":"The field's computed land-cover composition: DigiFarm 1 m land cover where the 1 m release covers the field (national LiDAR for tree/shrub cover where available), ESA WorldCover (10 m) otherwise — `source_resolution_m` and `release_covered_area_ha` say which. The class codes are the ESA WorldCover codes in both cases. `null` on the Field only when no composition exists AND no compute has ever been requested. With a status but no composition yet (`queued`, `no_data`, `error`) the object is present with `classes: []` and every other attribute `null`.","required":["status","scheme_id","dataset_label","source","computed_at","source_resolution_m","release_covered_area_ha","fallback_reason","classes"],"properties":{"status":{"type":["string","null"],"enum":["queued","done","no_data","error"],"description":"Lifecycle of the compute job: `queued` (pending), `done` (see `classes`), `no_data` (the pipeline found no coverage — a real gap, not a bug), `error`. `null` = never requested."},"scheme_id":{"type":["string","null"],"description":"Class taxonomy the codes belong to. `esa_worldcover` for everything computed since 2026-08; `corine_l3` only on legacy rows.","example":"esa_worldcover"},"dataset_label":{"type":["string","null"],"description":"Human dataset name + vintage, e.g. `ESA WorldCover 2025`."},"source":{"type":["string","null"],"description":"Source build tag of the raster the composition was computed from (e.g. `esa-worldcover-v200/2021`, or `arla-1m/<release>+esa-worldcover-v200/2021` for the 1 m release). Changes when a field is recomputed from a new source."},"computed_at":{"type":["string","null"],"format":"date-time","description":"ISO 8601 timestamp, UTC (`Z` suffix)."},"source_resolution_m":{"type":["number","null"],"description":"Grid the composition was computed on, in metres: `1` = DigiFarm 1 m release (possibly with a WorldCover fill, see `release_covered_area_ha`), `10` = ESA WorldCover fallback. `null` = not recorded (every result computed before the 1 m release, i.e. ESA WorldCover 10 m)."},"release_covered_area_ha":{"type":["number","null"],"description":"Hectares of the area the composition describes that were mapped from the 1 m release; the rest came from ESA WorldCover. `null` when not recorded. Hectares."},"fallback_reason":{"type":["string","null"],"description":"Informational. Why the 1 m release was not used for (part of) this field, e.g. `release_pixel_limit`, `release_feature_limit`, `release_source_mismatch`, `release_unreadable`, `release_catalog_unavailable`, `release_timeout`. `null` when it was used, or on WorldCover-only rows. New values may appear without a version bump."},"classes":{"type":"array","items":{"$ref":"#/components/schemas/LandCoverClass"},"description":"Sorted by area descending; empty when no composition exists."}}},"CadastralOrigin":{"type":"object","description":"Set only when a hand-drawn field was created from a cadastral-search result that had no detected boundary. Lineage only.","required":["country","components"],"properties":{"country":{"type":"string","description":"ISO 3166-1 alpha-2 of the cadastral system searched."},"components":{"type":"object","additionalProperties":{"type":"string"},"description":"The country-specific cadastral id components the farmer searched for."}}},"CadastralParcelMatch":{"type":"object","description":"The official cadastral parcel this field's boundary was matched to (intersection > 70 % of the field's area). When present, the field's DigiFarm boundary is treated as fully productive and `land_cover` describes the parcel's *leftover* (parcel minus boundary). `geometry` (the parcel's own outline) is only included on `GET /fields/{id}`.","required":["country","source_ref","area_ha","intersection_area_ha","non_productive_area_ha"],"properties":{"country":{"type":"string"},"source_ref":{"type":"string","description":"Identifier of the cadastral source layer the parcel came from."},"area_ha":{"type":"number","description":"The parcel's own area. Hectares."},"intersection_area_ha":{"type":"number","description":"Area of (field boundary ∩ parcel). Hectares."},"non_productive_area_ha":{"type":"number","description":"`max(0, area_ha − intersection_area_ha)` — the parcel's non-productive leftover. Hectares."},"geometry":{"$ref":"#/components/schemas/Geometry"}}},"DigifarmBoundaryMatch":{"type":"object","description":"Only for uploaded fields (`origin: uploaded`): the merged DigiFarm-detected boundary/boundaries found inside the uploaded outline, treated as the productive area within it. `geometry` only on `GET /fields/{id}`.","required":["boundary_ids","area_ha","intersection_area_ha","non_productive_area_ha"],"properties":{"boundary_ids":{"type":"array","items":{"type":"string"},"description":"DigiFarm boundary ids that were merged."},"area_ha":{"type":"number","description":"The merged DigiFarm boundary's own area. Hectares."},"intersection_area_ha":{"type":"number","description":"Area of (uploaded outline ∩ merged boundary). Hectares."},"non_productive_area_ha":{"type":"number","description":"`max(0, field area_ha − intersection_area_ha)`. Hectares."},"geometry":{"$ref":"#/components/schemas/Geometry"}}},"FieldLinks":{"type":"object","description":"Absolute URLs to related resources on this API.","required":["self","land_cover_geometry","farm"],"properties":{"self":{"type":"string","format":"uri"},"land_cover_geometry":{"type":"string","format":"uri"},"farm":{"type":"string","format":"uri"}}},"Field":{"type":"object","description":"A farmer field. See the data dictionary in `docs/integration-api.md` for the meaning of every key.","required":["id","farm_id","farm_business_id","legal_entity_id","legal_entity_sf_id","membership_id","country","name","source","source_ref","is_uploaded","origin","cadastral_origin","area_ha","productive_share","productive_area_ha","non_productive_area_ha","land_cover","cadastral_parcel_match","digifarm_boundary_match","merged_field_ids","boundary_confirmed","status","submitted_at","submission_source","created_at","updated_at","links"],"properties":{"id":{"type":"string","format":"uuid","description":"Stable, app-owned field id. Upsert key."},"farm_id":{"type":"string","description":"Salesforce `Farm.Id` the field belongs to (the stable join key)."},"farm_business_id":{"type":["string","null"],"description":"Salesforce `Farm.FarmId` (business code)."},"legal_entity_id":{"type":["string","null"],"description":"Business `LegalEntity.LegalEntityId`."},"legal_entity_sf_id":{"type":["string","null"],"description":"Salesforce `LegalEntity.Id`."},"membership_id":{"type":["string","null"],"description":"Business `Membership.MembershipId`."},"country":{"type":["string","null"],"description":"Farm country from master data, as stored."},"name":{"type":["string","null"],"description":"Farmer-entered label."},"source":{"type":"string","enum":["digifarm","manual"]},"source_ref":{"type":["string","null"],"description":"Originating DigiFarm delineated-field id when `source = digifarm`."},"is_uploaded":{"type":"boolean","description":"True for a manual field created from a file upload."},"origin":{"type":"string","enum":["digifarm","drawn","uploaded","cadastral"],"description":"How the boundary was produced — a convenience derived from `source`, `is_uploaded` and `cadastral_origin`."},"cadastral_origin":{"oneOf":[{"$ref":"#/components/schemas/CadastralOrigin"},{"type":"null"}]},"area_ha":{"type":["number","null"],"description":"Boundary area. Hectares."},"productive_share":{"type":["number","null"],"minimum":0,"maximum":1,"description":"Productive share of the field, 0..1, derived as the farmer UI derives it: null until the boundary is confirmed; 1 for a confirmed DigiFarm-detected or hand-drawn field; for an uploaded field the merged DigiFarm boundary found inside it over its own area, else the Cropland share of its land cover, else null."},"productive_area_ha":{"type":["number","null"],"description":"`area_ha × productive_share` when both are present. Hectares."},"non_productive_area_ha":{"type":["number","null"],"description":"`area_ha − productive_area_ha` when both are present. Hectares."},"land_cover":{"oneOf":[{"$ref":"#/components/schemas/LandCover"},{"type":"null"}]},"cadastral_parcel_match":{"oneOf":[{"$ref":"#/components/schemas/CadastralParcelMatch"},{"type":"null"}]},"digifarm_boundary_match":{"oneOf":[{"$ref":"#/components/schemas/DigifarmBoundaryMatch"},{"type":"null"}]},"merged_field_ids":{"type":"array","items":{"type":"string","format":"uuid"},"description":"Ids of fields merged into this one (lineage; those ids no longer exist)."},"boundary_confirmed":{"type":"boolean"},"status":{"type":"string","enum":["draft","submitted"]},"submitted_at":{"type":["string","null"],"format":"date-time","description":"ISO 8601 timestamp, UTC (`Z` suffix)."},"submission_source":{"type":["string","null"],"enum":["farmer","auto"],"description":"Who submitted the field: `farmer` (pressed Submit) or `auto` (submitted by the system when the season closed — the farmer had not finished). `null` while the field is a draft. Every field submitted before this existed is `farmer`."},"created_at":{"type":"string","format":"date-time","description":"ISO 8601 timestamp, UTC (`Z` suffix)."},"updated_at":{"type":"string","format":"date-time","description":"Last modification. The list window and cursor are based on this."},"geometry":{"allOf":[{"$ref":"#/components/schemas/Geometry"}],"description":"Present on `GET /fields/{id}` always, and on lists only with `include=geometry`."},"links":{"$ref":"#/components/schemas/FieldLinks"}}},"Address":{"type":"object","required":["street","city","state","postal_code","country"],"properties":{"street":{"type":["string","null"]},"city":{"type":["string","null"]},"state":{"type":["string","null"]},"postal_code":{"type":["string","null"]},"country":{"type":["string","null"]}}},"LatestReport":{"type":"object","description":"Pointer to the farm's most recent certified report.","required":["id","generated_at","verify_url"],"properties":{"id":{"type":"string","format":"uuid"},"generated_at":{"type":"string","format":"date-time","description":"ISO 8601 timestamp, UTC (`Z` suffix)."},"verify_url":{"type":"string","format":"uri","description":"Public verification page (no login)."}}},"Farm":{"type":"object","description":"A Salesforce Farm with at least one field, plus roll-ups over its fields.","required":["farm_id","farm_business_id","legal_entity_id","legal_entity_sf_id","legal_entity_name","vat_number","membership_id","membership_name","country","address","field_count","submitted_field_count","auto_submitted_field_count","total_area_ha","submission_status","submission_source","is_locked","last_field_updated_at","last_submitted_at","latest_report","links"],"properties":{"farm_id":{"type":"string","description":"Salesforce `Farm.Id`. Upsert key."},"farm_business_id":{"type":["string","null"],"description":"Salesforce `Farm.FarmId`."},"legal_entity_id":{"type":["string","null"],"description":"Business `LegalEntity.LegalEntityId`."},"legal_entity_sf_id":{"type":["string","null"],"description":"Salesforce `LegalEntity.Id`."},"legal_entity_name":{"type":["string","null"]},"vat_number":{"type":["string","null"]},"membership_id":{"type":["string","null"],"description":"Business `Membership.MembershipId`."},"membership_name":{"type":["string","null"]},"country":{"type":["string","null"]},"address":{"$ref":"#/components/schemas/Address"},"field_count":{"type":"integer"},"submitted_field_count":{"type":"integer"},"auto_submitted_field_count":{"type":"integer","description":"Of the submitted fields, how many the system submitted when the season closed."},"total_area_ha":{"type":"number","description":"Sum of `area_ha` over the farm's fields. Hectares."},"submission_status":{"type":"string","enum":["submitted","partial","none"],"description":"`submitted` = every field submitted; `partial` = some; `none` = none."},"submission_source":{"type":["string","null"],"enum":["farmer","auto"],"description":"Who submitted the farm, rolled up from its fields: `auto` once ANY field was auto-submitted (the farmer did not finish it), `farmer` when something is submitted and none of it by the system, `null` while nothing is submitted. Use `auto_submitted_field_count` and the fields' own `submission_source` for the detail."},"is_locked":{"type":"boolean","description":"True once every field is submitted — the farm is view-only from then on. (After the season close date no farm accepts farmer writes at all, regardless of this flag.)"},"last_field_updated_at":{"type":"string","format":"date-time","description":"max(`updated_at`) over the farm's fields. The list window and cursor are based on this."},"last_submitted_at":{"type":["string","null"],"format":"date-time","description":"ISO 8601 timestamp, UTC (`Z` suffix)."},"latest_report":{"oneOf":[{"$ref":"#/components/schemas/LatestReport"},{"type":"null"}]},"links":{"type":"object","required":["self","fields"],"properties":{"self":{"type":"string","format":"uri"},"fields":{"type":"string","format":"uri","description":"`GET /farms/{farm_id}/fields`."}}}}},"FarmReportLandCoverClass":{"type":"object","description":"One land-cover class summed across the farm's fields (active scheme only). Only classes with a non-zero area appear.","required":["code","label","area_ha","pct"],"properties":{"code":{"type":"integer","description":"Class code in `summary.land_cover.scheme_id`."},"label":{"type":["string","null"],"description":"English class label from the scheme, or `null` if the code is not in it."},"area_ha":{"type":"number","description":"Sum of this class's area over the fields counted in `fields_with_land_cover`. Hectares."},"pct":{"type":"integer","description":"Whole-number share of `covered_area_ha`, computed with the largest-remainder method so the classes sum to exactly 100."}}},"FarmReportLandCover":{"type":"object","description":"Land cover summed across the farm. Only compositions in the ACTIVE scheme (`scheme_id`) are summed, so codes are comparable; a field whose composition is in another (legacy) scheme is excluded from `classes` and counted under `fields_without_land_cover` — its own `land_cover` is still present verbatim in `fields[]`.","required":["scheme_id","dataset_label","dataset_labels","fields_with_land_cover","fields_without_land_cover","covered_area_ha","classes"],"properties":{"scheme_id":{"type":"string","description":"The app's active class taxonomy.","example":"esa_worldcover"},"dataset_label":{"type":["string","null"],"description":"The dataset label every counted field shares (e.g. `ESA WorldCover 2025`); the scheme's default label when no counted field carries one (legacy rows); `null` when the counted fields carry DIFFERENT labels (some at 1 m, some on WorldCover) — see `dataset_labels`. Before 1.3.0 the default label was returned in that case, which would now be untrue."},"dataset_labels":{"type":"array","items":{"type":"string"},"description":"Every distinct dataset label among the counted fields, sorted; the scheme's default label alone when none carries one."},"fields_with_land_cover":{"type":"integer","description":"Fields with a computed composition in `scheme_id`."},"fields_without_land_cover":{"type":"integer","description":"All other fields (never computed, pending, `no_data`, `error`, or a legacy scheme)."},"covered_area_ha":{"type":"number","description":"Sum of all class areas below — the area the composition actually describes. For a field with a `cadastral_parcel_match` the composition covers the parcel's leftover, so this is not simply the sum of field areas. Hectares."},"classes":{"type":"array","items":{"$ref":"#/components/schemas/FarmReportLandCoverClass"},"description":"Sorted by `area_ha` descending (then `code`). Empty when `covered_area_ha` is 0."}}},"FarmReportSummary":{"type":"object","description":"Roll-up over every field of the farm, computed from the same `Field` objects returned in `fields[]`.","required":["field_count","submitted_field_count","auto_submitted_field_count","draft_field_count","boundary_confirmed_count","total_area_ha","productive_area_ha","non_productive_area_ha","unclassified_area_ha","land_cover","origins","land_cover_status"],"properties":{"field_count":{"type":"integer","description":"Every field of the farm (≥ 1)."},"submitted_field_count":{"type":"integer","description":"Fields with `status: submitted`."},"auto_submitted_field_count":{"type":"integer","description":"Of those, the fields with `submission_source: auto`."},"draft_field_count":{"type":"integer","description":"`field_count − submitted_field_count`."},"boundary_confirmed_count":{"type":"integer","description":"Fields with `boundary_confirmed: true`."},"total_area_ha":{"type":"number","description":"Sum of `area_ha` over all fields (a `null` area counts as 0). Hectares."},"productive_area_ha":{"type":"number","description":"Sum of the fields' `productive_area_ha`. Hectares."},"non_productive_area_ha":{"type":"number","description":"Sum of the fields' `non_productive_area_ha`. Hectares."},"unclassified_area_ha":{"type":"number","description":"Sum of `area_ha` over fields whose `productive_share` is `null` (boundary not confirmed, or an uploaded field whose productive part is not yet known). `productive + non_productive + unclassified = total` up to 4-decimal rounding. Hectares."},"land_cover":{"$ref":"#/components/schemas/FarmReportLandCover"},"origins":{"type":"object","description":"Field counts by `origin`.","required":["digifarm","drawn","uploaded","cadastral"],"properties":{"digifarm":{"type":"integer"},"drawn":{"type":"integer"},"uploaded":{"type":"integer"},"cadastral":{"type":"integer"}}},"land_cover_status":{"type":"object","description":"Field counts by `land_cover.status`; `none` = `land_cover` is `null` (never requested).","required":["done","queued","no_data","error","none"],"properties":{"done":{"type":"integer"},"queued":{"type":"integer"},"no_data":{"type":"integer"},"error":{"type":"integer"},"none":{"type":"integer"}}}}},"FarmReport":{"type":"object","description":"One farm's complete report: the Farm, a summary over all of its fields, the fields themselves and the latest certificate pointer.","required":["generated_at","farm","summary","fields","latest_report","links"],"properties":{"generated_at":{"type":"string","format":"date-time","description":"Server time at which the report was assembled."},"farm":{"$ref":"#/components/schemas/Farm"},"summary":{"$ref":"#/components/schemas/FarmReportSummary"},"fields":{"type":"array","items":{"$ref":"#/components/schemas/Field"},"description":"Every field of the farm, ordered by (`created_at`, `id`) ascending. `geometry` only with `include=geometry`; the match objects never carry geometry here (use `GET /fields/{id}`)."},"latest_report":{"oneOf":[{"$ref":"#/components/schemas/LatestReport"},{"type":"null"}],"description":"Identical to `farm.latest_report`, repeated at the top level for convenience."},"links":{"type":"object","required":["self","farm","fields"],"properties":{"self":{"type":"string","format":"uri"},"farm":{"type":"string","format":"uri","description":"`GET /farms/{farm_id}`."},"fields":{"type":"string","format":"uri","description":"`GET /farms/{farm_id}/fields`."}}}}},"Report":{"type":"object","description":"A certified per-farm submission report. Immutable once generated.","required":["id","farm_id","farm_business_id","legal_entity_id","farmer_name","farm_label","country","locale","field_count","total_area_ha","status","submission_source","supersedes_id","superseded_by","generated_at","verify_url","pdf_url","links"],"properties":{"id":{"type":"string","format":"uuid","description":"Report id. Upsert key."},"farm_id":{"type":"string","description":"Salesforce `Farm.Id`."},"farm_business_id":{"type":["string","null"]},"legal_entity_id":{"type":["string","null"]},"farmer_name":{"type":["string","null"],"description":"Farmer (membership / legal entity) name as printed on the certificate."},"farm_label":{"type":["string","null"],"description":"Farm label as printed on the certificate (the business FarmId)."},"country":{"type":["string","null"]},"locale":{"type":["string","null"],"description":"Locale the report was generated in (`en`, `da`, `de`, `nl`, `sv`, `fr`)."},"field_count":{"type":["integer","null"]},"total_area_ha":{"type":["number","null"],"description":"Sum of field areas at generation time. Hectares."},"status":{"type":"string","enum":["certified","superseded"],"description":"`certified`, or `superseded` once a newer certified report exists for the farm (a re-issue after a land-cover update). Derived at read time; a superseded report is never modified and still verifies as signed.","example":"certified"},"submission_source":{"type":"string","enum":["farmer","auto"],"description":"Who submitted the farm this report certifies: `farmer`, or `auto` (the system generated it for a farm it auto-submitted when the season closed — the farmer had not finished and did not review it). Every report generated before this existed is `farmer`."},"supersedes_id":{"type":["string","null"],"format":"uuid","description":"Id of the earlier report this one supersedes. Signed into this report's snapshot, so it is tamper-evident. `null` on an ordinary report. An integrator learns of a re-issue from the NEW row (it appears in the `generated_at` window); the old row's `status` flips without appearing again."},"superseded_by":{"type":["string","null"],"format":"uuid","description":"Id of the newest report that supersedes this one; `null` while this is the farm's latest."},"generated_at":{"type":"string","format":"date-time","description":"The list window and cursor are based on this."},"verify_url":{"type":"string","format":"uri","description":"Public verification page for this certificate (no login)."},"pdf_url":{"type":"string","format":"uri","description":"`GET /reports/{id}/pdf` on this API (token required)."},"links":{"type":"object","required":["self","farm"],"properties":{"self":{"type":"string","format":"uri"},"farm":{"type":"string","format":"uri","description":"`GET /farms/{farm_id}`."}}}}},"ReportDetail":{"allOf":[{"$ref":"#/components/schemas/Report"},{"type":"object","required":["report_data"],"properties":{"report_data":{"type":"object","additionalProperties":true,"description":"The immutable snapshot the certificate was generated and signed from, verbatim. Shape is versioned by its own `schemaVersion` key (camelCase — it is stored, not serialized by this API); v2 carries `fields[]` (id, areaHa, productiveShare, landCover, flags), `expectedFieldCount`, `expectedTotalAreaHa`, `farmName`, `farmDetails`, `timeZone`."}}}]},"LandCoverGeometry":{"type":"object","required":["field_id","source","computed_at","bbox","render","geojson"],"properties":{"field_id":{"type":"string","format":"uuid"},"source":{"type":"string","description":"Source dataset + vintage that produced this (matches `land_cover.source`)."},"computed_at":{"type":"string","format":"date-time","description":"ISO 8601 timestamp, UTC (`Z` suffix)."},"bbox":{"type":"array","prefixItems":[{"type":"number"},{"type":"number"},{"type":"number"},{"type":"number"}],"minItems":4,"maxItems":4,"description":"`[minLon, minLat, maxLon, maxLat]`."},"render":{"type":"string","enum":["vector","raster"],"description":"`vector` = dissolved polygons in `geojson`."},"geojson":{"allOf":[{"$ref":"#/components/schemas/FeatureCollection"}],"description":"One Feature per land-cover class present, each with `properties.code`."}}},"Me":{"type":"object","required":["token","environment","api_version","server_time"],"properties":{"token":{"type":"object","required":["id","name","client","scopes","token_prefix","expires_at"],"properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"client":{"type":["string","null"]},"scopes":{"type":"array","items":{"type":"string","enum":["fields:read","reports:read"]}},"token_prefix":{"type":"string","description":"First 12 characters of the token, for identification.","example":"mrv_live_Ab3d"},"expires_at":{"type":["string","null"],"format":"date-time","description":"ISO 8601 timestamp, UTC (`Z` suffix)."}}},"environment":{"type":"string","enum":["production","development"],"description":"Which data set this server serves."},"api_version":{"type":"string","const":"v1"},"server_time":{"type":"string","format":"date-time","description":"ISO 8601 timestamp, UTC (`Z` suffix)."}}}}}}