Work Queues API

Add items, scan barcodes, claim and move work, run stage buttons and read queue reports.

Work Queues track items through a series of stages: boxes arriving at a warehouse, orders being packed, tickets being reviewed. This API puts items into a queue, scans barcodes, lets stations claim work, moves items between stages and reports what is where. Queues themselves (their stages and rules) are normally set up in the app.

If the Work Queues app is switched off in Settings › Apps, these routes answer 404 NOT_FOUND.

Endpoints

Queue ids are UUIDs. Permissions are checked against the queue (its key is the resource), so a role can be limited to one queue.

Method Path Permission What it does
GET /orgs/{orgId}/queues queues:read List queues you can see, with counts
POST /orgs/{orgId}/queues queues:create Create a queue
GET /orgs/{orgId}/queues/{queueId} queues:read Get a queue
PUT /orgs/{orgId}/queues/{queueId} queues:update Replace a queue's definition
DELETE /orgs/{orgId}/queues/{queueId} queues:delete Delete a queue
GET /orgs/{orgId}/queues/{queueId}/items queues:read List and filter items
POST /orgs/{orgId}/queues/{queueId}/items queues:enqueue Add one or many items
GET /orgs/{orgId}/queues/{queueId}/items/{itemId} queues:read Get an item
PATCH /orgs/{orgId}/queues/{queueId}/items/{itemId} queues:transition Edit an item's own fields
DELETE /orgs/{orgId}/queues/{queueId}/items/{itemId} queues:delete Delete an item
POST /orgs/{orgId}/queues/{queueId}/items/{itemId}/move queues:transition Move an item to a stage
POST /orgs/{orgId}/queues/{queueId}/scan queues:transition Scan a key: advance or create
POST /orgs/{orgId}/queues/{queueId}/claim queues:transition Take waiting items
GET /orgs/{orgId}/queues/{queueId}/board queues:read Every stage with its first items
GET /orgs/{orgId}/queues/{queueId}/stages/{stageKey}/items queues:read One stage's items
GET /orgs/{orgId}/queues/{queueId}/summary queues:read Counts and verification report
GET /orgs/{orgId}/queues/{queueId}/batches queues:read Batch labels in use
GET /orgs/{orgId}/queues/{queueId}/events queues:read Movement history
POST /orgs/{orgId}/queues/{queueId}/stages/{stageKey}/action queues:transition and functions:invoke Run a stage button on items

enqueue and transition are separate on purpose: a scanning station can add work without being able to move it through the pipeline, and a supervisor can move work without being able to invent it.

The queue object

{
  "id": "0190f0ff-…",
  "key": "inbound-boxes",
  "name": "Inbound boxes",
  "object_type": "",
  "enabled": true,
  "stages": [
    { "key": "expected", "label": "Expected", "kind": "start", "position": 0, "from": [], "wip_limit": 0, "sla_seconds": 0, "buttons": [] },
    { "key": "received", "label": "Received", "kind": "normal", "position": 1, "from": ["expected"], "wip_limit": 0, "sla_seconds": 3600, "buttons": [] },
    { "key": "shelved", "label": "Shelved", "kind": "terminal", "position": 2, "from": [], "wip_limit": 0, "sla_seconds": 0, "buttons": [] }
  ],
  "intake": { "enabled": false, "filter": [], "stage": "", "key_field": "", "close_on_unmatch": false },
  "settings": { "on_unknown_scan": "reject", "lease_seconds": 300, "allow_duplicates": false },
  "summary": { "total": 120, "open": 80, "closed": 40, "overdue": 3, "unexpected": 0, "by_stage": { "expected": 20 } }
}

Stage kind is start, normal or terminal. A terminal stage closes the item. from limits which stages may move into this one (empty means any). wip_limit caps how many items may sit in the stage (0 means no cap). sla_seconds marks items overdue after that long.

Creating a queue

POST and PUT take the same body: key (lowercase letters, digits, - or _, up to 60 characters; made from the name when omitted), name, object_type (optional record type to link items to), enabled, stages (up to 40, each with key, label, kind, from, wip_limit, sla_seconds, record_patch, on_enter, buttons), intake and settings. A PUT should echo the stage keys back so items keep their place. The key cannot be changed afterwards. Up to 200 queues per workspace (past that: 400 VALIDATION_ERROR). Errors: 409 KEY_TAKEN, 400 VALIDATION_ERROR.

The item object

{
  "id": "0190f100-…",
  "key": "BOX-000123",
  "stage": "received",
  "status": "open",
  "priority": 0,
  "source": "scan",
  "batch": "2026-10-04-truck-7",
  "record_id": "0190f0aa-…",
  "payload": { "weight_kg": 12.5 },
  "claimed_by": "0190f0a0-…",
  "claim_expires_at": "2026-10-04T09:35:00Z",
  "assignee_id": "",
  "attempts": 0,
  "due_at": "2026-10-04T10:30:00Z",
  "overdue": false,
  "entered_stage_at": "2026-10-04T09:30:00Z",
  "created_at": "2026-10-04T08:00:00Z"
}

status is open, done, failed or cancelled. source is manual, scan, import, intake or function. Items can carry up to 16 KB of payload.

POST /orgs/{orgId}/queues/{queueId}/items

