Receiving purchase orders

Receive a purchase order (PO) as deliveries arrive: everything at once, or some rows and quantities now and the rest later. This guide continues the bike workshop from Purchase orders with traceability: PO 3120415 with 5 packs of brake pads (row 46012001), 4 boxes of chain (row 46012002) and 3 pairs of hub motors (row 46012003), with batches, serial numbers and bins pre-assigned.

Before you start

  • We recommend turning on Require traceability assignment under Settings > Preferences, so a receipt that leaves batch- or serial-tracked stock untraced is refused with 422 INVENTORY_SETTINGS_VIOLATED.

Receive what arrived

On Monday the brake pads, all hub motors and 1.5 boxes of chain arrive. Receive them in one request, quantities in each row's purchase unit:

curl -X POST https://api.katanamrp.com/v1/purchase_order_receive \
  -H "Authorization: Bearer $KATANA_API_KEY" -H "Content-Type: application/json" \
  -d '[
    {"purchase_order_row_id": 46012001, "quantity": 5, "received_date": "2026-11-02T09:30:00.000Z"},
    {"purchase_order_row_id": 46012003, "quantity": 3, "received_date": "2026-11-02T09:30:00.000Z"},
    {"purchase_order_row_id": 46012002, "quantity": 1.5, "received_date": "2026-11-02T09:30:00.000Z"}
  ]'

The request returns 204. No row sends traceability, so each takes its pre-assigned entries, batches and serial numbers first:

  • Brake pads: 5 packs, 60 pcs, into bin A-02.
  • Hub motors: 3 pairs, the 6 serial numbers HM-0001 to HM-0006, four in A-01 and two in A-02.
  • Chain: 1.5 boxes, 15 pcs of batch CH-2610 into A-01.

The chain row was received in part, so it is split: a new row holds the 1.5 boxes received, with its received_date, and row 46012002 keeps the 2.5 boxes still to come. The PO is PARTIALLY_RECEIVED.

Receiving at another location with location_id keeps the pre-assigned batches and serial numbers but not their bins: the bins belong to the row's location.

Receive the rest

On Wednesday the other 2.5 boxes arrive, from batch CH-2611. No batch is pre-assigned for them, so a receipt without traceability would book them untraced. With Require traceability assignment on, it is refused:

{
  "error": {
    "statusCode": 422,
    "name": "UnprocessableEntityError",
    "code": "INVENTORY_SETTINGS_VIOLATED",
    "message": "Purchase order receipt violates inventory settings."
  }
}

Send the receipt's own traceability. Its entries replace the pre-assigned ones for this receipt, in the purchase unit like the quantity:

curl -X POST https://api.katanamrp.com/v1/purchase_order_receive \
  -H "Authorization: Bearer $KATANA_API_KEY" -H "Content-Type: application/json" \
  -d '{"purchase_order_row_id": 46012002, "quantity": 2.5, "received_date": "2026-11-04T14:00:00.000Z",
       "traceability": [{"batch_id": 3871302, "bin_location_id": 512002, "quantity": "2.5"}]}'

Batch CH-2611 (3871302) gets 25 pcs in A-02, and the PO is RECEIVED. Use several entries to split a receipt across batches or bins; serial entries take a serial_number_id and no quantity. Entries may not exceed the received quantity.

batch_transactions on a receipt is deprecated: use traceability. When both are sent, traceability is used.

Stock after the receipts

Stock is kept in the default unit:

ItemBinBatch / serial numberIn stock
Brake padsA-0260 pcs
ChainA-01CH-261015 pcs
ChainA-02CH-261125 pcs
Hub motorA-01HM-0001, HM-0002, HM-0003, HM-00044 pcs
Hub motorA-02HM-0005, HM-00062 pcs

Read it per bin and batch:

curl "https://api.katanamrp.com/v1/bin_inventory?location_id=160012&variant_id=24890211&granularity=BATCH" \
  -H "Authorization: Bearer $KATANA_API_KEY"
{
  "data": [
    {
      "location_id": 160012,
      "variant_id": 24890211,
      "batch_id": 3871301,
      "bin_location_id": 512001,
      "quantity_in_stock": "15.00000",
      "quantity_committed": "0.00000",
      "quantity_expected": "0.00000"
    },
    {
      "location_id": 160012,
      "variant_id": 24890211,
      "batch_id": 3871302,
      "bin_location_id": 512002,
      "quantity_in_stock": "25.00000",
      "quantity_committed": "0.00000",
      "quantity_expected": "0.00000"
    }
  ]
}

Use granularity=SERIAL_NUMBER for the hub motors. Bin inventory is updated asynchronously, so a receipt can take a moment to show.

Undo receipts

Set the PO back to NOT_RECEIVED to revert every receipt on it: the received rows return to the order and their stock leaves the bins.

curl -X PATCH https://api.katanamrp.com/v1/purchase_orders/3120415 \
  -H "Authorization: Bearer $KATANA_API_KEY" -H "Content-Type: application/json" \
  -d '{"status": "NOT_RECEIVED"}'

A single receipt can't be reverted on its own through the API.


Did this page help you?