Overview
You send a plot geometry, the deforestation analysis runs automatically, and you read the result as JSON and download the plot report as PDF. No article or supplier is needed — a plot with a commodity group is enough.Permissions
Key mechanism, base URL and the general status codes are in the Introduction; how to create a key is under Settings → API Keys. Plots exist in the EUDR module only.plots:write covers everything; plots:read is enough to read the result and download the report.
In a customer workspace, the report returns
403 with EUDR compliance module is not enabled
unless the EUDR module is enabled for the user the key acts as (a personal key: its owner; a company
key: the workspace’s highest-ranking active user). The result JSON has no such check.Creating a plot
POST /api/v1/plots creates one plot and starts its analysis. All fields are in the
endpoint reference; what an integration needs to know:
geojsonis required (see Geometry).commodityGroupis required unless you sendsupplierArticleIds: one ofcattle,cocoa,coffee,oil_palm,rubber,soya,wood. The API also acceptsnon_relevant(listed in the error message); do not send it for a plot you want analyzed. WithsupplierArticleIds, the group is then derived from the articles.- For
wood,speciesis required — each entry withcommonNameandscientificName. - Put your own plot reference in
name(see Idempotency). country(ISO 3166-1 alpha-2, e.g.BR): without it (or with a value that does not resolve to a country), the low-risk skip never applies and the plot is always analyzed.
Geometry
- Accepted:
Polygon,MultiPolygon,PointandMultiPoint— as a bare geometry or as aFeature. Coordinates in WGS84, order[longitude, latitude]; an altitude (third value) is accepted but not stored. Coordinates outside longitude ±180 / latitude ±90 are rejected; nothing is saved. - One request creates one plot. A
FeatureCollectionis rejected — send each feature as its own request. Other types (LineString,GeometryCollection, …) are rejected too. - When
sizeis given, aPointorMultiPointis only accepted up to 4 ha (20,000 ha whencommodityGroupiscattle); above that the EUDR requires a polygon. Withoutsizethere is no area check.
Quality checks
Before storing, the API runs the same geometry checks as the import in the app and stores the result:
Removing a hole — including one the self-intersection repair encloses — makes the excluded area
part of the plot: the plot gets larger. The API never swaps latitude and longitude. The create
response lists the codes above in
warnings ([{ "code": … }]); rounding, dropped altitude, removed
duplicate points and closed or reoriented rings are not listed. On a deduplicated answer warnings is
always empty, because that request stored nothing.
Idempotency
If you send the same plot again — samename, same country, same geometry (compared after the quality checks) and same
supplierArticleIds — the API creates no second plot and starts no second analysis; it answers
with the stored plot and "deduplicated": true. Name and country are compared ignoring case, leading
and trailing spaces, and repeated spaces. Other fields of a repeat, such as commodityGroup or size,
are not applied. The response carries "updated": true when producer, production dates or species of
the repeat were applied, otherwise false; the field is absent when a new plot was created. A repeat of a plot stored before these checks
existed is recognised too: the geometry exactly as sent is compared as well.
Checking a geometry without creating a plot
POST /api/v1/plots/validate takes the same body as create and runs the same checks, but writes
nothing — no plot, no analysis (a dry run). plots:read is enough, and commodityGroup is optional.
A request that create would refuse with a code gets 200 with valid: false and that code; a body
that is not JSON is a 400. valid says whether create would accept the request, apart from the
points listed under “Not checked” below. For a polygon with one hole, written with 6 decimals:
geometry is the geometry create would store, measuredAreaHa its area — 3.1 ha instead of the
2.68 ha of the polygon with its hole; null for points. With valid: false, errors holds the code and message create would answer,
geometry and measuredAreaHa are null, and precision is null if the request was refused before
the precision was measured. The dry run gives the point area cap and an invalid size a code
(plot_point_area_too_large, plot_size_invalid); create answers these without one. Not checked:
whether commodityGroup is missing without supplierArticleIds (create answers
plot_commodity_group_required), whether the supplierArticleIds belong to your company, and whether
the same plot already exists.
Polling the status
Poll every 15 to 30 seconds while the status is
pending or in_progress. The app applies no
per-key rate limit to these endpoints.
If the analysis is failed or skipped, you can have the plot analyzed again in the app with
Re-analyze (see Manage Plots). After Re-analyze, the status keeps
its previous value until the analysis starts.
Reading the result
analysis holds the last stored result. It is null when none was ever stored or after the
geometry changed. While a re-analysis is running (in_progress) or after a re-analysis failed, it can
still hold the previous result — compare assessedAt. The texts are English and identical to the
plot report.
riskLevel values may be added; treat a value you do not know as needing review. The
evidence[].dataset names are stable (JRC GFC 2020, Hansen GFC, GFW alerts,
JRC TMF AnnualChange, and JRC GFT 2020 for wood only); measurementStatus, observation and
relevance are human-readable and their wording may change — do not match on them.
Risk levels
The legacy numeric field
deforestationRiskResult is 0 low (also set for exempt), 1 high, 2
moderate, or null for no result (pending, skipped, failed including INVALID); during a
re-analysis or after a failed re-analysis it can still hold the previous value. Base your evaluation on analysisStatus and analysis.
Plot report (PDF)
GET /api/v1/plots/{id}/report returns the plot report as a PDF attachment. It is English and
carries the same evidence rows as analysis.evidence. The file name is plot-report-<name>.pdf, where
every character other than letters, digits, _ and - becomes _ (plot-report-plot.pdf without a
name).
Error codes
Rejected requests create nothing. The body holdserror and, in the cases below, a machine-readable
code:
plot_geometry_too_many_members, plot_geometry_bbox_spread_too_wide and
plot_geometry_area_too_large carry limit and actual in the same unit (parts, degrees, hectares);
split into several plots. For plot_geometry_too_many_vertices, simplify the geometry. These answer
without a code: 400 when the body is not JSON; 400 when a Point or MultiPoint is above the area
cap for its size (see Geometry); 400 when size is not a finite number ≥ 0; 403 when
a supplier article does not belong to your company.
Recipe: from GeoJSON to report
1
Create the plot
201 with the plot under created and warnings (empty here). Take
created.id; on a repeat the response carries "deduplicated": true.2
Poll until the analysis is done, then read the result
Every 15 to 30 seconds, until
analysisStatus is no longer pending or in_progress; the result
is then in analysis:3
Download the report