# API Guide

Full endpoint reference: `docs/openapi.yaml` (regenerate with `php artisan wms:openapi`). This page covers the conventions and the scanner flows that the reference cannot express.

## 1. Conventions

| Topic | Rule |
|-------|------|
| Base URL | `/api/v1` |
| Auth | `Authorization: Bearer <token>`; `POST /auth/login {email, password, device_name}` returns one. Integration tokens: `POST /auth/tokens` with explicit abilities (e.g. `["orders:write" → use permission names such as "outbound.orders.manage", "inventory.view"]`). A token with `*` has all abilities; the user's role still applies. |
| Scoping | Client users see only their client. Operators pass `client_id` and/or `warehouse_id` on list endpoints; operators restricted to warehouses are filtered automatically. |
| Idempotency | Send `Idempotency-Key: <uuid>` on POST/PUT/PATCH/DELETE. Same key + same body → stored response replayed with `Idempotent-Replayed: true`. Same key + different body → 422 `idempotency_conflict`. In-flight duplicate → 409. Keys expire after 24 h. |
| Envelope | Success: `{ "data": ..., "meta"?: {...} }`. Lists: `?page=&per_page=` (max 200). |
| Errors | `{ "error": { "code": "...", "message": "...", "context"?: {...}, "fields"?: {...} } }`. Codes are stable identifiers (e.g. `insufficient_stock`, `invalid_transition`, `over_receipt`, `wrong_location`). HTTP: 401 unauthenticated, 403 forbidden, 404 not found, 409 conflict/state, 422 validation or business rule, 429 rate limited. |
| Actions | State transitions are explicit calls: `POST /orders/{id}/confirm`, `/allocate`, `/cancel` … The allowed action names are enumerated per route in the OpenAPI `action` path parameter. |
| Quantities | Strings with 3 decimals in the product base UoM (`"12.000"`). Inputs accept numbers; `uom_code` + `quantity` convert on the way in (cases → eaches). |
| Tracing | Send `X-Request-Id` to correlate; it is echoed back and logged. |
| Webhooks | Subscribe with `POST /webhooks {url, events}`. Payload: `{id, event, occurred_at, data}`. Headers `X-WMS-Event`, `X-WMS-Delivery`, `X-WMS-Timestamp`, `X-WMS-Signature: sha256=<hmac>`. Retries with backoff up to 8 attempts. Event names: `asn.*`, `receipt.*`, `qc.*`, `putaway.*`, `order.*`, `wave.*`, `pick.*`, `package.*`, `shipment.*`, `inventory.*`, `count.*`, `replen.*`, `rma.*`, `work_order.*`, `billing.*`, `ai.*`. |

## 2. Typical console flows

**Inbound**
1. `POST /asns` (lines with `sku`, `quantity`, `uom_code`, optional `lot_number`, `expiry_date`) → `POST /asns/{id}/confirm`
2. Optional `POST /dock-appointments` → `check-in` → `assign-dock`
3. `POST /receipts {asn_id, receiving_location_code}` → `POST /receipts/{id}/lines` per pallet/line → `POST /receipts/{id}/complete`
4. QC lines: `POST /receipt-lines/{id}/qc {passed_quantity, failed_quantity, failure_reason_code}`
5. Putaway tasks appear: `GET /putaway-tasks?status[]=pending` → `GET /putaway-tasks/{id}/suggestions` → `POST /putaway-tasks/{id}/complete {location_code, override_reason?}`

**Outbound**
1. `POST /orders {..., lines, confirm: true, allocate: true}` → allocation report in the response
2. `POST /waves/preview {warehouse_id, criteria}` → `POST /waves {..., pick_method, release: true}` → pick tasks
3. Picking (RF, below) → `POST /orders/{id}/packages` → `POST /packages/{id}/lines` → `POST /packages/{id}/close`
4. `POST /shipments {order_ids}` → `/packed` → `/manifest {tracking_number}` → `/dispatch {vehicle_ref, seal_no}`

**Control**
- Counts: `POST /cycle-counts {location_codes}` → `/start` → RF scans → `/finish` → review lines → `/post`
- Replenishment: automatic (scheduler) or `POST /replenishment/scan`; manual `POST /replenishment-tasks`
- Slotting: `POST /slotting/analyse` → `GET /slotting-recommendations` → `/accept`

**AI**
- `GET /ai/recommendations?status=pending` → `/accept` or `/reject`
- `POST /ai/query {question}` → `{sql, explanation, rows}`
- `POST /asns/extract {client_id, warehouse_id, document_text}` → recommendation whose acceptance creates the draft ASN
- `PUT /ai/policies {use_case, mode: off|advise|auto, auto_threshold, daily_cost_cap_usd, client_id?, warehouse_id?}`

## 3. RF (scanner) flows

The RF API (`/api/v1/rf/*`) is designed so the device app is a thin state machine: every response contains `next: {action, prompt, expect}`.

| Step | Call | Device shows |
|------|------|--------------|
| Identify anything | `POST /rf/lookup {warehouse_id, code}` | location contents, LPN contents, product, or a document |
| Get work | `GET /rf/tasks/next?warehouse_id=&type=pick\|putaway\|replenishment` | highest-priority task for this operator (assigned first, then pool) |
| Receive | `POST /rf/receive/{receipt}/scan {barcode, quantity, lpn?/new_lpn, lot_number?, expiry_date?, serials?}` | received line, remaining ASN lines |
| Putaway | `POST /rf/putaway/{task}/confirm {location_code, lpn?, override_reason?}` | wrong LPN → `wrong_lpn`; different location than suggested without reason → `override_reason_required` |
| Pick | `POST /rf/pick/{task}/start {tote_lpn?}` then per line `POST /rf/pick-lines/{line}/confirm {location_code, lpn?, quantity, serials?, short_reason_code?}` | wrong location → `wrong_location`; short quantity requires a reason; the system re-allocates the shortfall elsewhere when possible and appends a new line to the task |
| Move | `POST /rf/move {lpn, to_location_code}` | whole LPN relocation, allocations travel with it |
| Replenish | `POST /rf/replenishment/{task}/confirm {to_location_code, from_location_code?, quantity?}` | |
| Count | `POST /rf/count/{count}/scan {location_code, barcode?, quantity, lot_number?, lpn?}` | blind: system quantities are hidden from operators without review permission |

All RF endpoints are idempotent through `Idempotency-Key`; the device should generate one per scan and retry on network failure.

## 4. Permissions

Roles and the permission matrix live in `app/Support/Permissions.php`. `GET /me` returns the effective permissions for the current token so a front-end can hide what the user cannot do.

| Role | Intended for |
|------|-------------|
| `super_admin` | Everything |
| `ops_manager` | Site management, all operations, AI governance |
| `supervisor` | Floor supervision incl. approvals, waves, exceptions |
| `operator` | RF work: receive, putaway, pick, pack, ship, count, replenish |
| `inventory_controller` | Counts, adjustments, holds, slotting, exception resolution |
| `finance` | Billing, rate cards, period close, audit |
| `client_admin` / `client_viewer` | Client portal: own products, ASNs, orders, returns, stock, reports (admin can write) |
| `integration` | ERP/API connections for a client |
