Pack an order with PackPilot (Arcus auto-pack)
Rule 25 dual-dispatch fix (2026-05-29): This endpoint was previously only
accessible via Cognito-JWT (/fulfillment/pack-order); API-key callers received
404. packOrderV1 is now wired in routes/api-v1/fulfillment.mjs per Rule 25.
Runs the PackPilot 3D bin-packing algorithm against an unpacked (or partially
packed) order. Creates one or more Package objects optimally sized to the
entity’s active box inventory, allocates inventory, and (if configured) auto-rates
and auto-buys Shippo labels in the same call.
Authorization: requires fulfillment:write API-key scope AND the per-user
fulfillment.pack permission (SoD assertion inside canonical handler).
Layer 1: entity_id is always derived from the API key; any entity_id
in the request body is silently overwritten.
THE ONE RULE: delegates to the canonical packOrder handler in
routes/fulfillment.mjs. All PackPilot logic (bin-packing, location-shortfall
guard, label auto-buy, leftover persistence, incident-id error correlation)
lives in the canonical handler; bug fixes propagate automatically.
Idempotency: idempotent per Idempotency-Key header. If the order is
already fully packed, returns 409 all_items_already_packed.
Key request body fields:
order_id(required, UUID): the order to packauto_rate(boolean, optional): fetch Shippo rates for each created packageauto_buy_label(boolean, optional): purchase Shippo label for each package (requiresauto_rate: trueand a configured shipping rule)
Blocker codes (422):
location_shortfall_blocks_pack: all packable lines are out of stock at the order’s location. Response includesshort_lines[]with cross-location stock.ship_complete_blocked:ship_complete=trueand one or more lines have insufficient inventory to fully pack.packpilot_no_boxes: no active box products are configured for this entity.packpilot_circuit_open: PackPilot Lambda is unavailable; use Manual Pack.packpilot_item_too_large: at least one line item exceeds the largest box.repack_blocked_label_void_failed: a repack was attempted but an existing Shippo label could not be voided; resolve carrier-side before repacking.
Authorizations
API key issued per entity via Settings > Developers > API Keys.
Each key carries scopes (e.g. orders:read, products:write).
Bearer token format: Authorization: Bearer ark_live_ent_
Test keys use ark_test_ent_. Both are issued per entity
via Settings > Developers > API Keys.
Headers
Client-generated unique key for idempotent POST/PATCH/DELETE operations. Alias for the Idempotency parameter. Max 255 chars. On retry with the same key, the original response is returned without re-executing the operation. Keys expire after 24 hours.
255Body
The order to pack. Must be confirmed, not yet fully fulfilled.
Fetch Shippo carrier rates for each created package immediately after packing.
Purchase a Shippo label for each package using the best matching shipping
rule. Requires auto_rate: true. If label purchase fails for a package,
the error is returned in package_auto_labels[pkg_id].error (non-fatal).
Response
Order packed successfully.

