Packing & shipping

Called with factory account keys. A key only sees its own account's data. Every example uses the same sample brand, order and item, so you can follow one item from call to call.

Base URL http://62.169.23.239:8001/api/v1Auth Bearer token9 endpoints

List Sealed Boxes#

GET/factory/packing/orders/{order_id}/boxes

Requires scope packing:read

Parameters

  • order_idstringpathRequired

    Skannit's id for the production order. Use it in every /production-orders/{order_id} and QR call.

Returns

HTTP 200
  • box_idstringRequired

    Id printed on the box label. Scanning the box resolves to this id.

  • sealed_attimestampRequired
  • sealed_bystringRequired
  • total_unitsintegerRequired
  • unit_tokensarray of strings

    Tokens of the items involved.

  • linesarray of objects

    Line items, one per variant.

    +Show 5 child attributes
    • colorstringRequired

      Colour name, exactly as on the product's variants.

    • sizestringRequired

      Size name, exactly as on the product's variants.

    • skustring | null

      Stock-keeping unit of the variant.

    • product_namestringRequired
    • quantityintegerRequired

      Number of units.

  • logistics_box_idstring | null
  • dispatch_idstring | null

    The shipment to a shop.

  • scan_urlstring | null

    URL encoded in the item's QR code. Opening it shows the passport.

  • weight_kgstring | null
GET /factory/packing/orders/{order_id}/boxes
curl
curl http://62.169.23.239:8001/api/v1/factory/packing/orders/ord_8c2f4e1a9b7d3c60/boxes \
  -H "Authorization: Bearer $SKANNIT_TOKEN"
200Response
json
[
  {
    "box_id": "BOX-F4E1A9-0003",
    "sealed_at": "2026-10-09T09:30:00Z",
    "sealed_by": "packer@portoknit.example",
    "total_units": 24,
    "unit_tokens": [
      "Qm7xK2pL9vR4tY8wZ1nB3c"
    ],
    "lines": [
      {
        "color": "White",
        "size": "M",
        "sku": "TT-100-WHT-M",
        "product_name": "Trail Tee",
        "quantity": 1
      }
    ],
    "logistics_box_id": "SKN-CRT-00402-9A1C3E7F",
    "dispatch_id": "b42d4ac7-4d7d-544e-99d3-941dad44d03a",
    "scan_url": "https://files.skannit.example/scan.png",
    "weight_kg": 11.6
  }
]

Printable QR label for a sealed box#

GET/factory/packing/orders/{order_id}/boxes/{box_id}/label.svg

Requires scope packing:read

SVG QR encoding the box's public scan URL, for sticking on the carton.

Only sealed boxes have one — an active box's id is not yet permanent.

Parameters

  • order_idstringpathRequired

    Skannit's id for the production order. Use it in every /production-orders/{order_id} and QR call.

  • box_idstringpathRequired

    Id printed on the box label. Scanning the box resolves to this id.

Returns

HTTP 200

No body.

GET /factory/packing/orders/{order_id}/boxes/{box_id}/label.svg
curl
curl http://62.169.23.239:8001/api/v1/factory/packing/orders/ord_8c2f4e1a9b7d3c60/boxes/BOX-F4E1A9-0003/label.svg \
  -H "Authorization: Bearer $SKANNIT_TOKEN"
200Response
json
// 200 — no body

Get Packing Session#

GET/factory/packing/orders/{order_id}/session

Requires scope packing:read

Parameters

  • order_idstringpathRequired

    Skannit's id for the production order. Use it in every /production-orders/{order_id} and QR call.

Returns

HTTP 200
  • order_idstringRequired

    Skannit's id for the production order. Use it in every /production-orders/{order_id} and QR call.

  • active_box_idstringRequired
  • active_unit_tokensarray of strings
  • active_started_attimestampRequired
  • box_capacityinteger

    Defaults to 120

  • sealed_boxesarray of objects
    +Show 10 child attributes
    • box_idstringRequired

      Id printed on the box label. Scanning the box resolves to this id.

    • sealed_attimestampRequired
    • sealed_bystringRequired
    • total_unitsintegerRequired
    • unit_tokensarray of strings

      Tokens of the items involved.

    • linesarray of objects

      Line items, one per variant.

      +Show 5 child attributes
      • colorstringRequired

        Colour name, exactly as on the product's variants.

      • sizestringRequired

        Size name, exactly as on the product's variants.

      • skustring | null

        Stock-keeping unit of the variant.

      • product_namestringRequired
      • quantityintegerRequired

        Number of units.

    • logistics_box_idstring | null
    • dispatch_idstring | null

      The shipment to a shop.

    • scan_urlstring | null

      URL encoded in the item's QR code. Opening it shows the passport.

    • weight_kgstring | null
  • dispatch_initialized_attimestamp | null
  • custody_tx_queuedinteger | null

    Custody-transfer chain transactions queued for the box just sealed. Null when this response isn't the result of sealing a box.

  • has_box_planboolean

    Whether the brand configured a logistics_plan box list for this order.

    Defaults to false

  • plan_box_idstring | null

    Brand-assigned id of the plan box the active box must fulfil, when has_box_plan is true.

  • plan_linesarray of objects

    Required color/size/quantity composition for the active box, from the brand's plan.

    +Show 3 child attributes
    • colorstringRequired

      Colour name, exactly as on the product's variants.

    • sizestringRequired

      Size name, exactly as on the product's variants.

    • quantityintegerRequired

      Number of units.

  • plan_boxes_totalinteger

    Total number of boxes in the brand's plan, for progress display (e.g. box 2 of 5).

    Defaults to 0

  • plan_box_sequenceinteger | null

    1-indexed position of the active box within the brand's plan box list.

