Appearance
Outbound: webhooks
API reference
Calls AIOTIC makes to you. You implement these endpoints; AIOTIC authenticates with the key you provided. Guide: The ERP receive endpoint · The processing webhook.
ERP receive endpoint — implemented by you
POST<your URL>X-API-KEY (your key)
AIOTIC calls this URL (configured per tenant as the ERP API URL) when an operator — or an API caller via POST /erp/send/{request_id} — sends a reviewed order to the ERP.
- Method
POST,Content-Type: application/json, headerX-API-KEY: <key you gave us>. - Respond within the tenant's timeout (default 30 s) with a JSON body carrying
success. request_idis stable across retries: make the handler idempotent (return the sameorder_numberif you already created the order for this id).- Return
success: falsewith a clearerrorfor business rejections (unknown article, blocked customer, …); the text is shown to the operator in AIOTIC.
Header X-API-KEY — The key you provided during onboarding
Request body — application/json
Body AIOTIC POSTs to your ERP receive endpoint.
| Field | Type | Required | Description |
|---|---|---|---|
request_id | string | yes | AIOTIC's order id (UUID). Stable across retries of the same send — use it as the idempotency key and store it on your sales order as external reference. Format: uuid. |
purchase_order | ErpPurchaseOrder | yes | The reviewed purchase order with operator corrections applied. Every key below is always present; unknown values are null. |
Example:
json
{
"request_id": "550e8400-e29b-41d4-a716-446655440000",
"purchase_order": {
"order_number": "EB2500011645",
"order_date": "2026-01-14",
"delivery_date": "2026-02-01",
"currency": "EUR",
"total_price": 1234.56,
"additional_information": "Please deliver before noon.",
"supplier": {
"company": "Acme Supplies BV",
"contact_person": "P. Jansen",
"email": "orders@acme.example",
"address": {
"street": "Industrieweg 5",
"postal_code": "1234 AB",
"city": "Amsterdam",
"country": "NL"
}
},
"customer": {
"customer_id": "58931",
"company": "LUMITECH INSTALLATIES",
"contact_person": "J. de Boer",
"email": "info@lumitech.example",
"phone": "+31 55 123 4567",
"vat_id": "NL001234567B01",
"iban": null,
"bic": null,
"address": {
"street": "Ambachtsweg 12",
"postal_code": "7327 AA",
"city": "Apeldoorn",
"country": "NL"
}
},
"shipping_details": {
"recipient": {
"company": "LUMITECH INSTALLATIES",
"department": null,
"contact_person": "J. de Boer",
"email": null,
"phone": null,
"address": {
"street": "Ambachtsweg 12",
"postal_code": "7327 AA",
"city": "Apeldoorn",
"country": "NL"
}
},
"special_instructions": null
},
"items": [
{
"article_number": "PROD-001",
"description": "LED Driver 48V",
"quantity": 10,
"unit": "ST",
"price": 12.34,
"currency": "EUR",
"line_total": 123.4
}
]
}
}Every field of the hand-off payload
Every key listed here is always present; "nullable" means the value may be null.
| Path | Type | Nullable | Description |
|---|---|---|---|
request_id | string | AIOTIC's order id (UUID). Stable across retries of the same send — use it as the idempotency key and store it on your sales order as external reference. | |
purchase_order | object | The reviewed purchase order with operator corrections applied. Every key below is always present; unknown values are null. | |
purchase_order.order_number | string | The customer's purchase-order number as printed, with / replaced by -. Map it to the "your reference" / external document number of the sales order. | |
purchase_order.order_date | string | yes | Order date as an ISO YYYY-MM-DD string where the document allowed it; otherwise as printed. |
purchase_order.delivery_date | string | yes | Requested delivery date (YYYY-MM-DD) or null. When the document stated a window it is already collapsed to a single date. |
purchase_order.currency | string | yes | Currency code as printed on the document (e.g. EUR) or null. |
purchase_order.total_price | number | yes | The document's printed total, which may include VAT, or the recalculated net sum when e-mail instructions changed lines. Informational — let your ERP compute totals. |
purchase_order.additional_information | string | yes | Free text from the document and e-mail plus notes AIOTIC appends (e.g. the original printed total after a recalculation). |
purchase_order.supplier | object | yes | Your own company as configured for the tenant — identical on every order, never read from the document. Safe to ignore. |
purchase_order.supplier.company | string | Your company name as configured for the tenant. | |
purchase_order.supplier.contact_person | string | yes | Contact person configured for the tenant, if any. |
purchase_order.supplier.email | string | yes | Order intake e-mail address of the tenant. |
purchase_order.supplier.address | object | Your company address as configured. | |
purchase_order.supplier.address.street | string | Street and house number. | |
purchase_order.supplier.address.postal_code | string | Postal code. | |
purchase_order.supplier.address.city | string | City. | |
purchase_order.supplier.address.country | string | yes | Country code as printed, usually ISO 3166-1 alpha-2. |
purchase_order.customer | object | The identified customer (debtor). customer_id is your customer number; the address block is canonicalised from your master record on a confident match. | |
purchase_order.customer.customer_id | string | yes | Your customer (debtor) number as synced via PUT /customer/{number}. null only when an operator explicitly sent an unidentified order. |
purchase_order.customer.company | string | yes | Customer company name. |
purchase_order.customer.contact_person | string | yes | Person who placed this order, as printed on the document (document-authoritative, not the master record). |
purchase_order.customer.email | string | yes | Customer e-mail address. |
purchase_order.customer.phone | string | yes | Customer phone number. |
purchase_order.customer.iban | string | yes | Bank account when printed on the order; usually null. |
purchase_order.customer.bic | string | yes | Bank identifier when printed on the order; usually null. |
purchase_order.customer.vat_id | string | yes | VAT registration number. |
purchase_order.customer.address | object | Customer (bill-to) postal address. | |
purchase_order.customer.address.street | string | yes | Street and house number. |
purchase_order.customer.address.postal_code | string | yes | Postal code as printed or as stored in your master record. |
purchase_order.customer.address.city | string | yes | City. |
purchase_order.customer.address.country | string | yes | Country code as printed, usually ISO 3166-1 alpha-2. |
purchase_order.shipping_details | object | Ship-to recipient and delivery instructions. Filled from the customer block when the document has no explicit delivery address. | |
purchase_order.shipping_details.recipient | object | The ship-to block. | |
purchase_order.shipping_details.recipient.company | string | yes | Ship-to company name. |
purchase_order.shipping_details.recipient.department | string | yes | Department or address line 2. |
purchase_order.shipping_details.recipient.contact_person | string | yes | Ship-to contact for the carrier. |
purchase_order.shipping_details.recipient.email | string | yes | Ship-to e-mail. |
purchase_order.shipping_details.recipient.phone | string | yes | Ship-to phone. |
purchase_order.shipping_details.recipient.address | object | Delivery address. | |
purchase_order.shipping_details.recipient.address.street | string | yes | Street and house number. |
purchase_order.shipping_details.recipient.address.postal_code | string | yes | Postal code as printed or as stored in your master record. |
purchase_order.shipping_details.recipient.address.city | string | yes | City. |
purchase_order.shipping_details.recipient.address.country | string | yes | Country code as printed, usually ISO 3166-1 alpha-2. |
purchase_order.shipping_details.special_instructions | string | yes | Free-text delivery instructions ("deliver before noon", dock number). |
purchase_order.items[] | array of objects | One entry per order line, in document order. Lines without an ordered quantity (assortment listings) are already dropped. | |
purchase_order.items[].article_number | string | yes | Your article number (SKU) after resolution through your catalog and customer item mappings. null only on an explicit override send of an unresolved line. |
purchase_order.items[].description | string | yes | Line description as printed by the customer. |
purchase_order.items[].quantity | integer | yes | Ordered quantity in whole units. null only when the quantity was unreadable and an operator overrode the review. |
purchase_order.items[].unit | string | yes | Unit of measure as printed (ST, PCS, Stk, m, KG, …) — map it to your ERP's codes. |
purchase_order.items[].price | number | yes | Unit price as stated by the customer, or null. |
purchase_order.items[].currency | string | yes | Line currency, normally equal to the header currency. |
purchase_order.items[].line_total | number | yes | Line amount as printed (quantity × price), or null. |
Expected response
Outcome (any HTTP status is accepted; the body decides)
Body your ERP receive endpoint must return. success is authoritative — AIOTIC ignores the HTTP status for the business outcome (a 500 with success: false and a success: true with 200 are both handled correctly; a non-JSON body is treated as a server error).
| Field | Type | Required | Description |
|---|---|---|---|
success | boolean | yes | |
order_number | string | Your ERP's reference for the created order; stored as erp_ref and shown to operators | |
error | string | Human-readable reason when success is false; shown to operators |
Accepted:
json
{
"success": true,
"order_number": "SO-2026-00981"
}Business rejection:
json
{
"success": false,
"error": "Unknown article number: PROD-999"
}Processing webhook (optional) — implemented by you
POST<your URL>X-API-KEY (your key)
If the tenant has the processing webhook enabled, AIOTIC POSTs the extracted order to this URL as soon as extraction finishes — before any operator review, and regardless of whether the order landed in PROCESSED or ATTENTION.
Use it as an early signal ("an order arrived, here is the AI's reading"), not as the hand-off: the reviewed, corrected version reaches you through the ERP receive endpoint.
- Header
X-API-KEY: <configured value>; respond2xxto acknowledge. - Delivery is best-effort: no retries and no signature today (see the proposal appendix in the guide).
Request body — application/json
Body of the optional processing webhook, sent when extraction completes (before any human review).
| Field | Type | Required | Description |
|---|---|---|---|
request_id | string | yes | Format: uuid. |
purchase_order | PurchaseOrder | yes |
Every field of the webhook payload
Every key listed here is always present; "nullable" means the value may be null.
| Path | Type | Nullable | Description |
|---|---|---|---|
request_id | string | ||
purchase_order | object | The extracted purchase order as returned in OrderStatus.result. Every field is always present; optional fields are null, never omitted. | |
purchase_order.order_number | string | Customer's PO number. / is replaced by -. | |
purchase_order.order_date | string | ISO 8601 date (YYYY-MM-DD) where the document allowed it | |
purchase_order.delivery_date | string | yes | Single requested delivery date (resolved from a window per tenant preference) |
purchase_order.delivery_date_from | string | yes | Lower bound when the document states a delivery window |
purchase_order.delivery_date_to | string | yes | Upper bound when the document states a delivery window |
purchase_order.supplier | object | The receiving company — your company. Pinned from tenant configuration, not extracted per document. | |
purchase_order.supplier.company | string | Your company name as configured for the tenant. | |
purchase_order.supplier.contact_person | string | yes | Contact person configured for the tenant, if any. |
purchase_order.supplier.email | string | yes | Order intake e-mail address of the tenant. |
purchase_order.supplier.address | object | Your company address as configured. | |
purchase_order.supplier.address.street | string | Street and house number. | |
purchase_order.supplier.address.postal_code | string | Postal code. | |
purchase_order.supplier.address.city | string | City. | |
purchase_order.supplier.address.country | string | yes | Country code as printed, usually ISO 3166-1 alpha-2. |
purchase_order.customer | object | yes | The identified customer (debtor). customer_id is your customer number and is set only when AIOTIC resolved the customer with confidence. |
purchase_order.customer.customer_id | string | yes | |
purchase_order.customer.company | string | ||
purchase_order.customer.contact_person | string | yes | |
purchase_order.customer.email | string | yes | |
purchase_order.customer.phone | string | yes | |
purchase_order.customer.branch | string | yes | Issuing branch / location named on the document, when any |
purchase_order.customer.vat_id | string | yes | |
purchase_order.customer.iban | string | yes | |
purchase_order.customer.bic | string | yes | |
purchase_order.customer.address | object | ||
purchase_order.customer.address.street | string | Street and house number. | |
purchase_order.customer.address.postal_code | string | Postal code. | |
purchase_order.customer.address.city | string | City. | |
purchase_order.customer.address.country | string | yes | Country code as printed, usually ISO 3166-1 alpha-2. |
purchase_order.shipping_details | object | yes | |
purchase_order.shipping_details.recipient | object | The ship-to block. | |
purchase_order.shipping_details.recipient.company | string | Ship-to company name. | |
purchase_order.shipping_details.recipient.contact_person | string | yes | Ship-to contact for the carrier. |
purchase_order.shipping_details.recipient.department | string | yes | Department or address line 2. |
purchase_order.shipping_details.recipient.email | string | yes | Ship-to e-mail. |
purchase_order.shipping_details.recipient.phone | string | yes | Ship-to phone. |
purchase_order.shipping_details.recipient.address | object | Delivery address. | |
purchase_order.shipping_details.recipient.address.street | string | Street and house number. | |
purchase_order.shipping_details.recipient.address.postal_code | string | Postal code. | |
purchase_order.shipping_details.recipient.address.city | string | City. | |
purchase_order.shipping_details.recipient.address.country | string | yes | Country code as printed, usually ISO 3166-1 alpha-2. |
purchase_order.shipping_details.special_instructions | string | yes | Free-text delivery instructions. |
purchase_order.items[] | array of objects | One order line as stored on the order (result.items[]). | |
purchase_order.items[].article_number | string | yes | Your (supplier-side) article number, resolved through the catalog and customer mappings where possible |
purchase_order.items[].customer_item_number | string | yes | The customer's own article number as printed, when present |
purchase_order.items[].description | string | yes | |
purchase_order.items[].quantity | integer | yes | Ordered quantity in whole units; null when unreadable (see quantity_state) |
purchase_order.items[].quantity_state | string | yes | What the quantity column literally showed. Unrecognised rows keep an empty quantity and put the order in ATTENTION. |
purchase_order.items[].unit | string | yes | Unit of measure as printed (e.g. ST, PCS, KG) |
purchase_order.items[].price | number | yes | Unit price |
purchase_order.items[].currency | string | yes | |
purchase_order.items[].line_total | number | yes | |
purchase_order.total_price | number | yes | |
purchase_order.currency | string | yes | |
purchase_order.additional_information | string | yes | Free text from the document / e-mail, plus audit notes AIOTIC appends (e.g. original document total) |
Expected response
Acknowledged