Add items. The key is the item's identity in the queue, so adding a key that is already open is a harmless no-op (unless the queue is set to allow duplicates): a double scan or a retried request does not create duplicates.

Field Type Required Notes
items array One of items or keys 1 to 500 items. Each has key, and optionally stage, batch, priority, record_id, assignee_id, payload
keys array of strings Shorthand for a pasted manifest. Ignored when items is present
stage string No Default stage for items that do not name one. The start stage if omitted
batch string No A label to group a load, for example a delivery
source string No manual (default), scan, import, intake or function. Items created with source scan are counted as unexpected in the report, so use import for a manifest
note string No Recorded on each item's history
curl -s -X POST https://axisiq.co/api/v1/orgs/$ORG/queues/$Q/items \
  -H "Authorization: Bearer $AXIS_KEY" -H "Content-Type: application/json" \
  -d '{"batch": "truck-7", "keys": ["BOX-000123", "BOX-000124", "BOX-000125"]}'

Response 201

{ "data": { "created": 3, "duplicates": 0, "items": [ { "id": "…", "key": "BOX-000123", "stage": "expected", "status": "open" } ] } }

Stage limits (work in progress caps) do not apply when adding items, only when moving them.

POST /orgs/{orgId}/queues/{queueId}/scan

Look an item up by its key and move it on, as a barcode scanner does. It always answers 200; the verdict tells you what happened.

Field Type Required Notes
key string Yes The barcode or item key
stage string No Where a new item should be created (when to_stage is not given). The start stage if omitted
to_stage string No Where a matching item should go (or where a new one is created). The next stage if omitted for an existing item
batch string No
note string No
payload object No
verdict Meaning
moved The item existed and was advanced
created The key was new and the queue accepts unknown keys, so an item was created (this also needs queues:enqueue, otherwise 403 FORBIDDEN)
duplicate The item is already at the target stage (a second beep)
unknown The key is not in this queue and the queue rejects unknown keys
blocked A stage rule refused the move (not an allowed source stage, or the stage is full)
{ "data": { "verdict": "moved", "message": "moved to received", "item": { "id": "…", "key": "BOX-000123", "stage": "received" } } }

POST /orgs/{orgId}/queues/{queueId}/items/{itemId}/move

Field Type Required Notes
to_stage string Yes Stage key
status string No open, done, failed or cancelled. Default: done when entering a terminal stage, otherwise open
note string No

Response 200 with the item. A move can be refused with 400 VALIDATION_ERROR when the target stage does not accept items from the current stage, or when it is at its limit. If the stage updates a linked record, that update is made first and as you, so a failure there stops the move.

POST /orgs/{orgId}/queues/{queueId}/claim

Take up to count waiting items from a stage for yourself. Used by pickers who each pull their own work. Two callers never receive the same item.

Field Type Notes
stage string Optional. Stage to pull from
count number Optional. Default 1, at most 50 (more is 400 VALIDATION_ERROR)

Response 200: { "items": [ … ], "claimed": 2 }. A claim lasts 5 minutes by default (set per queue) and then returns to the pool if not finished.

PATCH /orgs/{orgId}/queues/{queueId}/items/{itemId}

Change an item without moving it: priority, batch, assignee_id (empty string clears), due_at, payload, release (true gives up your claim), note. Only the stage cannot be changed here; use move.

GET /orgs/{orgId}/queues/{queueId}/items

Parameter Notes
stage, status, batch, key Filters
q Search text
overdue true for overdue items only
assignee_id, record_id Filter by assignee or linked record
limit Default 50, maximum 200
offset Start position

Returns { "items": [ … ], "total": 120, "next_offset": 50 }. next_offset is null on the last page. The "missing items" report is ?stage=expected&status=open.

GET /orgs/{orgId}/queues/{queueId}/summary

Optional batch. Returns the verification report:

{
  "data": {
    "queue": { "id": "…", "key": "inbound-boxes", "name": "Inbound boxes" },
    "summary": { "total": 120, "open": 80, "closed": 40, "overdue": 3, "unexpected": 2, "by_stage": { "expected": 20, "received": 60, "shelved": 40 } }
  }
}

With a batch loaded as a manifest, items still sitting in the starting stage are the ones missing, and items created by a scan that nobody expected are counted as unexpected.

Other reads

  • GET …/board?limit=&batch= returns { "queue": {…}, "stages": [ … ] }, each stage with its first items, total and next_offset.
  • GET …/stages/{stageKey}/items accepts the same filters as the item list.
  • GET …/batches lists batch labels.
  • GET …/events?item_id=&limit= returns the movement history (default 100, maximum 500).

POST /orgs/{orgId}/queues/{queueId}/stages/{stageKey}/action

Runs a stage's button, a function, over up to 25 items, as you. Needs functions:invoke as well.

{ "button_id": "…", "item_ids": ["0190f100-…", "0190f101-…"] }

Returns one result per item: [{ "item_id": "…", "ok": true }, { "item_id": "…", "ok": false, "error": "…" }].

Errors

Status Code When
400 VALIDATION_ERROR Bad body, bad id, 1 to 500 items rule, payload over 16 KB, a stage rule refused the move
403 FORBIDDEN Missing the queue permission for this queue
404 NOT_FOUND No such queue, item, stage or button
409 KEY_TAKEN A queue with that key already exists