GET /factory/packing/orders/{order_id}/session
curl
curl http://62.169.23.239:8001/api/v1/factory/packing/orders/ord_8c2f4e1a9b7d3c60/session \
  -H "Authorization: Bearer $SKANNIT_TOKEN"
200Response
json
{
  "order_id": "ord_8c2f4e1a9b7d3c60",
  "active_box_id": "943e1de8-71fd-52c4-9719-67f231baead4",
  "active_unit_tokens": [
    "active unit token"
  ],
  "active_started_at": "2026-10-09T09:30:00Z",
  "box_capacity": 120,
  "sealed_boxes": [
    {
      "box_id": "BOX-F4E1A9-0003",
      "sealed_at": "2026-10-09T09:30:00Z",
      "sealed_by": "packer@portoknit.example",
      "total_units": 24,
      "unit_tokens": [
        "Qm7xK2pL9vR4tY8wZ1nB3c"
      ],
      "lines": [
        {
          "color": "White",
          "size": "M",
          "sku": "TT-100-WHT-M",
          "product_name": "Trail Tee",
          "quantity": 1
        }
      ],
      "logistics_box_id": "SKN-CRT-00402-9A1C3E7F",
      "dispatch_id": "b42d4ac7-4d7d-544e-99d3-941dad44d03a",
      "scan_url": "https://files.skannit.example/scan.png",
      "weight_kg": 11.6
    }
  ],
  "dispatch_initialized_at": null,
  "custody_tx_queued": 1,
  "has_box_plan": false,
  "plan_box_id": "9e6aa029-c02d-538d-bf4b-500770397c38",
  "plan_lines": [
    {
      "color": "White",
      "size": "M",
      "quantity": 1
    }
  ],
  "plan_boxes_total": 1,
  "plan_box_sequence": 1
}

List Packing Queue#

GET/factory/packing/queue

Requires scope packing:read

Orders ready for or in progress at the packing station.

Returns

