Skip to content

Errors, idempotency & limits

Concepts

Error shape

Every error is JSON with a detail member. Usually a string:

json
{ "detail": "Document with ID 550e8400-e29b-41d4-a716-446655440000 not found" }

A few endpoints return a structured detail so you can branch on a stable code instead of parsing text. Today that is POST /order/raw/upload when the e-mail is not a purchase order:

json
{ "detail": { "error": "not_a_purchase_order", "message": "…", "request_id": "…", "category": "quotation",
              "subject": "Offer 10531", "language": "de", "line_item_count": 25 } }

Write your client so that detail may be a string or an object. FastAPI-style validation errors (422) carry a list under detail.

Status codes

CodeMeaningTypical cause
200 / 202 / 204OK / upsert accepted / deleted
400Bad requestmalformed UUID, unsupported file, order not in FAILED for a retry, e-mail not a PO
401Unauthorizedmissing/invalid key, or the sync key on a non-master-data path
404Not foundunknown order / customer / product / mapping; mapping references a missing customer or product
409Conflictorder not sendable or already SENDING; rejected e-mail already overridden
415Unsupported media typefile extension not accepted
422Unprocessableyour ERP answered success: false on a send (detail = your error text); validation error
500Server erroryour ERP returned a non-JSON body or timed out during a send; unexpected failure
503Unavailabletenant not initialised, classification or ERP integration not configured

Retrying safely

OperationSafe to retry?How
POST /order/uploadYes, if you pass your own request_idSame UUID → same order; without it a retry creates a duplicate order
PUT master dataYesUpserts are idempotent
DELETE master dataYesA second delete returns 404 — treat as success
POST /erp/send/{id}YesAIOTIC locks the order; a concurrent send gets 409; a failed send rolls back so you can send again
POST /order/retry/{id}No (creates a new order each time it succeeds)Check the status first
GET anythingYes

Retry on 408, 429, 502, 503, 504 and on connection errors with exponential backoff and jitter (the SDK: 0.5 s · 2^attempt, capped at 30 s, three attempts). Do not retry a 503 on /erp/send blindly — it means the tenant has no ERP endpoint configured.

Idempotency on your side

Your ERP receive endpoint is called with a request_id that is stable across retries. Store request_id → your order number before you answer, and answer the same thing again if you see the id twice. Details in Idempotency & failure handling.

Correlating orders

  • Put your own reference in the upload as extra form fields; it comes back in metadata on every status read.
  • Use request_id in your ERP as the external reference. It appears in the AIOTIC app, in support tickets and in the hand-off payload.

Limits

LimitValue
size on list endpoints1 … 1000
top_k on customer search1 … 1000
Files per uploadany; all files form one order
Accepted upload types.pdf .jpg .jpeg .png .txt .md (+ .eml on the raw endpoint)
ERP receive timeout30 s default
Server-side rate limitnone — self-limit (SDK default 10 req/s)

Documentation revision 3 · Published 8 September 2026 · commit 6862d5e. Verified against AIOTIC API v1.0.0. AIOTIC is a product of DevOps Company.