Purchase order ( purchase_order )

A purchase_order is an order issued by a merchant to a supplier. It carries amounts, line items, and progress status and serves as the anchor for supplier invoices received in return.

Role

The purchase order is the entry object for the Accounts Payable (AP) lifecycle. It formalizes the merchant's commitment to a supplier before goods or services are delivered and invoiced. Its lifecycle follows the operational journey: drafting → internal approval → sending to supplier → receipt → closure.

Received supplier invoices may be created directly from the purchase order or linked afterward. Invoice lines may reference purchase-order lines for precise matching.

The supplier is a company platform object — the same objects are used for buyers in AR flows and suppliers in AP flows.

Identifier and structure

Each purchase order has a stable identifier prefixed with po_.

JSON
"purchase_order":{22 items
"object":"purchase_order"
"id":"po_3c8f1a9b2d4e7f6a"
"merchant_id":"mer_1a2b3c4d5e6f7a8b"
"supplier_id":"cmp_9b2e4f1a7c3d8e5f"
"supplier_contact_id":null
"source_reference":"erp::tenant-42::purchase_order::158"
"reference":"PO-2026-00158"
"supplier_order_reference":"CONF-SUP-8741"
"delivery_details":{1 item
"address":{...}4 items
}
"status":"sent"
"currency":"eur"
"amount_excluding_tax":250000
"amount_tax":50000
"amount_including_tax":300000
"metadata":{}0 items
"approved_at":"2026-06-17T09:00:00.000Z"
"sent_at":"2026-06-17T10:30:00.000Z"
"cancelled_at":null
"fulfilled_at":null
"completed_at":null
"created_at":"2026-06-17T08:45:00.000Z"
"updated_at":"2026-06-17T10:30:00.000Z"
}
{
"object": "purchase_order",
"id": "po_3c8f1a9b2d4e7f6a",
"merchant_id": "mer_1a2b3c4d5e6f7a8b",
"supplier_id": "cmp_9b2e4f1a7c3d8e5f",
"supplier_contact_id": null,
"source_reference": "erp::tenant-42::purchase_order::158",
"reference": "PO-2026-00158",
"supplier_order_reference": "CONF-SUP-8741",
"delivery_details": {
  "address": {
    "line1": "4 rue des Ateliers",
    "city": "Lyon",
    "postal_code": "69007",
    "country": "FR"
  }
},
"status": "sent",
"currency": "eur",
"amount_excluding_tax": 250000,
"amount_tax": 50000,
"amount_including_tax": 300000,
"metadata": {},
"approved_at": "2026-06-17T09:00:00.000Z",
"sent_at": "2026-06-17T10:30:00.000Z",
"cancelled_at": null,
"fulfilled_at": null,
"completed_at": null,
"created_at": "2026-06-17T08:45:00.000Z",
"updated_at": "2026-06-17T10:30:00.000Z"
}

Fields

FieldTypeDescription
idstringPurchase-order identifier (prefix `po_`).
objectstringAlways "purchase_order".
merchant_idstringIssuing merchant.
supplier_idstringRecipient supplier (`cmp_…`). Required at creation.
supplier_contact_idstring | nullSupplier contact (`ctc_…`). Optional.
source_referencestring | nullIdentity or provenance of the purchase order in your source system.
referencestring | nullBusiness purchase-order number assigned by the merchant.
supplier_order_referencestring | nullOrder number or confirmation assigned by the supplier in response to the purchase order.
delivery_detailsobject | nullOpen shipping or destination information useful to the P2P flow.
statusenumPurchase-order status: `draft`, `approved`, `sent`, `cancelled`, `fulfilled`, `completed`.
currencystringISO 4217 currency code in lowercase (for example `eur`).
amount_excluding_taxintegerAmount excluding tax in cents.
amount_taxintegerTax amount in cents.
amount_including_taxintegerAmount including tax in cents. Constraint: excluding tax + tax = including tax.
metadataobjectFlat map of `string | number | boolean` scalars, following the API metadata convention.
approved_atdatetime | nullInternal approval timestamp.
sent_atdatetime | nullTimestamp when sent to the supplier.
cancelled_atdatetime | nullCancellation timestamp.
fulfilled_atdatetime | nullTimestamp of receipt of goods or services.
completed_atdatetime | nullAccounting-closure timestamp.
created_atdatetimeCreation date.
updated_atdatetimeLast update date.

Lifecycle

The purchase order follows a linear lifecycle from drafting to closure. Only status draft is editable.

Statuses

StatusDescriptionFinal
draftDraft. Editable — amounts, lines, contact. Only possible initial status.no
approvedApproved internally. Not editable.no
sentSent to the supplier.no
fulfilledGoods or services received.no
completedClosed — accounting processing complete.yes
cancelledCanceled. Reachable from `draft`, `approved`, or `sent`.yes

