Product & Engineering
A compliance pipeline you can integrate against, not a portal you have to work around.
POST arbitrary invoice JSON, get a structured status back. No manual field mapping to reverse-engineer, no undocumented behavior — the same pipeline is available as a stateless dry-run and as a persisting submit call.
/validate ↔ /submit
Build and test against one endpoint, ship on both.
POST /api/v1/compliance/validate and /submit share the exact same request body and normalize-and-check pipeline. Validate is a stateless dry-run; submit persists to the ledger and enqueues transmission. Nothing changes in the payload between the two — swap the URL when you’re ready to go live.
curl -X POST https://<api-host>/api/v1/compliance/validate \ -H "X-API-Key: $API_KEY" \ -H "Content-Type: application/json" \ -d '{ "source_reference": "INV-2026-0001", "payload": { ... } }'{ "status": "PENDING_TRANSMISSION", "ledger_id": "b3f1c2a0-...", "duplicate": false, "issues": []}Built for real integration work
The parts that make an API safe to build against.
Idempotent by construction
Requests are idempotent on (tenant, source_reference), chaos-tested under concurrent load — safe to retry on a timeout or redeliver from your own outbox without a duplicate FTA transmission.
Signed webhooks in both directions
HMAC-SHA256-signed webhooks, with timestamp freshness windows and nonce replay protection, so you can verify a callback actually came from us.
Structured errors, not a generic failure
Every failed check returns a ValidationIssue — field, code, message, severity — so a bad payload tells you exactly what to fix.
A ledger id on every response
ledger_id and duplicate come back on every submit call, giving you a correlation id to key your own logs and support conversations on.
Issue-code catalog
Errors tell you what to fix.
An excerpt from the full catalog — every issue code you can get back from validate is documented, not just the ones that seemed important at launch.
MISSING_MANDATORYerrorA field PINT-AE requires unconditionally could not be mapped from your payload.
LINE_MATHerrornet_amount + vat_amount != gross_amount on a line item (2dp, ROUND_HALF_UP).
VAT_RATE_MISMATCHerrorThe vat_rate on a line isn't one of the rates allowed for that VAT category.
TIN_TRN_MISMATCHerrorThe Peppol TIN doesn't match the corresponding TRN field.
Docs and collection
A Postman collection and integration docs, not a sales deck.
The curl example above is the actual request shape — copy it, point it at your payload, and read back a real ValidationIssue list. The full developer docs cover authentication, the complete issue-code catalog, and the webhook signature contract.