Warehouse pick & returns

Called with shop (retail) 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 token5 endpoints

Pick by order number#

POST/retail/integrations/fulfillment/orders/{external_order_id}/scan

Requires scope fulfillment:write

Pick scan by the shop's own order number: links the scanned unit's passport to the matching pending line of that order. item_id takes the raw scanned QR (any printed URL form) or a bare unit token. Same outcomes as the per-task scan; never transfers ownership.

Parameters

  • external_order_idstringpathRequired

    Your web shop's own order id. Skannit keys the order on it, so sending it twice does not create it twice.

Request body

  • item_idstring | null

    Scanned QR unit token — provenance_confidence 'high'

  • product_numberstring | null

    Hand-keyed fallback — provenance_confidence 'low'

Returns

HTTP 200
  • matchedbooleanRequired

    True when the scanned item was accepted. False is a normal answer (wrong item, already sold) — scan another.

  • task_idstringRequired

    One unit of a web order to pick. An order with quantity 3 creates 3 tasks.

  • statusstringRequired

    Current state of the object. See the allowed values.

    One ofpendingpickedshippeddeliveredcancelledrefusedlostreturn_requestedreturn_receivedreturnedreturn_rejected
  • provenance_confidencestring | null

    high when the item's history comes from the factory; low when it was registered later.

    One ofhighlow
  • unit_tokenstring | null

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

  • reasonstring | null
    One ofwrong_variantalready_linkedalready_solddamageddifferent_item
  • mismatchobject | null

    What was ordered vs. what was scanned. Spec §21: on a mismatch nothing fires and the worker rescans, so the response has to show both sides rather than a bare error.

    +Show 4 child attributes
    • ordered_product_idstring | null
    • ordered_variantstring | null
    • scanned_product_idstring | null
    • scanned_variantstring | null
  • detailstring | null
POST /retail/integrations/fulfillment/orders/{external_order_id}/scan
curl
curl -X POST http://62.169.23.239:8001/api/v1/retail/integrations/fulfillment/orders/1001/scan \
  -H "Authorization: Bearer $SKANNIT_TOKEN" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{
    "item_id": "http://62.169.23.239:8001/api/v1/scan/Qm7xK2pL9vR4tY8wZ1nB3c"
  }'
200Response
json
{
  "matched": true,
  "task_id": "266ac6a0-a008-5349-ae80-086961f95f9a",
  "status": "picked",
  "provenance_confidence": "high",
  "unit_token": "Qm7xK2pL9vR4tY8wZ1nB3c",
  "reason": null,
  "mismatch": null,
  "detail": null
}

Pick by task#

POST/retail/integrations/fulfillment/tasks/{task_id}/scan

Requires scope fulfillment:write

Pick scan: check the unit and link its passport to the order.

A failed check returns 200 with matched: false and a reason, a normal outcome the worker resolves by picking another item. Never transfers ownership.

Parameters

  • task_idstringpathRequired

    One unit of a web order to pick. An order with quantity 3 creates 3 tasks.

Request body

  • item_idstring | null

    Scanned QR unit token — provenance_confidence 'high'

  • product_numberstring | null

    Hand-keyed fallback — provenance_confidence 'low'

Returns

HTTP 200
  • matchedbooleanRequired

    True when the scanned item was accepted. False is a normal answer (wrong item, already sold) — scan another.

  • task_idstringRequired

    One unit of a web order to pick. An order with quantity 3 creates 3 tasks.

  • statusstringRequired

    Current state of the object. See the allowed values.

    One ofpendingpickedshippeddeliveredcancelledrefusedlostreturn_requestedreturn_receivedreturnedreturn_rejected
  • provenance_confidencestring | null

    high when the item's history comes from the factory; low when it was registered later.

    One ofhighlow
  • unit_tokenstring | null

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

  • reasonstring | null
    One ofwrong_variantalready_linkedalready_solddamageddifferent_item
  • mismatchobject | null

    What was ordered vs. what was scanned. Spec §21: on a mismatch nothing fires and the worker rescans, so the response has to show both sides rather than a bare error.

    +Show 4 child attributes
    • ordered_product_idstring | null
    • ordered_variantstring | null
    • scanned_product_idstring | null
    • scanned_variantstring | null
  • detailstring | null
POST /retail/integrations/fulfillment/tasks/{task_id}/scan
curl
curl -X POST http://62.169.23.239:8001/api/v1/retail/integrations/fulfillment/tasks/266ac6a0-a008-5349-ae80-086961f95f9a/scan \
  -H "Authorization: Bearer $SKANNIT_TOKEN" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{
    "item_id": "Qm7xK2pL9vR4tY8wZ1nB3c"
  }'
200Response
json
{
  "matched": true,
  "task_id": "266ac6a0-a008-5349-ae80-086961f95f9a",
  "status": "picked",
  "provenance_confidence": "high",
  "unit_token": "Qm7xK2pL9vR4tY8wZ1nB3c",
  "reason": null,
  "mismatch": null,
  "detail": null
}

