Skip to content

API Reference

The ScanPick API exposes REST endpoints for all operations. In development mode (ASPNETCORE_ENVIRONMENT=Development), a fully interactive API explorer is available at the Scalar UI endpoint.

http://<host>:<port>/api

All endpoints except /api/auth/login require a JWT in the Authorization header:

Authorization: Bearer <token>

Authenticate a worker by PIN and receive a JWT.

Request:

{
"workerId": "worker-001",
"pin": "1234"
}

Response:

{
"token": "eyJhbGci...",
"workerId": "worker-001",
"name": "Alice Manager",
"role": "manager",
"expiresAt": "2026-06-21T12:00:00Z"
}

List all waves with optional status filter.

Query Parameters:

  • status — filter by status: Pending, InProgress, Completed, Cancelled
  • assignedWorkerId — filter by assigned worker

Response:

[
{
"id": "wave-001",
"name": "Wave-001",
"status": "InProgress",
"assignedWorkerId": "worker-003",
"assignedWorkerName": "Charlie Picker",
"totalPickTasks": 5,
"completedPickTasks": 2,
"skippedPickTasks": 1,
"createdAt": "2026-06-19T08:00:00Z"
}
]

Create a new wave.

Request:

{
"name": "Wave-004",
"orderIds": ["order-001", "order-002"]
}

Get wave detail including orders, pick tasks, and items.

Cancel a wave (must be in Pending status).

Start a wave. Consolidates items into pick tasks and transitions to InProgress.

Request:

{
"assignedWorkerId": "worker-003"
}

(Re)assign a worker to a wave.

Mark a wave as Completed. All pick tasks must be picked or skipped.

Get all pick tasks for a wave, sorted by optimized pick path.

Response:

[
{
"id": "picktask-001",
"productName": "Widget Alpha",
"expectedBarcode": "5901234567890",
"quantity": 10,
"pickedQuantity": 3,
"status": "InProgress",
"zone": "A",
"aisle": "01",
"rack": "03",
"shelf": "02",
"bin": "01",
"sortPath": "01-03-02"
}
]

Submit a pick scan from the mobile device. Supports offline idempotency via client-generated UUID.

Request:

{
"pickTaskId": "picktask-001",
"barcode": "5901234567890",
"scannedAt": "2026-06-19T10:30:00Z",
"idempotencyKey": "a1b2c3d4-e5f6-...",
"workerId": "worker-003"
}

Response:

{
"success": true,
"pickTaskId": "picktask-001",
"newPickedQuantity": 4,
"pickTaskStatus": "InProgress",
"remainingQuantity": 6
}

Skip a pick task with a reason (discrepancy reporting).

Request:

{
"pickTaskId": "picktask-003",
"reason": "Damaged",
"workerId": "worker-003"
}

Values for reason: Damaged, OutOfStock, WrongLocation, Other

Get warehouse details with zones and location counts.

Initialize warehouse with zones and generate locations.

List locations with optional filters (zone, occupied status).

Update location metadata (description, etc.).

Bulk generate locations from zone configuration.

Health check endpoint. Returns 200 OK when the API is running and database is reachable.

Real-time hub for pushing scan events to connected clients.

Methods (server → client):

  • PickTaskUpdated — a pick task’s picked quantity changed
  • WaveProgressUpdated — wave completion statistics changed
  • WorkerScanned — another worker’s scan activity (supervisor view)

Methods (client → server):

  • SubscribeToWave(waveId) — subscribe to updates for a specific wave
  • UnsubscribeFromWave(waveId) — unsubscribe

All SignalR methods use single object parameters for backward-compatible schema evolution.

All endpoints return consistent error responses:

{
"error": {
"code": "VALIDATION_ERROR",
"message": "A human-readable error message",
"details": [
{
"field": "workerId",
"message": "Worker ID is required"
}
]
}
}

Common HTTP status codes:

  • 400 — Bad request (validation error)
  • 401 — Unauthorized (missing or invalid JWT)
  • 403 — Forbidden (insufficient role)
  • 404 — Resource not found
  • 409 — Conflict (invalid status transition)
  • 500 — Internal server error