Transitions

ActionEndpointFromToTimestamp populated
ApprouverPOST /:id/approvedraftapprovedapproved_at
EnvoyerPOST /:id/sendapprovedsentsent_at
ReceivePOST /:id/fulfillapproved, sentfulfilledfulfilled_at
ClosePOST /:id/completefulfilledcompletedcompleted_at
AnnulerPOST /:id/canceldraft, approved, sentcancelledcancelled_at
Cumulative timestamps

Progress timestamps are cumulative: moving directly from approved to fulfilled also populates sent_at. Moving from draft to fulfilled also populates approved_at and sent_at with the same timestamp. Likewise, complete populates fulfilled_at if it was still null.

Lignes d'article

Line items describe the products or services ordered. They may be supplied at creation and atomically replaced during update while the purchase order is in draft). They are available through GET /v1/purchase-orders/:id/line-items.

FieldTypeDescription
idstringLine identifier (prefix `li_`).
product_namestringProduct or service name. Required.
descriptionstring | nullAdditional description.
product_referencestring | nullProduct reference in your catalog.
quantityintegerQuantity (positive integer).
unit_amount_excluding_taxintegerUnit price excluding tax in cents.
unit_amount_including_taxintegerUnit price including tax in cents.
amount_excluding_taxintegerLine amount excluding tax (= `unit_ht` × `quantity` when absent).
amount_taxintegerLine tax amount.
amount_including_taxintegerLine amount including tax (= `unit_ttc` × `quantity` when absent).
currencystringCurrency. Must match the purchase-order currency.

If amount_excluding_tax or amount_including_tax is not supplied, it is calculated automatically (unit_amount × quantity). The excluding tax + tax = including tax constraint applies to every line.

Supplier-invoice lines may reference a purchase-order line through purchase_order_line_item_id for line-by-line matching.

Supplier invoices

A purchase order may be associated with one or more supplier invoices through a many-to-many relationship. An invoice may also be linked to several purchase orders, for example partial deliveries across several POs.

Create an invoice from the purchase order

POST /v1/purchase-orders/:id/supplier-invoices creates a supplier invoice that automatically inherits the purchase-order currency and establishes the relationship between the two objects.

HTTP
POST /v1/purchase-orders/po_3c8f/supplier-invoices
{8 items
"type":"invoice"
"amount_excluding_tax":250000
"amount_tax":50000
"amount_including_tax":300000
"reference":"SUPPLIER-INVOICE-2026-0042"
"issue_date":"2026-06-17"
"received_at":"2026-06-18T09:00:00.000Z"
"due_date":"2026-07-17"
}
{
"type": "invoice",
"amount_excluding_tax": 250000,
"amount_tax": 50000,
"amount_including_tax": 300000,
"reference": "SUPPLIER-INVOICE-2026-0042",
"issue_date": "2026-06-17",
"received_at": "2026-06-18T09:00:00.000Z",
"due_date": "2026-07-17"
}

The invoice is created with status = received, settlement_status = unpaid and disputed = false. These three pieces of information evolve independently: receipt/approval, settlement, and dispute.

Link existing invoices

EndpointEffet
GET /v1/purchase-orders/:id/supplier-invoicesLists linked supplier invoices.
POST /v1/purchase-orders/:id/supplier-invoice-linksAtomically replaces the complete set of links. Send { "supplier_invoice_ids": ["si_…"] }.
DELETE /v1/purchase-orders/:id/supplier-invoice-links/:supplier_invoice_idRemoves one link without affecting others.

Links can also be managed from the supplier invoice through POST /v1/supplier-invoices/:id/purchase-order-links.

In processes

There is no dedicated node for creating or transitioning a purchase order. The object is managed through direct API calls or HTTP actions in an orchestration process.

The purchase order can be passed as typed input in a process — it can be retrieved through the generic helper fetch_purchase_order from its identifier.

In a typical AP flow, the process is triggered by a receipt event (purchase_order.fulfilled or supplier_invoice.received), then orchestrates invoice approval and supplier payment.

Events

EventTrigger
purchase_order.createdPurchase order created.
purchase_order.updatedPurchase order updated — amounts, lines, contact.
purchase_order.approvedMoved to `approved`.
purchase_order.sentMoved to `sent`.
purchase_order.fulfilledMoved to `fulfilled` — receipt confirmed.
purchase_order.completedMoved to `completed` — accounting closure.
purchase_order.cancelledMoved to `cancelled`.

Transition events include final status in their payload. The payload also contains supplier_id so processes can filter events by supplier.