202 Accepted rather than an immediate result. Understanding why — and how to work with the asynchronous job and webhook system — is essential before you build a production integration.
Why 202 Accepted?
Two operations at the heart of the compliance pipeline cannot complete in a single HTTP round-trip: Satellite deforestation screening. When you submit GeoJSON polygons, AgriBackup dispatches each feature to the Copernicus Data Space Ecosystem (CDSE) for analysis against Sentinel-2 imagery. Depending on imagery availability and the number of features, screening can take seconds to minutes. Holding the HTTP connection open for that duration is impractical for enterprise batch volumes. Hedera DLT anchoring. Anchoring a batch, shipment link, or DDS to the Hedera Hashgraph requires waiting for network consensus. While Hedera’s finality is fast (typically 3–5 seconds), the API cannot return a200 OK before the transaction ID is confirmed on-chain — doing so would allow you to build compliance logic on a transaction that might never reach consensus.
The endpoints that trigger one or both of these operations return 202 Accepted immediately, with a job ID you use to track progress:
| Endpoint | Async reason |
|---|---|
POST /api/v1/enterprise/eudr/polygons | Satellite screening + Hedera anchoring |
POST /api/v1/enterprise/eudr/batches | Hedera anchoring + Copernicus risk assessment |
POST /api/v1/enterprise/eudr/shipments/link | Hedera smart contract execution |
POST /api/v1/enterprise/eudr/declarations/dds | Hedera land tenure anchoring + TRACES NT submission |
POST /api/v1/enterprise/eudr/reports/archive | Bulk ZIP compilation |
The 202 response payload
Every async endpoint returns aJobAcceptedResponse body and a Location header:
The unique ID you use to poll job status. Example:
job_998877Always
PENDING at acceptance time.Advisory estimate of how long before the job completes or reaches the next phase.
ISO-8601 timestamp of when the job was accepted.
Location response header points directly to the job status URL, for example:
Polling the job endpoint
If you prefer polling over webhooks, callGET /api/v1/enterprise/eudr/jobs/{jobId} repeatedly. The response includes a Retry-After header when the job is still in progress, telling you how many seconds to wait before the next poll:
Job phases
Jobs move through the following phases in order:| Phase | Description |
|---|---|
IMPORTING | Records are being ingested and validated |
ANALYZING | Copernicus satellite screening is running |
ANCHORING | Hedera DLT anchoring is in progress |
GENERATING_CERTS | DDS XML or archive ZIP is being compiled |
COMPLETED | Job finished successfully |
FAILED | Job terminated with errors — check the errors array |
Webhooks
Webhooks are the recommended way to react to async completion events in production. Rather than polling, you register an HTTPS endpoint and AgriBackup delivers a POST payload to it the moment each event fires.Registering a webhook
CallPOST /api/v1/enterprise/eudr/webhooks with the URL you want to receive events and the event types you want to subscribe to:
signingSecret at registration time. Store this secret securely — you use it to verify every incoming payload.
Webhook event types
| Event | Fired when |
|---|---|
polygon.verified | Satellite screening completes and the polygon receives a compliance verdict |
batch.risk_assessed | A batch finishes Hedera anchoring and risk assessment |
shipment.linked | The Hedera smart contract confirms a batch-to-shipment link |
dds.submitted | A DDS has been sent to TRACES NT |
dds.validated | TRACES NT confirms the DDS is valid |
dds.rejected | TRACES NT rejects the DDS — the payload body contains the rejection reason |
job.failed | Any async job terminates in the FAILED phase |
report.ready | A bulk archival ZIP is ready for download |
Verifying webhook payloads
AgriBackup signs every outbound webhook with HMAC-SHA256 using the signing secret you received at registration. The signature is sent in theX-AgriBackup-Signature header as a hex-encoded digest of the raw request body. Verify it before processing the payload:
Dead-letter queue
If AgriBackup cannot deliver a webhook after repeated retries (for example, your endpoint is down), the event moves to the dead-letter queue (DLQ). Retrieve permanently failed events withGET /api/v1/enterprise/eudr/webhooks/dlq and replay individual or bulk events back to your primary endpoint with the replay endpoints.
Async flow sequence
The following diagram illustrates the full asynchronous flow for polygon ingestion:- You POST the polygon payload and immediately receive
202 Acceptedwith ajobId. - AgriBackup queues satellite screening with Copernicus CDSE.
- You can optionally poll
GET /jobs/{jobId}— theRetry-Afterheader guides your polling interval. - Once screening completes, AgriBackup anchors the results on Hedera and waits for consensus.
- On consensus, the job moves to
COMPLETEDand AgriBackup delivers thepolygon.verifiedwebhook to your registered endpoint.
Idempotency keys
Mutating endpoints that are either asynchronous or expensive to retry accept anIdempotency-Key header. Pass a unique string per logical operation — a UUID, a reference from your ERP, or any value that uniquely identifies the request:
202 Accepted, resend the exact same request with the same Idempotency-Key. AgriBackup returns the original 202 response instead of creating a duplicate job. This is safe to retry any number of times.
Idempotency keys are scoped to your organization and expire after 24 hours. Use a key that encodes enough context (for example,
batch_BR-2026-991_ingest) to be meaningful in logs and support tickets.When to always include an Idempotency-Key
POST /api/v1/enterprise/eudr/polygons— polygon ingestionPOST /api/v1/enterprise/eudr/batches— batch registrationPOST /api/v1/enterprise/eudr/shipments/link— shipment linkagePOST /api/v1/enterprise/eudr/declarations/dds— DDS generation