Skip to content

Idempotency & failure handling

Receiving orders

The receive endpoint sits between two systems that both retry. Get three things right and nothing gets booked twice or lost.

1. Idempotency on request_id

request_id is AIOTIC's identity for the order and it never changes across retries of a send. Your rule: one request_id → at most one sales order.

python
existing = erp.find_order_by_request_id(request_id)     # external reference column, indexed
if existing:
    return {"success": True, "order_number": existing.number}

Persist the link in the same transaction as the order (or before you answer). If you keep it in a side table, write it before returning success: true.

The SDK's ErpReceiver does this with an IdempotencyStore (in-memory, SQLite, or your own) and asks the adapter's find_order_by_request_id as a second line of defence.

2. Transactions

Create header and lines atomically. A half-written order that later answers success: false leaves debris in the ERP that no one knows about. With a data API this means one database transaction; with a functional API, one create call (or compensating delete on failure).

3. Failure paths, one by one

What went wrongRight behaviourResult in AIOTIC
Wrong key401, {"success": false, "error": "unauthorized"}rollback; operator sees error
Payload does not validate (your rules){"success": false, "error": "<why>"}rollback; operator fixes and resends
ERP rejects for business reasons{"success": false, "error": "<ERP text>"}same
ERP unreachable / timeout{"success": false, "error": "ERP unavailable, retry later"} — nothing writtenrollback; retry later
Your endpoint crashes after the ERP created the order but before answeringAIOTIC times out and rolls back; the operator retries; your idempotency lookup finds the order and answers success: trueconsistent
Your endpoint is down entirelyAIOTIC gets a connection error, rolls backoperator retries when you are back

The one case you must design for is the crash after create: the external reference must be written with the order, not afterwards.

4. Duplicates that are not retries

A customer can send the same PO twice; an operator can upload it twice. Those arrive with different request_ids. Detect by (customer_id, order_number) and decide:

  • reject with success: false "PO EB2500011645 already booked as SO-981" (recommended — a person decides), or
  • accept and create a new order if your business allows repeat POs with the same number.

The SDK's NoDuplicateOrder rule implements the first policy; the key is remembered only after a successful booking, so a rejected order can be corrected and sent again.

5. What to log

Per call: request_id, outcome, order_number or error text, duration. Never the key. Keep the payload for a while (it is small) — support questions come days later.

6. What to monitor

  • rate of success: false per error text (a spike in "unknown article" means your product sync is behind)
  • p95 response time (must stay well under 30 s)
  • calls with an unknown key (someone is probing)

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