Updated: 2026-11-10
Purchase order integration
There are two ways to create purchase orders through the API:
- One request:
PUT /orders/purchasecreates or updates the whole order, header and inbound lots, to the state you send. Best when another system (ERP, webshop, EDI) owns the purchase order and pushes it to tracezilla. - Several requests:
POST /orders/purchasecreates the order, thenPOST /orders/purchase/{orderId}/inbound/lotsadds one inbound lot per request. Best when you build the order step by step.
The two flows have slightly different validation logic. See the notes in each section.
Prerequisites
- Bearer token or client credentials
- API base url from tracezilla for your company
- Optionally a tracezilla login to access Swagger API documentation
- The UUID of the supplier partner and one of its locations
- The UUID of your own partner and the location the goods are delivered to. See Manage locations
- The SKU codes (one request) or SKU UUIDs (several requests) of the products you buy. See Finding SKU ids
Reference
PUT /orders/purchaseCreate or update a purchase order with inbound lots in one requestPOST /orders/{orderType}Create an orderPOST /orders/{orderType}/{orderId}/inbound/lotsAdd an inbound lot to an orderGET /skusGet a list of SKUsGET /partners/{partnerId}/locationsGet the locations of a partner
Create or update the order in one request
Endpoint
1
PUT /orders/purchase
tracezilla looks for an existing purchase order whose ext_ref matches order_header.ext_ref, or one of alternative_order_refs. Cancelled orders are skipped.
- No match: the order is created and you get response code
201. - Match: the order is updated and you get response code
200.
You can send the same request again every time the order changes in your system.
Notice the request sets the order to exactly what you send. Inbound lots that are on the order but not in inbound_lots are removed. Always send the complete list of lines.
Request parameters (body)
| key | value | type | description |
|---|---|---|---|
| order_header.ext_ref | PO-10045 | string | Required. Your reference for the order, max 50 characters. Used to find the order again on later requests |
| order_header.delivery_date | 2026-11-20 | date | Required. Expected delivery date |
| order_header.status | draft | string | Defaults to from_edi |
| order_header.partners.supplier.partner_id | - | UUID | Required. The supplier |
| order_header.partners.supplier.location_id | - | UUID | Required. The supplier location |
| order_header.partners.deliver_to.partner_id | - | UUID | Your own partner. Set it whenever the order has traceable lines |
| order_header.partners.deliver_to.location_id | - | UUID | The location where the goods are received. Set it whenever the order has traceable lines |
| order_header.partners.pickup_from | - | object | Defaults to the supplier |
| inbound_lots[].sku_code | 1001 | string | The SKU code. Alternatively use sku_id |
| inbound_lots[].quantity | 10 | integer | Quantity in the lot unit of the SKU. Alternatively use quantity_pu |
| inbound_lots[].batch_number | L2611 | string | Batch number of the lot |
| inbound_lots[].expiry_date | 2027-05-01 | date | Expiry date of the lot |
| inbound_lots[].unit_price | 12.50 | number | Purchase price |
| post_save_action | confirm | string | none (default), confirm or receive |
See the tech docs for all fields, including lot_attributes, lot_traces, service_lines, price_logic and files.
Purchase order example curl request
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
curl -X 'PUT' \
'https://app.tracezilla.com/api/v1/example-company/orders/purchase' \
-H 'accept: application/json' \
-H 'Content-Type: application/json' \
-H 'Authorization: Bearer {yourBearerToken}' \
-d '{
"order_header": {
"ext_ref": "PO-10045",
"status": "draft",
"delivery_date": "2026-11-20",
"partners": {
"supplier": {
"partner_id": "3c6f1d0e-8a3b-4f5e-9a7c-2b1d4e6f8a90",
"location_id": "7a2e9c41-5b8d-4e3f-a1c6-0d9e8f7b6a53"
},
"deliver_to": {
"partner_id": "feea330b-a635-411e-a3d5-9191c911d381",
"location_id": "9eb34497-e393-46cc-9141-f4ad9f7ceea1"
}
}
},
"inbound_lots": [
{
"sku_code": "1001",
"batch_number": "L2611",
"expiry_date": "2027-05-01",
"quantity": 10,
"unit_price": 12.50
},
{
"sku_code": "1002",
"batch_number": "L2612",
"quantity": 4,
"unit_price": 8.00
}
]
}'
Confirm the order
Set post_save_action to confirm to confirm the order in the same request:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
curl -X 'PUT' \
'https://app.tracezilla.com/api/v1/example-company/orders/purchase' \
-H 'accept: application/json' \
-H 'Content-Type: application/json' \
-H 'Authorization: Bearer {yourBearerToken}' \
-d '{
"order_header": {
"ext_ref": "PO-10045",
"delivery_date": "2026-11-20",
"partners": {
"supplier": {
"partner_id": "3c6f1d0e-8a3b-4f5e-9a7c-2b1d4e6f8a90",
"location_id": "7a2e9c41-5b8d-4e3f-a1c6-0d9e8f7b6a53"
},
"deliver_to": {
"partner_id": "feea330b-a635-411e-a3d5-9191c911d381",
"location_id": "9eb34497-e393-46cc-9141-f4ad9f7ceea1"
}
}
},
"inbound_lots": [
{
"sku_code": "1001",
"batch_number": "L2611",
"expiry_date": "2027-05-01",
"quantity": 10,
"unit_price": 12.50
},
{
"sku_code": "1002",
"batch_number": "L2612",
"quantity": 4,
"unit_price": 8.00
}
],
"post_save_action": "confirm"
}'
490 Locked
Once the order is confirmed, another PUT with the same ext_ref returns response code 490 The order is currently in a locked state and cannot be updated!
To change a confirmed order anyway, add "ignore_order_state": true to the request body. The order is reopened, updated, and keeps its status.
Create the order in several requests
Create order
Endpoint
Replace {orderType} including the curly brackets with purchase
1
POST /orders/{orderType}
Request parameter (path)
| key | value | type | description |
|---|---|---|---|
| orderType | purchase | string | Purchase orders |
Request parameters (body)
This endpoint validates more strictly than PUT /orders/purchase. status, pickup_date and all three partner roles are required, and partners must be referenced by UUID.
| key | value | type | description |
|---|---|---|---|
| ext_ref | PO-10046 | string | Your reference for the order |
| status | draft | string | Required |
| delivery_date | 2026-11-20 | date | Required |
| pickup_date | 2026-11-20 | date | Required. Same as or before delivery_date |
| partners.supplier.partner_id | - | UUID | Required |
| partners.supplier.location_id | - | UUID | Required |
| partners.pickup_from.partner_id | - | UUID | Required. Usually the supplier |
| partners.pickup_from.location_id | - | UUID | Required |
| partners.deliver_to.partner_id | - | UUID | Required. Your own partner |
| partners.deliver_to.location_id | - | UUID | Required. The location where the goods are received |
Create order example curl request
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
curl -X 'POST' \
'https://app.tracezilla.com/api/v1/example-company/orders/purchase' \
-H 'accept: application/json' \
-H 'Content-Type: application/json' \
-H 'Authorization: Bearer {yourBearerToken}' \
-d '{
"ext_ref": "PO-10046",
"status": "draft",
"delivery_date": "2026-11-20",
"pickup_date": "2026-11-20",
"partners": {
"supplier": {
"partner_id": "3c6f1d0e-8a3b-4f5e-9a7c-2b1d4e6f8a90",
"location_id": "7a2e9c41-5b8d-4e3f-a1c6-0d9e8f7b6a53"
},
"pickup_from": {
"partner_id": "3c6f1d0e-8a3b-4f5e-9a7c-2b1d4e6f8a90",
"location_id": "7a2e9c41-5b8d-4e3f-a1c6-0d9e8f7b6a53"
},
"deliver_to": {
"partner_id": "feea330b-a635-411e-a3d5-9191c911d381",
"location_id": "9eb34497-e393-46cc-9141-f4ad9f7ceea1"
}
}
}'
POST /orders/purchase response sample:
1
2
3
4
5
6
7
8
{
"data": {
"id": "5b1f0c2e-6d4a-4c8b-9e3f-1a2b3c4d5e6f",
"type": "purchase",
"ext_ref": "PO-10046",
"status": "draft",
"delivery_date": "2026-11-20",
...
Extract "id" for {orderId} in the next request
Create inbound lot
Endpoint
1
POST /orders/{orderType}/{orderId}/inbound/lots
Request parameter (path)
| key | value | type | description |
|---|---|---|---|
| orderType | purchase | string | Purchase orders |
| orderId | - | UUID | "id" from the create order response |
Request parameters (body)
The field names differ from PUT /orders/purchase. The SKU is identified by sku_id, not sku_code (see Finding SKU ids), and the expiry date goes in dates.best_before, not expiry_date.
| key | value | type | description |
|---|---|---|---|
| sku_id | - | UUID | Required. Look up the UUID from the SKU code with GET /skus |
| quantity | 10 | integer | Quantity in the lot unit of the SKU |
| batch_number | L2613 | string | Batch number of the lot |
| dates.best_before | 2027-05-01 | date | Expiry date of the lot |
| unit_price | 12.50 | number | Purchase price |
Inbound lot example curl request
1
2
3
4
5
6
7
8
9
10
11
12
13
14
curl -X 'POST' \
'https://app.tracezilla.com/api/v1/example-company/orders/purchase/{orderId}/inbound/lots' \
-H 'accept: application/json' \
-H 'Content-Type: application/json' \
-H 'Authorization: Bearer {yourBearerToken}' \
-d '{
"sku_id": "be3233c4-c0a2-4f47-a62a-303492c20ba6",
"quantity": 10,
"batch_number": "L2613",
"dates": {
"best_before": "2027-05-01"
},
"unit_price": 12.50
}'
If the request succeeds, you get response code 200 and the created line in a data array. Repeat the request for each lot on the order.