Plot Ingestion
End-to-end recipe for ingesting plot geometry the "upload first,
validate later" way: a customer ships plot polygons without paying for
any validation up front, inspects the staged plots in tabular and
geo+json form, then opts in to core + EUDR assessments via the
ingestion endpoint, and finally kicks off deforestation metrics — all
keyed by a single asset_task_id.
Use this when plots arrive ahead of any compliance decision and you want to review what staged before spending on assessments or metrics. The sequence is shaped around that deferral: upload cheaply (no validation), inspect, then opt in to assessments and metrics as separate keyed calls — so cost is only incurred once you've decided the plots are worth validating. For an upload that processes metrics in one call, see Quick Ingestion; for facility/supplier uploads, see Facility / Supplier Ingestion.
▶Endpoint map
| Step | Method | Path | Threads to next |
|---|---|---|---|
| 01 | POST | /ingestions/assets (location_type: plot, no assessments) | plot_lifecycle_task_id, signed upload_url |
| 01b | PUT | {upload_url} — the signed URL from step 01 (raw file bytes) | (uploads the bytes; no API key) |
| 02 | GET | /ingestions/{task_id} (poll until staged) | — |
| 03 | PUT | /ingestions/assets?filter[assets.task_id]=eq:{task_id} (include_core:true, include_eudr:true) | opts in to assessments |
| 04 | GET | /ingestions/assets/{task_id}?include=normalised_data,assessments | table view (JSON) |
| 05 | GET | /ingestions/assets/{task_id} with Accept: application/geo+json | map view (FeatureCollection) |
| 06 | PUT | /ingestions/assets?filter[assets.task_id]=eq:{task_id} (metrics:["deforestation"]) | plot_lifecycle_metrics_task_id |
| 07 | GET | /ingestions/{metrics_task_id} (poll until terminal) | — |
| 08 | GET | /metrics/plots/deforestation (filtered by the same task) | deforestation time-series |
Step 01b is the signed-URL byte PUT — an explicit HTTP request, not a
docs-UI action. Step 01 returns the signed URL in
meta.client_actions[0].href (mirrored on data.attributes.upload_url);
PUT the raw file bytes to it with the headers from the descriptor. The task
stays pending until the upload finalises, which is what step 02 waits for.
See 01 Upload Plots for the descriptor and the
exact PUT headers.
▶Required scopes
| Scope | Used by |
|---|---|
ingestions:write | Steps 01, 03, 06 (upload, assessments opt-in, metrics) |
ingestions:read | Steps 02, 04, 05, 07 (poll + read staged assets) |
metrics:read | Step 08 (deforestation metrics) |
▶Upload file format
A file of plot geometry — one plot per row/feature, with a polygon
geometry and a commodity_type. Supported: CSV, GeoJSON / NDJSON, Parquet,
GeoPackage, Shapefile (ZIP), .xlsx, .xls (up to 100 MB). ZIP-wrapped
formats need an explicit filename so auto-detection routes them
correctly. See Asset Upload for the full
column reference and per-format rules.
▶Variables exchanged
plot_lifecycle_task_id— set by step 01, read by every subsequent step.plot_lifecycle_metrics_task_id— set by step 06 (equalsplot_lifecycle_task_idwhen the filter fast-path reuses the existing task).plot_lifecycle_poll_retries/plot_lifecycle_metrics_poll_retries— used by the polling helper to bound retries.
▶Why this is a workflow, not a per-endpoint test
The point isn't to verify any single endpoint — those are covered in
Tests/Emulated/Ingestion/ and Tests/Emulated/Locations/. This
collection exercises the composition: the post-upload assessment
path reaches the same locations the upload created, the
results endpoint surfaces both formats, and metrics dispatch against
the resolved task. Treat it as runnable documentation.