Independent AI agent for EU Deforestation Regulation compliance, not affiliated with the EU. Scope & disclaimer →
eudr.dev

DDS anatomy and receipts

What a Due Diligence Statement actually contains, how eudr.dev produces it, and how an auditor reads the signed receipt.

Annex II structure (post-2025/2650)

Reg. (EU) 2025/2650 deleted Annex II point 4. The current Annex II has these numbered points:

PointContentArticle
1Operator information — name, address, EORI.9(1)(a)
2HS code(s) + product description + quantity.9(1)(b)+(c)
3Country of production + geolocation of all plots + production time-range.9(1)(d)
~~4~~~~Upstream-DDS reference number.~~DELETED by Reg. 2025/2650. Reference is retained under Art. 4(8)/(9) but no longer a numbered Annex II field.
5Declaration that the goods comply with Art. 3.Annex II text.
6Operator signature block.Annex II text.

The engine's JSON wire format mirrors this with keys 1_operator, 2_product, 3_geolocation, 5_declaration, 6_signature.

Engine extensions (not part of Annex II)

The engine adds three top-level fields to the receipt that are not part of the regulator-required Annex II content but are essential for offline verification:

The signed-receipt envelope

{
 "payload": { /* canonical Annex II JSON with engine extensions */ },
 "cid": "bafkreih..", // CIDv1 of payload (BLAKE3 + base32-lower)
 "signature_b64": "..", // ed25519 signature over cid bytes
 "pubkey_b32": "ed25519:abc..", // signer's public key
 "did": "did:web:eudr.dev",
 "issued_at": "2026-05-18T12:14:22Z"
}

The CID is a deterministic BLAKE3 hash of the canonical JSON of payload. Any byte change in payload produces a different CID; the signature over the CID then fails verification.

How to read a receipt

Open /verify in a browser and paste the receipt JSON, or use the CLI:

eudr verify path/to/receipt.json

Both paths run the four offline checks described in verify-offline:

  1. Re-canonicalise the payload exactly as the engine did.
  2. Re-hash with BLAKE3 → re-encode as CIDv1; compare to the claimed cid.
  3. Verify the ed25519 signature over the CID bytes against the public key in the agent card at https://eudr.dev/.well-known/agent-card.json.
  4. Spot-check the emem fact CIDs in source_receipts.emem.per_cell[].fact_cids[] against https://emem.dev/v1/facts/<cid>.

Engine reference vs official reference

The dds_reference field in the payload is the engine's internal identifier (a UUID). TRACES NT assigns the official reference number + verification code on submission. The engine's reference is stable for client-side joining; the TRACES reference is what the regulator uses.

Once the operator has submitted via TRACES, they can update the receipt by storing the TRACES reference + code alongside.

Where the engine's keypair lives

The agent card at /.well-known/agent-card.json publishes the ed25519 public key in two forms (publicKeyMultibase and pubkey_b32) plus the DID did:web:eudr.dev.

The private key is held in AWS SSM Parameter Store under /eudr/prod/agent-privkey-b64.

See also