Skip to main content

Receive Shipment

POST 

/api/inbound-shipments/receive

Receive goods against a purchase order shipment. Creates a receipt record and triggers inventory movements.

Authentication: Requires Bearer token.

Async behavior (SKU-8063):

  • By default, this endpoint dispatches the receive to a background job chain and returns 202 Accepted with data.tracked_job_log_id. The frontend should open the global job tray (notifyJobStarted) and watch lastCompletedJob to refresh.
  • Pass ?async=0 to force the legacy synchronous response (200 with the receipt resource).
  • The async path is only taken when the payload is ad-hoc eligible: requires purchase_order_id, and rejects any payload that includes unexpected_items, inbound_shipment_id, or negative receipt_lines[].quantity. Ineligible payloads silently fall back to the sync path.
  • 409 Conflict is returned when a ProcessPurchaseOrderReceiptJob is already in flight (PENDING or PROCESSING) for the same purchase_order_id — the caller should tell the user to track progress in the job tray instead of retrying.

Fields:

  • purchase_order_id (conditional): Required if purchase_order_shipment_id is not provided. Required for the async path.
  • purchase_order_shipment_id (optional): Specific shipment ID to receive. If omitted, receives for the entire PO
  • received_at (required): Date/time of receipt
  • warehouse_id (optional): Override destination warehouse
  • shipment_date (optional): Used if a new shipment needs to be created automatically
  • shipping_method_id (optional): Shipping method for auto-created shipment
  • tracking (optional): Tracking number for auto-created shipment, max 255 characters
  • inbound_shipment_id (optional, exists:inbound_shipments,id): Route the whole receive against this specific inbound shipment. Restricts delegation to that shipment and over-receives it past its planned capacity if the received quantity exceeds what was expected. Used by the PO-detail receive drawer when the receiver explicitly picks a target shipment. Presence forces sync fallback.
  • force_new_shipment (optional, boolean): If true, skip auto-routing/delegation to existing planned shipments and create a brand-new ad-hoc inbound shipment for this receipt. Mutually exclusive in intent with inbound_shipment_id
  • receipt_lines (optional): Array of specific line quantities to receive. If omitted, receives all unreceived lines
  • receipt_lines[].purchase_order_shipment_line_id (conditional): Shipment line ID. Required without purchase_order_line_reference or purchase_order_line_id
  • receipt_lines[].purchase_order_line_id (conditional): PO line ID. Alternative to shipment_line_id
  • receipt_lines[].purchase_order_line_reference (conditional): PO line reference code. Alternative to IDs
  • receipt_lines[].quantity (required): Quantity received. Negative quantities force sync fallback.
  • unexpected_items (optional): Items received that were not on the original PO. Presence forces sync fallback.
  • unexpected_items[].product_id (conditional): Product ID. Required without product_sku
  • unexpected_items[].product_sku (conditional): Product SKU. Required without product_id
  • unexpected_items[].quantity (required): Quantity of unexpected item
  • unexpected_items[].action (optional): Action for unexpected item (e.g., add_to_inventory)
  • unexpected_items[].amount (optional): Unit cost for unexpected item
  • unexpected_items[].description (optional): Description for unexpected item

Request

Responses

Successful response