Unlink a damaged item#

POST/retail/integrations/fulfillment/tasks/{task_id}/unlink

Requires scope fulfillment:write

Damaged at packing: write the unit off and return the order to pick.

Parameters

  • task_idstringpathRequired

    One unit of a web order to pick. An order with quantity 3 creates 3 tasks.

Request body

  • reasonstring

    Defaults to damaged

  • notestring | null

Returns

HTTP 200
  • task_idstringRequired

    One unit of a web order to pick. An order with quantity 3 creates 3 tasks.

  • sourcestringRequired
  • order_referencestring | null

    Order number your customer sees (for example #1001).

  • external_order_idstringRequired

    Your web shop's own order id. Skannit keys the order on it, so sending it twice does not create it twice.

  • product_idstring | null

    Skannit's id for the product.

  • product_namestring | null
  • assigned_variantstring | null

    Colour / size the order line asks for.

  • skustring | null

    Stock-keeping unit of the variant.

  • quantityinteger

    Number of units.

    Defaults to 1

  • buyer_emailstring | null

    GL-02: buyer identity is never sent out (always null); the order reference identifies the order. Kept in the schema only so the public v1 contract doesn't break. Stored on the task only to email the buyer.

  • buyer_phonestring | null

    Stored only. Matching is by email. Never returned in responses (always null).

  • buyer_namestring | null

    Never returned in responses (always null).

  • deadlinetimestamp | null

    When the order is promised. Drives the queue's ordering; NULL when the provider sent no SLA.

  • statusstring

    Current state of the object. See the allowed values.

    One ofpendingpickedshippeddeliveredcancelledrefusedlostreturn_requestedreturn_receivedreturnedreturn_rejected

    Defaults to pending

  • linked_unit_tokenstring | null

    The unit whose passport is linked to this order (set by the pick scan).

  • carrierstring | null

    Carrier name, for example PostNL or DHL.

  • tracking_numberstring | null

    The carrier's tracking number.

  • shipped_attimestamp | null

    When your web shop reported the parcel shipped.

  • delivered_attimestamp | null

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

  • is_matchableboolean

    False when the external SKU matched no Skannit product. Such a task is visible to a worker but cannot be picked until it is mapped.

    Defaults to true

  • created_attimestampRequired

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

POST /retail/integrations/fulfillment/tasks/{task_id}/unlink
curl
curl -X POST http://62.169.23.239:8001/api/v1/retail/integrations/fulfillment/tasks/266ac6a0-a008-5349-ae80-086961f95f9a/unlink \
  -H "Authorization: Bearer $SKANNIT_TOKEN" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{
    "reason": "damaged",
    "note": "Seam torn at packing"
  }'
200Response
json
{
  "task_id": "266ac6a0-a008-5349-ae80-086961f95f9a",
  "source": "web_shop",
  "order_reference": "#1001",
  "external_order_id": "1001",
  "product_id": "f6abe715-90aa-5908-a0a6-12951a3a21cc",
  "product_name": "Trail Tee",
  "assigned_variant": "White / M",
  "sku": "TT-100-WHT-M",
  "quantity": 1,
  "buyer_email": null,
  "buyer_phone": null,
  "buyer_name": null,
  "deadline": null,
  "status": "pending",
  "linked_unit_token": null,
  "carrier": "PostNL",
  "tracking_number": "3SNWD1234567890",
  "shipped_at": null,
  "delivered_at": null,
  "is_matchable": true,
  "created_at": "2026-10-09T09:30:00Z"
}

Receive a return#

POST/retail/integrations/fulfillment/tasks/{task_id}/receive

Requires scope fulfillment:write

Scan in a refused parcel (shipped) or a customer return (return_requested).

Parameters

  • task_idstringpathRequired

    One unit of a web order to pick. An order with quantity 3 creates 3 tasks.

Request body

  • item_idstring | null

    Scanned QR unit token — provenance_confidence 'high'

  • product_numberstring | null

    Hand-keyed fallback — provenance_confidence 'low'

Returns

HTTP 200
  • matchedbooleanRequired

    True when the scanned item was accepted. False is a normal answer (wrong item, already sold) — scan another.

  • task_idstringRequired

    One unit of a web order to pick. An order with quantity 3 creates 3 tasks.

  • statusstringRequired

    Current state of the object. See the allowed values.

    One ofpendingpickedshippeddeliveredcancelledrefusedlostreturn_requestedreturn_receivedreturnedreturn_rejected
  • provenance_confidencestring | null

    high when the item's history comes from the factory; low when it was registered later.

    One ofhighlow
  • unit_tokenstring | null

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

  • reasonstring | null
    One ofwrong_variantalready_linkedalready_solddamageddifferent_item
  • mismatchobject | null

    What was ordered vs. what was scanned. Spec §21: on a mismatch nothing fires and the worker rescans, so the response has to show both sides rather than a bare error.

    +Show 4 child attributes
    • ordered_product_idstring | null
    • ordered_variantstring | null
    • scanned_product_idstring | null
    • scanned_variantstring | null
  • detailstring | null
POST /retail/integrations/fulfillment/tasks/{task_id}/receive
curl
curl -X POST http://62.169.23.239:8001/api/v1/retail/integrations/fulfillment/tasks/266ac6a0-a008-5349-ae80-086961f95f9a/receive \
  -H "Authorization: Bearer $SKANNIT_TOKEN" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{
    "item_id": "Qm7xK2pL9vR4tY8wZ1nB3c"
  }'
200Response
json
{
  "matched": true,
  "task_id": "266ac6a0-a008-5349-ae80-086961f95f9a",
  "status": "return_received",
  "provenance_confidence": "high",
  "unit_token": "Qm7xK2pL9vR4tY8wZ1nB3c",
  "reason": null,
  "mismatch": null,
  "detail": "Box BOX-F4E1A9-0003 manifest says 48 units"
}

Inspect a return#

POST/retail/integrations/fulfillment/tasks/{task_id}/inspection

Requires scope fulfillment:write

Accept (passport back to the shop) or reject (stays with the customer).

Parameters

  • task_idstringpathRequired

    One unit of a web order to pick. An order with quantity 3 creates 3 tasks.

Request body

  • decisionstringRequired

    accept = the shop takes the passport back; reject = it stays with the customer.

    One ofacceptreject
  • next_stepstring | null

    Required to accept: what happens to the item once the shop owns it again.

    One ofrestockrepairrecycle
  • reasonstring | null

    Required to reject: why (worn, damaged by the customer, ...).

Returns

HTTP 200
  • task_idstringRequired

    One unit of a web order to pick. An order with quantity 3 creates 3 tasks.

  • sourcestringRequired
  • order_referencestring | null

    Order number your customer sees (for example #1001).

  • external_order_idstringRequired

    Your web shop's own order id. Skannit keys the order on it, so sending it twice does not create it twice.

  • product_idstring | null

    Skannit's id for the product.

  • product_namestring | null
  • assigned_variantstring | null

    Colour / size the order line asks for.

  • skustring | null

    Stock-keeping unit of the variant.

  • quantityinteger

    Number of units.

    Defaults to 1

  • buyer_emailstring | null

    GL-02: buyer identity is never sent out (always null); the order reference identifies the order. Kept in the schema only so the public v1 contract doesn't break. Stored on the task only to email the buyer.

  • buyer_phonestring | null

    Stored only. Matching is by email. Never returned in responses (always null).

  • buyer_namestring | null

    Never returned in responses (always null).

  • deadlinetimestamp | null

    When the order is promised. Drives the queue's ordering; NULL when the provider sent no SLA.

  • statusstring

    Current state of the object. See the allowed values.

    One ofpendingpickedshippeddeliveredcancelledrefusedlostreturn_requestedreturn_receivedreturnedreturn_rejected

    Defaults to pending

  • linked_unit_tokenstring | null

    The unit whose passport is linked to this order (set by the pick scan).

  • carrierstring | null

    Carrier name, for example PostNL or DHL.

  • tracking_numberstring | null

    The carrier's tracking number.

  • shipped_attimestamp | null

    When your web shop reported the parcel shipped.

  • delivered_attimestamp | null

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

  • is_matchableboolean

    False when the external SKU matched no Skannit product. Such a task is visible to a worker but cannot be picked until it is mapped.

    Defaults to true

  • created_attimestampRequired

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

POST /retail/integrations/fulfillment/tasks/{task_id}/inspection
curl
curl -X POST http://62.169.23.239:8001/api/v1/retail/integrations/fulfillment/tasks/266ac6a0-a008-5349-ae80-086961f95f9a/inspection \
  -H "Authorization: Bearer $SKANNIT_TOKEN" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{
    "decision": "accept",
    "next_step": "restock"
  }'
200Response
json
{
  "task_id": "266ac6a0-a008-5349-ae80-086961f95f9a",
  "source": "web_shop",
  "order_reference": "#1001",
  "external_order_id": "1001",
  "product_id": "f6abe715-90aa-5908-a0a6-12951a3a21cc",
  "product_name": "Trail Tee",
  "assigned_variant": "White / M",
  "sku": "TT-100-WHT-M",
  "quantity": 1,
  "buyer_email": null,
  "buyer_phone": null,
  "buyer_name": null,
  "deadline": null,
  "status": "returned",
  "linked_unit_token": "Qm7xK2pL9vR4tY8wZ1nB3c",
  "carrier": "PostNL",
  "tracking_number": "3SNWD1234567890",
  "shipped_at": null,
  "delivered_at": null,
  "is_matchable": true,
  "created_at": "2026-10-09T09:30:00Z"
}
NextTill sales→