Scanning
Scan sessions, scan events, and read-only scannable identifiers.
Scanning API
The scanning layer resolves scanned codes (barcodes, QR codes, asset numbers) to platform entities and drives operational workflows through context handlers. A scannable identifier is a unique code with a polymorphic target (asset, flightcase, or catalogue item). A scan session binds a context and an optional target, snapshots an expected set, and records every scan attempt as an append-only event — regardless of outcome.
Resolution returns typed outcomes (resolved, unknown, ambiguous, wrong-context, duplicate, blocked, refused, failed) rather than exceptions, so scan attempts always record cleanly. Handler terminal results (blocked / refused / failed) are persisted on the scan event — not as resolved — so a later successful re-scan is not misclassified as a duplicate.
Endpoints
| Method | URL | Description |
|---|---|---|
| GET | /api/v1/scannable_identifiers |
List scannable identifiers |
| GET | /api/v1/scan_sessions |
List scan sessions |
| POST | /api/v1/scan_sessions |
Open a scan session |
| GET | /api/v1/scan_sessions/{scan_session} |
Show a session |
| POST | /api/v1/scan_sessions/{scan_session}/scans |
Submit a scan |
| GET | /api/v1/scan_sessions/{scan_session}/events |
List a session's scan events |
| POST | /api/v1/scan_sessions/{scan_session}/close |
Close a session |
| POST | /api/v1/scan_sessions/{scan_session}/abandon |
Abandon a session |
Identifier write operations (assign, replace, deactivate, generate) and label printing are currently performed through the web UI actions rather than the API; the identifiers endpoint is read-only.
Authentication
Requires scanning:read (GET) or scanning:write (POST). Read routes check scanning.access; opening, closing, and abandoning sessions check scanning.manage_sessions; submitting a scan checks scanning.scan. Session show/events additionally apply the session policy.
Open a session
POST /api/v1/scan_sessions
| Field | Type | Required | Description |
|---|---|---|---|
context |
string | Yes | Scan context (see below) |
target_type |
string | No | Polymorphic target type (required together with target_id) |
target_id |
int | No | Polymorphic target id |
warehouse_id |
int | No | Warehouse the session operates in |
A context must be a registered handler or listed in the scanning config allowlist. Available contexts: check-out, check-in, stocktake, transfer, lookup, prep, and sub-hire receiving.
Submit a scan
POST /api/v1/scan_sessions/{scan_session}/scans
Accepts the scanned value and the input method (manual, keyboard-wedge, or camera-QR). The value is normalised per adapter, resolved within the session context, dispatched to the context handler, and recorded as a scan event inside one database transaction with the handler mutation. The response returns the outcome, the resolved entity where applicable, and a next_action hint. Duplicate scans return without side effects and only match prior resolved events. Handler refusals (for example a failed dispatch gate) persist as blocked / refused / failed outcomes with human-readable reasons.
Response shape
Sessions serialise through ScanSessionData, scans through ScanResultData, events through ScanEventData, and identifiers through ScannableIdentifierData. The input method is stored in event metadata. Collection keys: scan_sessions, scan_events, scannable_identifiers.
Webhooks
Scan sessions do not currently emit webhooks; scan attempts are captured on the append-only event log and the audit trail.