Updated: 2026-11-10

Purchase order integration

There are two ways to create purchase orders through the API:

  • One request: PUT /orders/purchase creates 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/purchase creates the order, then POST /orders/purchase/{orderId}/inbound/lots adds 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

Reference

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.