Skip to content

The purchase-order model ​

Concepts

Two closely related shapes exist:

  • PurchaseOrder — what you read in OrderStatus.result (the stored extraction, with AIOTIC's additive fields).
  • ErpPurchaseOrder — what your ERP receive endpoint gets (a fixed subset, with operator corrections applied).

Both follow the same rules: every key is always present, optional values are null (never omitted), dates are ISO YYYY-MM-DD, amounts are decimal numbers, quantities are whole numbers.

PurchaseOrder (in result) ​

json
{
  "order_number": "EB2500011645",
  "order_date": "2026-01-14",
  "delivery_date": "2026-02-01",
  "delivery_date_from": null,
  "delivery_date_to": null,
  "supplier": { "company": "Acme Supplies BV", "contact_person": null, "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", "branch": null,
                "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", "contact_person": "J. de Boer", "department": null,
                        "email": null, "phone": null,
                        "address": { "street": "Ambachtsweg 12", "postal_code": "7327 AA", "city": "Apeldoorn", "country": "NL" } },
                        "special_instructions": null },
  "items": [
    { "article_number": "PROD-001", "customer_item_number": "LT-ART-001", "description": "LED Driver 48V",
      "quantity": 10, "quantity_state": "Valid", "unit": "ST", "price": 12.34, "currency": "EUR", "line_total": 123.40 }
  ],
  "total_price": 123.40,
  "currency": "EUR",
  "additional_information": null
}
FieldTypeNotes
order_numberstringThe customer's PO number. / is replaced by - (many ERPs cannot store it).
order_datestringISO date where the document allowed it.
delivery_datestring | nullThe single date your ERP consumes. When the document states a window, AIOTIC collapses it to one end according to the tenant's preference (earliest by default).
delivery_date_from / delivery_date_tostring | nullThe window bounds, for audit. null for single-date orders.
currencystring | nullISO code as printed (EUR).
total_pricenumber | nullThe printed document total — may include VAT. When e-mail instructions changed the lines, this is the recalculated net sum and the original total is noted in additional_information.
additional_informationstring | nullFree text from document and e-mail, plus notes AIOTIC appends.

Supplier ​

supplier is you. It is pinned from tenant configuration and identical on every order; it is not extracted from the document. Do not map it — it is there so the payload is self-describing.

Customer ​

FieldNotes
customer_idYour customer (debtor) number, exactly as you synced it via PUT /customer/{number}. null when AIOTIC could not identify the sender with confidence — the order is then in ATTENTION.
company, address, email, phone, vat_idWhen a customer was identified with high confidence, these are canonicalised from your master record; otherwise they are as read from the document.
branchThe issuing branch/location named on the document (chains with one debtor per branch).
iban, bicRarely present on purchase orders; passed through when found.

Shipping details ​

shipping_details.recipient is the ship-to block. When the document has no explicit one, AIOTIC fills it from the identified customer. special_instructions carries delivery remarks ("deliver before noon").

Line items ​

FieldNotes
article_numberYour SKU, after resolution through the catalog and customer item mappings (how). null = unresolved → ATTENTION.
customer_item_numberThe customer's own code as printed, when present. Useful to create a mapping afterwards.
quantityWhole units. null only when quantity_state is Unrecognised. Lines with a blank or zero quantity (assortment listings) are dropped before storage.
quantity_stateValid, Unrecognised (kept for review), or absent on older orders.
unitAs printed (ST, PCS, Stk, m, KG…). Map it on your side (SDK sanitizer).
price, line_totalUnit price and line amount as printed, when present.

ErpPurchaseOrder (what your endpoint receives) ​

The hand-off payload is a fixed allow-list of the above:

  • header: order_number, order_date, delivery_date, currency, total_price, additional_information, supplier
  • customer: customer_id, company, contact_person, email, phone, iban, bic, vat_id, address{street, postal_code, city, country}
  • shipping_details.recipient: company, department, contact_person, email, phone, address{…} and special_instructions
  • items[]: article_number, description, quantity, unit, price, currency, line_total

Not included: quantity_state, customer_item_number, branch, delivery_date_from/to. Operator edits from the AIOTIC app are merged in before sending. The full JSON Schema is in the API reference.

Working with it in Python ​

python
from aiotic.models import ErpReceiveRequest, PurchaseOrder

req = ErpReceiveRequest.model_validate_json(body)      # in your receive endpoint
for line in req.purchase_order.items:
    ...

status = client.orders.get(request_id)                  # when polling
po: PurchaseOrder | None = status.result
if po and po.unresolved_items:
    ...

Revision 28-051026-58cfad3 · API v1.0.0 · AIOTIC is a product of DevOps Company.