Get Audit Trail Task
A render that stops without reporting. A
generate_audit_trail_pdftask stillpendingorprocessing15 minutes after it was created is reported asfailed— that is the hard limit the renderer job runs under, so it has already been stopped. The window starts when the task is created, so time spent queued counts toward it. Ask for a new render.
Poll the status of an async DDS task — the record-less status endpoint returned by Create Audit Trail.
POST /regulations/eudr/audit-trail is asynchronous: it returns 202
with a dds_record_task envelope and a Location header pointing here. The
worker then resolves the filter, runs EUDR / art9 / art10 / hazard /
infrastructure assessments, and inserts the dds_record + version 1
atomically — the record only appears once this task reaches completed.
Poll this endpoint until the task is terminal.
This handler is org-scoped: the task is only visible to the organisation that
created it (ctx.effectiveOrgIds). Polling with a key from a different org
returns 404 — use the same key / x-acting-as you created the task with.
▶Status lifecycle
status | Meaning |
|---|---|
pending | Enqueued, worker not yet started |
processing | Worker running (plot resolution, assessments, insert) |
completed | Record + v1 written; result carries the new ids |
failed | Aborted before any rows were written; see error_message. A render past the window above is also reported here, whether or not its worker got to write anything |
▶Response attributes
| Field | Type | Description |
|---|---|---|
operation | "create_record" | "create_version" | "submit" | "generate_audit_trail_pdf" | What the task does |
status | enum | See lifecycle above |
error_message | string | null | Failure reason when status: "failed" (e.g. "Filter matched no plots"). For a render aged out by the window above, this is written by us from the task's age, not by the worker — which by then has usually stopped without saying anything |
result | object | null | Set only on completed. For create_record: { record_id, version_id, version_number, records[] } — see below. For create_version: { version_id, version_number }. For submit: adds the traces_* / submitted_at block. For generate_audit_trail_pdf: see the row below |
end_date, include_unaccounted_plots, rerun_deforestation | — | Echo of the originating request's parameters |
dds_record_id | uuid | null | The record the task belongs to. Stamped from the 202 onward for every operation, including a v1 create, whose record id is minted before dispatch. Null only on tasks enqueued before that was the case |
created_at, updated_at | ISO 8601 | Task timestamps |
▶result for generate_audit_trail_pdf
result for generate_audit_trail_pdfcontent_type and size_bytes describe the PDF; each sibling artefact
repeats that pair under its own prefix. The other unprefixed fields describe
the render as a whole.
| Field | Description |
|---|---|
content_type, size_bytes | The PDF |
dds_hash | Report fingerprint the render was keyed on |
cache_hit | true when an unchanged version reused the stored render |
version_id | The version rendered |
download_url | Path to the PDF download route |
package_content_type, package_size_bytes, package_download_url | The export ZIP |
html_content_type, html_size_bytes, html_download_url | The interactive HTML |
geojson_content_type, geojson_part_count, geojson_total_size_bytes, geojson_dds_hash, geojson_download_url | The TRACES GeoJSON. part_count because it is the only multi-part artefact; total_size_bytes is the sum across its parts |
Two ways a field goes missing, and they are different:
- A whole block is absent when its artefact does not exist. The
interactive HTML lags the task's completion, and
geojson_*is absent on a task that completed before that export existed. - Every
*_download_urlis absent, including the PDF's, when the task is missing either the record id or the version id — the route is built from both. The metadata still describes real artefacts; fetch them through the record's Export routes.
The *_download_url values are route paths, not files. Follow one to get a
short-lived signed link.
▶result.records — the auto-split per-group list (create_record)
result.records — the auto-split per-group list (create_record)Create auto-splits the resolved plot set into one record per distinct
(country_code, commodity) (EUDR records are single-country /
single-commodity). result.records is the authoritative list of what
was produced; the top-level result.record_id / version_id /
version_number are a backward-compatible pointer to the first
successfully created group — so the top-level version_id is always a
real id on a completed task (a task only completes if ≥1 group was
created; if every group failed the task is failed with result: null).
The pointer deliberately skips failed groups: in the rare multi-group split
where group 0 failed but a later group succeeded, the top-level pointer
points at that later record, while group 0 (and the id minted on the 202)
appears in result.records with status: "failed". Single-group callers
can keep reading the top-level fields; multi-record callers should read
result.records for the per-group truth.
| Field | Type | Description |
|---|---|---|
record_id | uuid | The group's DDS record. The first group reuses the id from the 202 |
version_id | uuid | null | The group's v1; null when the group failed |
version_number | int | 1 on create |
country_code | string | The group's country (part of the grouping key) |
commodity | string | The group's normalised commodity (part of the grouping key) |
status | "created" | "failed" | Per-group outcome — failures are isolated, so one bad group doesn't sink the rest |
error_message | string | Present only when status: "failed" |
A single homogeneous plot set yields exactly one entry (and the legacy
top-level pointer). Synchronous body errors (Zod, incomplete operator,
unsupported separate_by) are returned as 400 by the create call itself,
not here.
Note: a common
failedreason is"Filter matched no plots"— the createfilterresolved zero plots visible to the caller. The DDScommodityfilter is alias-aware (e.g.woodmatchestimber,palmmatchespalm oil), but it still has to match plots you've actually ingested. Check the commodity / country of your staged plots.
Required scope:
eudr:read