Skip to main content
The compliance rollup is the single authoritative view of a transaction’s end-to-end state. Instead of assembling it from five module endpoints (buyer, order, invoice, payment, transport), call one endpoint and get everything, including the list of what is still missing. It composes; it does not judge. Every module below is the same projection its own operation returns, in the same schema, so a client that already generates InvoiceResponse reads modules.invoice with the type it has.

Endpoint

Response shape

In modules.invoice.type, PRELIMINARY means the VAT security deposit invoice; FINAL means the final invoice. These wire values remain unchanged. Each module is the schema its own operation returns — KycStatusResponse, OrderStatus plus OrderVinResponse[], InvoiceResponse, PaymentResponse, TransportResponse. Nothing here is computed for the rollup. updatedAt is the latest change among the rows the rollup reads. There is no rollup row of its own, so it is the newest of the underlying timestamps rather than a field anybody writes.

Status values

complianceStatus is a three-state rollup:

VALID does not mean blockers[] is empty

VALID records a decision staff made, not a proof that every artifact is on file. Staff can force-close an order, so VALID with a non-empty blockers[] is possible and is not a contradiction. Read it as “closed, with these items still outstanding”. If your integration gates on “everything is in”, gate on blockers[] being empty rather than on the status. There is no fourth state. The platform records that an order is open, closed or cancelled; it does not compute a compliance verdict, so there is no failure status to wait for. The VAT question — whether VAT was applied to this transaction — is answered by InvoiceResponse.vatIncluded, which is what was declared on the invoice by the party that issued it.

Blockers

blockers[] is the actionable list of what is missing. Each entry carries:
  • module: which module of modules is waiting — buyer, order, invoice, payment or transport.
  • code: a stable machine key. Five values:
  • documentType: present when the blocker names a specific document — it is the type to upload. Absent on the other codes.
  • message: English prose written for a person to read. Not stable across releases, and never to be parsed. Display it, or map code to your own copy.
Always show these to your users. They are the fastest path to diagnosing “why isn’t this order moving?”, and code plus documentType is enough to deep-link straight to the upload that clears the blocker.

Per-VIN variance

The platform records the two transport milestones against a transport, and a transport belongs to a shipment. An order NT24 staff split across several shipments can therefore be partly delivered. The transport module reports that two ways. Its order-level status is the least advanced transport, so a partly delivered order reads PICKUP_CONFIRMED. Its vins[] carries one entry per vehicle, read from the shipment that carries it, and shows which vehicles have arrived. See Transport.

Polling efficiently with ETag

The rollup supports If-None-Match for cheap polling:
The validator is opaque. Store it, send it back verbatim, and compare it for equality only. It is not a version number and carries no ordering: a different validator means the rollup changed, and nothing more can be read out of one. Do not write if (validator > cached) — there is no counter behind it. Use a short poll interval (10–60s) for orders in flight; less for closed ones.

When to poll vs subscribe to webhooks

See Webhooks overview for the subscription pattern.

Next

Idempotency

How to retry safely.

Webhooks overview

Event-driven alternative to polling.