HTTP 200
  • itemsarray of objects

    The objects on this page.

    +Show 12 child attributes
    • order_idstringRequired

      Skannit's id for the production order. Use it in every /production-orders/{order_id} and QR call.

    • order_display_idstringRequired

      Order number formatted for display (#PO-YYYY-XXXX).

    • brand_namestringRequired
    • product_namestringRequired
    • flow_typestringRequired

      standard = the factory knows each item's variant when printing; variable = variants are assigned at QC.

    • total_unitsinteger

      Defaults to 0

    • packed_unitsinteger

      Defaults to 0

    • sealed_boxesinteger

      Defaults to 0

    • active_unitsinteger

      Defaults to 0

    • expected_boxesinteger

      Defaults to 0

    • statusstringRequired

      Current state of the object. See the allowed values.

      One ofREADYIN_PROGRESSQC_REQUIREDLABELS_PENDINGDISPATCH_READY
    • status_labelstringRequired
  • totalinteger

    Total count.

    Defaults to 0

GET /factory/packing/queue
curl
curl http://62.169.23.239:8001/api/v1/factory/packing/queue \
  -H "Authorization: Bearer $SKANNIT_TOKEN"
200Response
json
{
  "items": [
    {
      "order_id": "ord_8c2f4e1a9b7d3c60",
      "order_display_id": "#PO-2026-7F3A",
      "brand_name": "Northwind Apparel",
      "product_name": "Trail Tee",
      "flow_type": "flow type",
      "total_units": 24,
      "packed_units": 24,
      "sealed_boxes": 24,
      "active_units": 24,
      "expected_boxes": 24,
      "status": "READY",
      "status_label": "Available"
    }
  ],
  "total": 1
}

Seal Active Box#

POST/factory/packing/orders/{order_id}/boxes/seal

Requires scope packing:write

Parameters

  • order_idstringpathRequired

    Skannit's id for the production order. Use it in every /production-orders/{order_id} and QR call.

Request body

  • sealed_bystring | null
  • weight_kgany | null

    TR-04: gross weight of the sealed carton, in kilograms (0.001–999.999).

Returns

HTTP 200
  • order_idstringRequired

    Skannit's id for the production order. Use it in every /production-orders/{order_id} and QR call.

  • active_box_idstringRequired
  • active_unit_tokensarray of strings
  • active_started_attimestampRequired
  • box_capacityinteger

    Defaults to 120

  • sealed_boxesarray of objects
    +Show 10 child attributes
    • box_idstringRequired

      Id printed on the box label. Scanning the box resolves to this id.

    • sealed_attimestampRequired
    • sealed_bystringRequired
    • total_unitsintegerRequired
    • unit_tokensarray of strings

      Tokens of the items involved.

    • linesarray of objects

      Line items, one per variant.

      +Show 5 child attributes
      • colorstringRequired

        Colour name, exactly as on the product's variants.

      • sizestringRequired

        Size name, exactly as on the product's variants.

      • skustring | null

        Stock-keeping unit of the variant.

      • product_namestringRequired
      • quantityintegerRequired

        Number of units.

    • logistics_box_idstring | null
    • dispatch_idstring | null

      The shipment to a shop.

    • scan_urlstring | null

      URL encoded in the item's QR code. Opening it shows the passport.

    • weight_kgstring | null
  • dispatch_initialized_attimestamp | null
  • custody_tx_queuedinteger | null

    Custody-transfer chain transactions queued for the box just sealed. Null when this response isn't the result of sealing a box.

  • has_box_planboolean

    Whether the brand configured a logistics_plan box list for this order.

    Defaults to false

  • plan_box_idstring | null

    Brand-assigned id of the plan box the active box must fulfil, when has_box_plan is true.

  • plan_linesarray of objects

    Required color/size/quantity composition for the active box, from the brand's plan.

    +Show 3 child attributes
    • colorstringRequired

      Colour name, exactly as on the product's variants.

    • sizestringRequired

      Size name, exactly as on the product's variants.

    • quantityintegerRequired

      Number of units.

  • plan_boxes_totalinteger

    Total number of boxes in the brand's plan, for progress display (e.g. box 2 of 5).

    Defaults to 0

  • plan_box_sequenceinteger | null

    1-indexed position of the active box within the brand's plan box list.

POST /factory/packing/orders/{order_id}/boxes/seal
curl
curl -X POST http://62.169.23.239:8001/api/v1/factory/packing/orders/ord_8c2f4e1a9b7d3c60/boxes/seal \
  -H "Authorization: Bearer $SKANNIT_TOKEN" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{
    "weight_kg": 11.6
  }'
200Response
json
{
  "order_id": "ord_8c2f4e1a9b7d3c60",
  "active_box_id": "943e1de8-71fd-52c4-9719-67f231baead4",
  "active_unit_tokens": [
    "active unit token"
  ],
  "active_started_at": "2026-10-09T09:30:00Z",
  "box_capacity": 120,
  "sealed_boxes": [
    {
      "box_id": "BOX-F4E1A9-0003",
      "sealed_at": "2026-10-09T09:30:00Z",
      "sealed_by": "packer@portoknit.example",
      "total_units": 24,
      "unit_tokens": [
        "Qm7xK2pL9vR4tY8wZ1nB3c"
      ],
      "lines": [
        {
          "color": "White",
          "size": "M",
          "sku": "TT-100-WHT-M",
          "product_name": "Trail Tee",
          "quantity": 1
        }
      ],
      "logistics_box_id": "SKN-CRT-00402-9A1C3E7F",
      "dispatch_id": "b42d4ac7-4d7d-544e-99d3-941dad44d03a",
      "scan_url": "https://files.skannit.example/scan.png",
      "weight_kg": 11.6
    }
  ],
  "dispatch_initialized_at": null,
  "custody_tx_queued": 1,
  "has_box_plan": false,
  "plan_box_id": "9e6aa029-c02d-538d-bf4b-500770397c38",
  "plan_lines": [
    {
      "color": "White",
      "size": "M",
      "quantity": 1
    }
  ],
  "plan_boxes_total": 1,
  "plan_box_sequence": 1
}

Initialize Packing Dispatch#

POST/factory/packing/orders/{order_id}/dispatch/initialize

Requires scope packing:write

Parameters

  • order_idstringpathRequired

    Skannit's id for the production order. Use it in every /production-orders/{order_id} and QR call.

Returns

HTTP 200
  • order_idstringRequired

    Skannit's id for the production order. Use it in every /production-orders/{order_id} and QR call.

  • active_box_idstringRequired
  • active_unit_tokensarray of strings
  • active_started_attimestampRequired
  • box_capacityinteger

    Defaults to 120

  • sealed_boxesarray of objects
    +Show 10 child attributes
    • box_idstringRequired

      Id printed on the box label. Scanning the box resolves to this id.

    • sealed_attimestampRequired
    • sealed_bystringRequired
    • total_unitsintegerRequired
    • unit_tokensarray of strings

      Tokens of the items involved.

    • linesarray of objects

      Line items, one per variant.

      +Show 5 child attributes
      • colorstringRequired

        Colour name, exactly as on the product's variants.

      • sizestringRequired

        Size name, exactly as on the product's variants.

      • skustring | null

        Stock-keeping unit of the variant.

      • product_namestringRequired
      • quantityintegerRequired

        Number of units.

    • logistics_box_idstring | null
    • dispatch_idstring | null

      The shipment to a shop.

    • scan_urlstring | null

      URL encoded in the item's QR code. Opening it shows the passport.

    • weight_kgstring | null
  • dispatch_initialized_attimestamp | null
  • custody_tx_queuedinteger | null

    Custody-transfer chain transactions queued for the box just sealed. Null when this response isn't the result of sealing a box.

  • has_box_planboolean

    Whether the brand configured a logistics_plan box list for this order.

    Defaults to false

  • plan_box_idstring | null

    Brand-assigned id of the plan box the active box must fulfil, when has_box_plan is true.

  • plan_linesarray of objects

    Required color/size/quantity composition for the active box, from the brand's plan.

    +Show 3 child attributes
    • colorstringRequired

      Colour name, exactly as on the product's variants.

    • sizestringRequired

      Size name, exactly as on the product's variants.

    • quantityintegerRequired

      Number of units.

  • plan_boxes_totalinteger

    Total number of boxes in the brand's plan, for progress display (e.g. box 2 of 5).

    Defaults to 0

  • plan_box_sequenceinteger | null

    1-indexed position of the active box within the brand's plan box list.

POST /factory/packing/orders/{order_id}/dispatch/initialize
curl
curl -X POST http://62.169.23.239:8001/api/v1/factory/packing/orders/ord_8c2f4e1a9b7d3c60/dispatch/initialize \
  -H "Authorization: Bearer $SKANNIT_TOKEN" \
  -H "Idempotency-Key: $(uuidgen)"
200Response
json
{
  "order_id": "ord_8c2f4e1a9b7d3c60",
  "active_box_id": "943e1de8-71fd-52c4-9719-67f231baead4",
  "active_unit_tokens": [
    "active unit token"
  ],
  "active_started_at": "2026-10-09T09:30:00Z",
  "box_capacity": 120,
  "sealed_boxes": [
    {
      "box_id": "BOX-F4E1A9-0003",
      "sealed_at": "2026-10-09T09:30:00Z",
      "sealed_by": "packer@portoknit.example",
      "total_units": 24,
      "unit_tokens": [
        "Qm7xK2pL9vR4tY8wZ1nB3c"
      ],
      "lines": [
        {
          "color": "White",
          "size": "M",
          "sku": "TT-100-WHT-M",
          "product_name": "Trail Tee",
          "quantity": 1
        }
      ],
      "logistics_box_id": "SKN-CRT-00402-9A1C3E7F",
      "dispatch_id": "b42d4ac7-4d7d-544e-99d3-941dad44d03a",
      "scan_url": "https://files.skannit.example/scan.png",
      "weight_kg": 11.6
    }
  ],
  "dispatch_initialized_at": null,
  "custody_tx_queued": 1,
  "has_box_plan": false,
  "plan_box_id": "9e6aa029-c02d-538d-bf4b-500770397c38",
  "plan_lines": [
    {
      "color": "White",
      "size": "M",
      "quantity": 1
    }
  ],
  "plan_boxes_total": 1,
  "plan_box_sequence": 1
}

Scan Unit Into Box#

POST/factory/packing/orders/{order_id}/scan

Requires scope packing:write

Parameters

  • order_idstringpathRequired

    Skannit's id for the production order. Use it in every /production-orders/{order_id} and QR call.

Request body

  • unit_tokenstringRequired

    The item's own token. It is what the item's QR code carries, and the id every item event uses.

Returns

HTTP 200
  • order_idstringRequired

    Skannit's id for the production order. Use it in every /production-orders/{order_id} and QR call.

  • active_box_idstringRequired
  • active_unit_tokensarray of strings
  • active_started_attimestampRequired
  • box_capacityinteger

    Defaults to 120

  • sealed_boxesarray of objects
    +Show 10 child attributes
    • box_idstringRequired

      Id printed on the box label. Scanning the box resolves to this id.

    • sealed_attimestampRequired
    • sealed_bystringRequired
    • total_unitsintegerRequired
    • unit_tokensarray of strings

      Tokens of the items involved.

    • linesarray of objects

      Line items, one per variant.

      +Show 5 child attributes
      • colorstringRequired

        Colour name, exactly as on the product's variants.

      • sizestringRequired

        Size name, exactly as on the product's variants.

      • skustring | null

        Stock-keeping unit of the variant.

      • product_namestringRequired
      • quantityintegerRequired

        Number of units.

    • logistics_box_idstring | null
    • dispatch_idstring | null

      The shipment to a shop.

    • scan_urlstring | null

      URL encoded in the item's QR code. Opening it shows the passport.

    • weight_kgstring | null
  • dispatch_initialized_attimestamp | null
  • custody_tx_queuedinteger | null

    Custody-transfer chain transactions queued for the box just sealed. Null when this response isn't the result of sealing a box.

  • has_box_planboolean

    Whether the brand configured a logistics_plan box list for this order.

    Defaults to false

  • plan_box_idstring | null

    Brand-assigned id of the plan box the active box must fulfil, when has_box_plan is true.

  • plan_linesarray of objects

    Required color/size/quantity composition for the active box, from the brand's plan.

    +Show 3 child attributes
    • colorstringRequired

      Colour name, exactly as on the product's variants.

    • sizestringRequired

      Size name, exactly as on the product's variants.

    • quantityintegerRequired

      Number of units.

  • plan_boxes_totalinteger

    Total number of boxes in the brand's plan, for progress display (e.g. box 2 of 5).

    Defaults to 0

  • plan_box_sequenceinteger | null

    1-indexed position of the active box within the brand's plan box list.

POST /factory/packing/orders/{order_id}/scan
curl
curl -X POST http://62.169.23.239:8001/api/v1/factory/packing/orders/ord_8c2f4e1a9b7d3c60/scan \
  -H "Authorization: Bearer $SKANNIT_TOKEN" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{
    "unit_token": "Qm7xK2pL9vR4tY8wZ1nB3c"
  }'
200Response
json
{
  "order_id": "ord_8c2f4e1a9b7d3c60",
  "active_box_id": "943e1de8-71fd-52c4-9719-67f231baead4",
  "active_unit_tokens": [
    "active unit token"
  ],
  "active_started_at": "2026-10-09T09:30:00Z",
  "box_capacity": 120,
  "sealed_boxes": [
    {
      "box_id": "BOX-F4E1A9-0003",
      "sealed_at": "2026-10-09T09:30:00Z",
      "sealed_by": "packer@portoknit.example",
      "total_units": 24,
      "unit_tokens": [
        "Qm7xK2pL9vR4tY8wZ1nB3c"
      ],
      "lines": [
        {
          "color": "White",
          "size": "M",
          "sku": "TT-100-WHT-M",
          "product_name": "Trail Tee",
          "quantity": 1
        }
      ],
      "logistics_box_id": "SKN-CRT-00402-9A1C3E7F",
      "dispatch_id": "b42d4ac7-4d7d-544e-99d3-941dad44d03a",
      "scan_url": "https://files.skannit.example/scan.png",
      "weight_kg": 11.6
    }
  ],
  "dispatch_initialized_at": null,
  "custody_tx_queued": 1,
  "has_box_plan": false,
  "plan_box_id": "9e6aa029-c02d-538d-bf4b-500770397c38",
  "plan_lines": [
    {
      "color": "White",
      "size": "M",
      "quantity": 1
    }
  ],
  "plan_boxes_total": 1,
  "plan_box_sequence": 1
}

Shipping notice: ship sealed boxes with an external carrier#

POST/factory/transport/orders/{order_id}/shipments

Requires scope factory_shipments:write

Register and release a shipment of this order's sealed boxes (GS1 Despatch Advice). Skannit links the carrier's tracking; the receiver's scan is the proof of delivery and moves custody.

Parameters

  • order_idstringpathRequired

    Skannit's id for the production order. Use it in every /production-orders/{order_id} and QR call.

Request body

  • box_idsarray of strings

    Sealed box ids to ship. Empty = every sealed box of the order not already on a shipment.

  • ship_to_namestringRequired

    Receiving warehouse or shop name

  • ship_to_detailstring | null

    Address or dock

  • retail_idstring | null

    Receiving shop account, if known

  • carrierobjectRequired

    Carrier name, for example PostNL or DHL.

    +Show 3 child attributes
    • namestringRequired

      Carrier or 3PL, e.g. DHL Express, Maersk, a local courier

    • tracking_numberstringRequired

      Consignment / waybill / tracking reference

    • tracking_urlstring | null

      Carrier's public tracking page for live location

  • expected_deliverydate | null

    Date the goods should leave the factory.

  • transport_modestring
    One oflocalinternational

    Defaults to local

  • notesstring | null

Returns

HTTP 201
  • dispatch_idstringRequired

    The shipment to a shop.

  • order_idstringRequired

    Skannit's id for the production order. Use it in every /production-orders/{order_id} and QR call.

  • order_display_idstringRequired

    Order number formatted for display (#PO-YYYY-XXXX).

  • brand_namestring | null
  • statusstringRequired

    Current state of the object. See the allowed values.

    One ofdraftassignedin_transitdeliveredcancelled
  • transport_modestring
    One oflocalinternational

    Defaults to local

  • estimated_deliverydate | null
  • eta_labelstring | null
  • is_delayedboolean

    Defaults to false

  • journey_progress_percentinteger

    Defaults to 0

  • journey_progress_labelstring

    Defaults to

  • conversation_idstring | null
  • origin_station_namestring | null
  • origin_station_detailstring | null
  • destination_hub_namestring | null
  • destination_hub_detailstring | null
  • origin_gps_latnumber | null

    Fixed endpoints, so the journey map can plot where the shipment runs between rather than only the legs the driver pinned.

  • origin_gps_lngnumber | null
  • destination_gps_latnumber | null
  • destination_gps_lngnumber | null
  • retail_idstring | null

    The shop (retail account) id.

  • retail_namestring | null
  • dispatch_notesstring | null
  • carrier_typestringRequired
    One ofskannit_riderexternal_carrierbrand_fleet
  • carrier_providerstring | null
    One ofdhlglspostnlother
  • carrier_tracking_numberstring | null
  • carrier_namestring | null
  • carrier_tracking_urlstring | null
  • transporter_idstring | null
  • transporter_namestring | null
  • driver_namestring | null
  • vehicle_platestring | null
  • driver_contactstring | null
  • total_boxesinteger

    Defaults to 0

  • total_quantityinteger

    Defaults to 0

  • total_weight_kgstring | null
  • itemsarray of objects

    The objects on this page.

    +Show 2 child attributes
    • product_namestringRequired
    • quantityintegerRequired

      Number of units.

  • boxesarray of objects
    +Show 7 child attributes
    • box_idstringRequired

      Id printed on the box label. Scanning the box resolves to this id.

    • box_labelstringRequired
    • unit_countintegerRequired
    • unit_tokensarray of strings

      Tokens of the items involved.

    • statusstringRequired

      Current state of the object. See the allowed values.

      One ofnormalflaggeddelayedin_transitdelivered
    • last_locationstring | null
    • last_location_attimestamp | null
  • milestonesarray of objects
    +Show 23 child attributes
    • milestone_idstringRequired
    • event_typestringRequired
    • titlestringRequired
    • detailstring | null
    • occurred_attimestamp | null

      Null until the leg is reached — arrival time.

    • is_currentboolean

      Defaults to false

    • statusstring

      Current state of the object. See the allowed values.

      One ofpendingplannedin_transitreachedskipped

      Defaults to reached

    • sequence_positioninteger | null
    • modestring | null
      One ofroadseaairrailother
    • location_namestring | null
    • planned_attimestamp | null
    • gps_latnumber | null
    • gps_lngnumber | null
    • departed_attimestamp | null

      Departure side of the leg — null until the driver taps Depart.

    • departed_gps_latnumber | null
    • departed_gps_lngnumber | null
    • place_namestring | null

      Human-readable places, resolved on-device at capture time. The UI shows these instead of coordinates.

    • departed_place_namestring | null
    • transporter_idstring | null
    • transporter_namestring | null
    • estimated_arrival_attimestamp | null

      Projection from the driver's own observed speed across completed legs. Null until at least one leg has been completed — before that there is no measured speed and any figure would be invented.

    • is_delayedboolean

      Server-computed so two clients can't disagree; the device clock belongs to the driver and is not trustworthy for this.

      Defaults to false

    • delay_minutesinteger | null

      Signed minutes late (positive) or early (negative) vs planned_at.

  • alertobject | null
    +Show 5 child attributes
    • titlestringRequired
    • detailstringRequired
    • severitystring
      One ofcriticalwarninginfo

      Defaults to warning

    • acknowledgedboolean

      Defaults to false

    • route_deviation_kmnumber | null
  • dispatched_attimestamp | null
  • picked_up_attimestamp | null
  • delivered_attimestamp | null

    When the parcel was reported delivered — the moment ownership moved.

  • pod_photo_urlstring | null
  • created_attimestampRequired

    When the object was created (ISO 8601, UTC).

  • updated_attimestampRequired

    When the object last changed (ISO 8601, UTC).

  • last_updated_labelstring | null
  • repair_request_idinteger | null

    Set on a repair leg (consumer <-> repair shop); the transporter may decline it before pickup.

  • repair_legstring | null
  • logistics_planobject | null
    +Show 2 child attributes
    • boxesarray of objects
      +Show 6 child attributes
      • idstringRequired
      • modestringRequired
        One ofsamemixed
      • capacityintegerRequired
      • regionstring | null
      • linesarray of objectsRequired

        Line items, one per variant.

        +Show 5 child attributes
        • colorstringRequired

          Colour name, exactly as on the product's variants.

        • sizestringRequired

          Size name, exactly as on the product's variants.

        • batch_skustring | null

          SKU printed on the label for this variant in this batch.

        • quantityintegerRequired

          Number of units.

        • volume_lstring | null

          Packaged volume of one unit, in litres. Used to size boxes.

      • created_atstring | null

        When the object was created (ISO 8601, UTC).

    • destinationsarray of objects
      +Show 8 child attributes
      • idstringRequired
      • namestringRequired
      • citystring | null
      • countrystringRequired
      • arrival_datestring | null
      • prioritystring
        One oflowstandardurgent

        Defaults to standard

      • box_idsarray of strings

        Ids of the boxes this call acts on.

      • instructionsstring

        Defaults to

  • custody_tx_queuedinteger | null

    Number of custody-transfer chain transactions successfully queued for this status change (factory->transporter on take-custody, transporter->retail on delivery). Null when the action taken didn't trigger a custody transfer (e.g. plain detail fetch).

POST /factory/transport/orders/{order_id}/shipments
curl
curl -X POST http://62.169.23.239:8001/api/v1/factory/transport/orders/ord_8c2f4e1a9b7d3c60/shipments \
  -H "Authorization: Bearer $SKANNIT_TOKEN" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{
    "ship_to_name": "Ship to",
    "retail_id": "4974bf7c-8314-5bb9-9f74-8c1497523eb5",
    "carrier": "PostNL",
    "notes": "Received at dock 3"
  }'
201Response
json
{
  "dispatch_id": "b42d4ac7-4d7d-544e-99d3-941dad44d03a",
  "order_id": "ord_8c2f4e1a9b7d3c60",
  "order_display_id": "#PO-2026-7F3A",
  "brand_name": "Northwind Apparel",
  "status": "draft",
  "transport_mode": "local",
  "estimated_delivery": "2026-11-20",
  "eta_label": "Arrives Sat 11 Oct",
  "is_delayed": false,
  "journey_progress_percent": 72,
  "journey_progress_label": "",
  "conversation_id": "14b1be4a-c85b-528b-bb05-270ec6fea314",
  "origin_station_name": "Rotterdam DC",
  "origin_station_detail": "Waalhaven 12, Rotterdam",
  "destination_hub_name": "Northwind Amsterdam",
  "destination_hub_detail": "Kalverstraat 1, Amsterdam",
  "origin_gps_lat": 51.9244,
  "origin_gps_lng": 4.4777,
  "destination_gps_lat": 51.9244,
  "destination_gps_lng": 4.4777,
  "retail_id": "4974bf7c-8314-5bb9-9f74-8c1497523eb5",
  "retail_name": "Northwind Amsterdam",
  "dispatch_notes": "Deliver before 10:00",
  "carrier_type": "skannit_rider",
  "carrier_provider": "PostNL",
  "carrier_tracking_number": "3SNWD1234567890",
  "carrier_name": "Carrier",
  "carrier_tracking_url": "https://files.skannit.example/carrier_tracking.png",
  "transporter_id": "f74f2d3e-d02f-58f6-b03b-795142c1e5d9",
  "transporter_name": "FastFreight BV",
  "driver_name": "Jan de Vries",
  "vehicle_plate": "VX-123-B",
  "driver_contact": "+31687654321",
  "total_boxes": 24,
  "total_quantity": 24,
  "total_weight_kg": 11.6,
  "items": [
    {
      "product_name": "Trail Tee",
      "quantity": 1
    }
  ],
  "boxes": [
    {
      "box_id": "BOX-F4E1A9-0003",
      "box_label": "Box",
      "unit_count": 24,
      "unit_tokens": [
        "Qm7xK2pL9vR4tY8wZ1nB3c"
      ],
      "status": "normal",
      "last_location": "A15 near Rotterdam",
      "last_location_at": null
    }
  ],
  "milestones": [
    {
      "milestone_id": "9e787ca7-0de0-5952-bc10-0063d6ab12de",
      "event_type": "picked_up",
      "title": "Delayed at depot",
      "detail": "Box BOX-F4E1A9-0003 manifest says 48 units",
      "occurred_at": null,
      "is_current": false,
      "status": "pending",
      "sequence_position": 1,
      "mode": "road",
      "location_name": "Rotterdam DC",
      "planned_at": null,
      "gps_lat": 51.9244,
      "gps_lng": 4.4777,
      "departed_at": null,
      "departed_gps_lat": 51.9244,
      "departed_gps_lng": 4.4777,
      "place_name": "Rotterdam",
      "departed_place_name": "Departed place",
      "transporter_id": "f74f2d3e-d02f-58f6-b03b-795142c1e5d9",
      "transporter_name": "FastFreight BV",
      "estimated_arrival_at": null,
      "is_delayed": false,
      "delay_minutes": 1
    }
  ],
  "alert": {
    "title": "Delayed at depot",
    "detail": "Box BOX-F4E1A9-0003 manifest says 48 units",
    "severity": "critical",
    "acknowledged": false,
    "route_deviation_km": 1
  },
  "dispatched_at": null,
  "picked_up_at": null,
  "delivered_at": null,
  "pod_photo_url": "https://files.skannit.example/pod_photo.png",
  "created_at": "2026-10-09T09:30:00Z",
  "updated_at": "2026-10-09T09:30:00Z",
  "last_updated_label": "2 minutes ago",
  "repair_request_id": 1,
  "repair_leg": "repair leg",
  "logistics_plan": {
    "boxes": [
      {
        "id": "SKN-CRT-00402-9A1C3E7F",
        "mode": "same",
        "capacity": 1,
        "region": "EU",
        "lines": [
          {
            "color": "White",
            "size": "M",
            "batch_sku": "TT-100-WHT-M",
            "quantity": 1,
            "volume_l": 0.5
          }
        ],
        "created_at": "2026-10-09T09:30:00Z"
      }
    ],
    "destinations": [
      "in_store"
    ]
  },
  "custody_tx_queued": 1
}

Upsert Packing Session#

PUT/factory/packing/orders/{order_id}/session

Requires scope packing:write

Parameters

  • order_idstringpathRequired

    Skannit's id for the production order. Use it in every /production-orders/{order_id} and QR call.

Request body

  • active_box_idstring | null
  • active_unit_tokensarray of strings | null
  • box_capacityinteger | null

Returns

HTTP 200
  • order_idstringRequired

    Skannit's id for the production order. Use it in every /production-orders/{order_id} and QR call.

  • active_box_idstringRequired
  • active_unit_tokensarray of strings
  • active_started_attimestampRequired
  • box_capacityinteger

    Defaults to 120

  • sealed_boxesarray of objects
    +Show 10 child attributes
    • box_idstringRequired

      Id printed on the box label. Scanning the box resolves to this id.

    • sealed_attimestampRequired
    • sealed_bystringRequired
    • total_unitsintegerRequired
    • unit_tokensarray of strings

      Tokens of the items involved.

    • linesarray of objects

      Line items, one per variant.

      +Show 5 child attributes
      • colorstringRequired

        Colour name, exactly as on the product's variants.

      • sizestringRequired

        Size name, exactly as on the product's variants.

      • skustring | null

        Stock-keeping unit of the variant.

      • product_namestringRequired
      • quantityintegerRequired

        Number of units.

    • logistics_box_idstring | null
    • dispatch_idstring | null

      The shipment to a shop.

    • scan_urlstring | null

      URL encoded in the item's QR code. Opening it shows the passport.

    • weight_kgstring | null
  • dispatch_initialized_attimestamp | null
  • custody_tx_queuedinteger | null

    Custody-transfer chain transactions queued for the box just sealed. Null when this response isn't the result of sealing a box.

  • has_box_planboolean

    Whether the brand configured a logistics_plan box list for this order.

    Defaults to false

  • plan_box_idstring | null

    Brand-assigned id of the plan box the active box must fulfil, when has_box_plan is true.

  • plan_linesarray of objects

    Required color/size/quantity composition for the active box, from the brand's plan.

    +Show 3 child attributes
    • colorstringRequired

      Colour name, exactly as on the product's variants.

    • sizestringRequired

      Size name, exactly as on the product's variants.

    • quantityintegerRequired

      Number of units.

  • plan_boxes_totalinteger

    Total number of boxes in the brand's plan, for progress display (e.g. box 2 of 5).

    Defaults to 0

  • plan_box_sequenceinteger | null

    1-indexed position of the active box within the brand's plan box list.

PUT /factory/packing/orders/{order_id}/session
curl
curl -X PUT http://62.169.23.239:8001/api/v1/factory/packing/orders/ord_8c2f4e1a9b7d3c60/session \
  -H "Authorization: Bearer $SKANNIT_TOKEN" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{}'
200Response
json
{
  "order_id": "ord_8c2f4e1a9b7d3c60",
  "active_box_id": "943e1de8-71fd-52c4-9719-67f231baead4",
  "active_unit_tokens": [
    "active unit token"
  ],
  "active_started_at": "2026-10-09T09:30:00Z",
  "box_capacity": 120,
  "sealed_boxes": [
    {
      "box_id": "BOX-F4E1A9-0003",
      "sealed_at": "2026-10-09T09:30:00Z",
      "sealed_by": "packer@portoknit.example",
      "total_units": 24,
      "unit_tokens": [
        "Qm7xK2pL9vR4tY8wZ1nB3c"
      ],
      "lines": [
        {
          "color": "White",
          "size": "M",
          "sku": "TT-100-WHT-M",
          "product_name": "Trail Tee",
          "quantity": 1
        }
      ],
      "logistics_box_id": "SKN-CRT-00402-9A1C3E7F",
      "dispatch_id": "b42d4ac7-4d7d-544e-99d3-941dad44d03a",
      "scan_url": "https://files.skannit.example/scan.png",
      "weight_kg": 11.6
    }
  ],
  "dispatch_initialized_at": null,
  "custody_tx_queued": 1,
  "has_box_plan": false,
  "plan_box_id": "9e6aa029-c02d-538d-bf4b-500770397c38",
  "plan_lines": [
    {
      "color": "White",
      "size": "M",
      "quantity": 1
    }
  ],
  "plan_boxes_total": 1,
  "plan_box_sequence": 1
}