EU Deforestation Regulation (EUDR)

Build an audit trail and file it as the Due Diligence Statement (DDS) the EUDR requires for placing in-scope commodities on the EU market. You assemble and refine an audit-trail record from the plots and deforestation assessments you already hold in Epoch, then submit that record β€” filing it as a DDS with the EU TRACES portal on your behalf.

All endpoints are under /regulations/eudr.

The core idea: audit record β†’ DDS

There are two surfaces, and the difference is just lifecycle state:

  • Audit Trail (/audit-trail/*) β€” the working draft. You create a record from a set of plots, refine it (exclude plots, add justifications, set the operator and commodity blocks, manage suppliers and report fields), cut immutable versions, and export a preview report. Nothing here is filed.
  • DDS (/dds/*) β€” the filed artifact. When you submit an audit record's current version it is sent to TRACES and becomes a DDS, appearing in the submitted lists.
build & refine                    file                      read back
──────────────                    ────                      ─────────
POST /audit-trail  ──refine──▢  POST /dds/:id/submit  ──▢  GET /dds
  (or fast path)                                           GET /dds/:id

Two ways to create a record

PathWhen to use itHow
Fast path"I just uploaded plots/facilities and want the audit record built automatically." Best for straight-through, one-commodity uploads.Set create_audit_trail: true (with metrics: ["deforestation"]) on the ingestion upload. The worker auto-creates the record once processing finishes; poll the ingestion task's audit_trail_task_id.
Explicit path"I want to choose exactly which plots go in, supply the operator/commodity details up front, or split one upload into several records."Create Audit Trail β€” POST /audit-trail with a filter selecting the plots plus optional operator, commodity, and grouping dimensions.

Both paths produce the same kind of record and converge on the same audit-trail and DDS endpoints. The fast path uses the org's default operator and an empty commodity block (set the commodity via Update DDS Record before submit). Record creation is asynchronous in both cases β€” you receive a dds_record_task; poll Get Audit Trail Task until it completes and carries the new record_id.

For runnable, end-to-end recipes see the EUDR Workflows collection (Fast Path from Plots / Facilities, and the Comprehensive explicit walkthrough).

Typical client journey

  1. Get plots in with a deforestation run β€” via ingestion (fast path) or any earlier upload.
  2. Create the audit record β€” fast path automatically, or POST /audit-trail with an explicit plot filter.
  3. Refine it β€” exclude irrelevant plots, attach justifications / compliance overrides, set the operator + commodity blocks, pin suppliers, add report data fields. Every edit is captured in the append-only Audit Log.
  4. Preview β€” export the Report (JSON or GeoJSON) to review the package before filing.
  5. Submit β€” record the operator's Authorisation, then Submit DDS. The record becomes a filed DDS.
  6. Reprocess when sourcing changes β€” Reprocess cuts a new version against fresh assessments / a new end_date.

What's in this section

Folder / endpointWhat it's for
Create Audit TrailStart a new audit record from a plot filter (the explicit path)
Preview Audit Trail SizeCount the plots a create would resolve, before committing to the run
TasksPoll async create/version/submit tasks β€” one by id (Get Audit Trail Task) or the org-wide feed (List All Audit Trail Tasks)
Audit TrailThe working surface β€” read, refine, version, and report on a record
Due Diligence StatementThe filed surface β€” submit a record and read back submitted DDS records

Access & scoping

  • Reference lookups only: eudr:reference permits GET /regulations/eudr/scope, /scope/entries and /species. It grants no audit-trail or DDS access.
  • Scopes: eudr:read for reads (including the reference lookups), eudr:write for create/edit/submit.
  • Multi-org: a record is visible only to the org that owns it (dds_record.organization_id ∈ effectiveOrgIds); records from another org return 404.