EUDR Audit Trail From Tagged Facilities

End-to-end recipe that goes from a facility upload to an exported EUDR DDS report — where a tag supplied on the upload is the key that binds the upload to the audit record.

Facility upload, tag-driven selection. This workflow uploads location_type: facility assets, and every upload must carry a tag. That same tag — not a task id — is what the audit-record create filters on (filter.tag). The tag is the through-line: apply it at upload, select by it at create.

Why a tag (not a task id)?

The sibling Plots-Only workflow binds the record to a single upload via filter[assets.task_id]. That is fine when one upload == one record. A tag is the better key when:

  • the batch spans multiple uploads (tag them all the same, select once);
  • you want a stable, human-meaningful selector (q2-2026-cocoa) rather than an opaque task UUID;
  • you re-upload / append over time and want the record's scope to follow the tag.

Tags applied to the asset_task at upload propagate to the resolved plots, so filter: { "tag": { "eq": "…" } } selects exactly the plots under every upload that carried that tag.

How a facility resolves to plots

The DDS audit trail is built from plots. A facility upload resolves to its underlying plots via its supply shed, and the upload's tag rides through to those plots. So a tagged facility upload feeds the audit record exactly the plots beneath it.

Endpoint map

StepMethodPathThreads to next
01POST/ingestions/assets (location_type: facility, with a tags array)fac_task_id, fac_tag
02GET/ingestions/{task_id} (poll until staged)—
03PUT/ingestions/assets?filter[assets.task_id]=eq:{task_id} (metrics:["deforestation"])fac_metrics_task_id
04GET/ingestions/{metrics_task_id} (poll until terminal)—
05POST/regulations/eudr/audit-trail (select by tag: filter: { "tag": { "eq": "{{fac_tag}}" } })fac_create_task_id
06GET/regulations/eudr/audit-trail/tasks/{create_task_id} (poll until complete)fac_record_id
07GET/regulations/eudr/audit-trail/{record_id}/report(built DDS report)
08—Render a standalone HTML report (Bruno-side preview)—
09GET/regulations/eudr/audit-trail/{record_id}/audit-trail/htmlsigned download URL
10POST/regulations/eudr/audit-trail/{record_id}/authorisationsclears authorization_missing
11POST/regulations/eudr/dds/{record_id}/submitfac_submit_task_id
12GET/regulations/eudr/audit-trail/tasks/{submit_task} (poll until complete)TRACES identifiers

Omitting the tag breaks the workflow — step 05 selects by it. Steps 10–12 file the record with EU TRACES — the end of the customer's flow. Submit files only the compliant supply base and requires a live authorisation for the current version (step 10).

Variables exchanged

  • fac_task_id — set by step 01 (the upload); read by steps 02, 03.
  • fac_tag — set by step 01 (the tag applied to the upload); read by step 05 as the selection filter. This is the binding key.
  • fac_metrics_task_id — set by step 03; read by step 04.
  • fac_create_task_id — set by step 05; polled in step 06.
  • fac_record_id — set by step 06 from result.records[0].record_id; read by steps 07–08.
  • fac_report_html — set by step 08 (the rendered HTML string).
  • fac_*_poll_retries — used by the polling helper to bound retries.

Why this is a workflow, not a per-endpoint test

It exercises the composition: a tagged facility upload flows (facility → shed → plot) into an audit record selected purely by its tag, and the resulting DDS report is rendered to a shareable HTML page. Treat it as runnable documentation.