# M4 API Catalog (Implementation Contract) Status: Active (Planning + Route Inventory) Date: 2026-02-24 Owner: Technical Lead Environment: dev ## Frontend source of truth For frontend implementation, use: - `docs/MILESTONES/M4/planning/m4-core-api-frontend-guide.md` Reason: - this catalog is the broader M4 planning contract - the frontend guide is the exact deployed request/response contract ## 1) Scope and purpose This file defines the backend endpoint contract for the M4 foundation build. ## 2) Global API rules 1. Canonical route groups: - `/core/*` for foundational integration routes - `/commands/*` for business-critical writes 2. Foundation phase security model: - authenticated user required - role map enforcement deferred - policy hook required in handler design 3. Standard error envelope: ```json { "code": "STRING_CODE", "message": "Human readable message", "details": {}, "requestId": "optional-request-id" } ``` 4. Required request headers: - `Authorization: Bearer ` - `X-Request-Id: ` (optional but recommended) 5. Required response headers: - `X-Request-Id` 6. Validation: - all input validated server-side - reject unknown/invalid fields 7. Logging: - route - requestId - actorId - latencyMs - outcome 8. Timeouts and retries: - command writes must be retry-safe - use idempotency keys for command write routes 9. Idempotency storage: - store in Cloud SQL table - key scope: `userId + route + idempotencyKey` - key retention: 24 hours - repeated key returns original response payload ## 3) Compatibility aliases (transition) 1. `POST /uploadFile` -> `POST /core/upload-file` 2. `POST /createSignedUrl` -> `POST /core/create-signed-url` 3. `POST /invokeLLM` -> `POST /core/invoke-llm` ## 4) Rate-limit baseline (initial) 1. `/core/invoke-llm`: 60 requests per minute per user 2. `/core/upload-file`: 30 requests per minute per user 3. `/core/create-signed-url`: 120 requests per minute per user 4. `/commands/*`: 60 requests per minute per user ## 4.1 Timeout baseline (initial) 1. `/core/invoke-llm`: 20-second hard timeout 2. other `/core/*` routes: 10-second timeout 3. `/commands/*` routes: 15-second timeout ## 5) Core routes ## 5.1 Upload file 1. Method and route: `POST /core/upload-file` 2. Auth: required 3. Idempotency key: optional 4. Request: multipart form data - `file` (required) - `category` (optional) - `visibility` (optional: `public` or `private`) 5. Success `200`: ```json { "fileUri": "gs://bucket/path/file.ext", "contentType": "application/pdf", "size": 12345, "bucket": "krow-uploads-private", "path": "documents/staff/..." } ``` 6. Errors: - `UNAUTHENTICATED` - `INVALID_FILE_TYPE` - `FILE_TOO_LARGE` - `UPLOAD_FAILED` ## 5.2 Create signed URL 1. Method and route: `POST /core/create-signed-url` 2. Auth: required 3. Idempotency key: optional 4. Request: ```json { "fileUri": "gs://bucket/path/file.ext", "expiresInSeconds": 300 } ``` 5. Success `200`: ```json { "signedUrl": "https://...", "expiresAt": "2026-02-24T15:00:00Z" } ``` 6. Errors: - `UNAUTHENTICATED` - `FORBIDDEN_FILE_ACCESS` - `INVALID_EXPIRES_IN` - `SIGN_URL_FAILED` ## 5.3 Invoke model 1. Method and route: `POST /core/invoke-llm` 2. Auth: required 3. Idempotency key: optional 4. Request: ```json { "prompt": "...", "responseJsonSchema": {}, "fileUrls": [] } ``` 5. Success `200`: ```json { "result": {}, "model": "provider/model-name", "latencyMs": 980 } ``` 6. Errors: - `UNAUTHENTICATED` - `INVALID_SCHEMA` - `MODEL_TIMEOUT` - `MODEL_FAILED` 7. Provider default: - Vertex AI Gemini ## 5.4 Health check 1. Method and route: `GET /healthz` 2. Auth: optional (internal policy) 3. Success `200`: ```json { "ok": true, "service": "krow-backend", "version": "commit-or-tag" } ``` ## 5.5 Storage bucket policy defaults (dev) 1. Public bucket: `krow-workforce-dev-public` 2. Private bucket: `krow-workforce-dev-private` 3. Private objects are never returned directly; only signed URLs are returned. ## 6) Command routes (wave 1) ## 6.1 Create order 1. Method and route: `POST /commands/orders/create` 2. Auth: required 3. Idempotency key: required 4. Purpose: create order + shifts + roles atomically 5. Replaces: - `apps/web/src/features/operations/orders/components/CreateOrderDialog.tsx` - `apps/mobile/packages/features/client/home/lib/src/presentation/widgets/shift_order_form_sheet.dart` - `apps/mobile/packages/features/client/create_order/lib/src/data/repositories_impl/client_create_order_repository_impl.dart` ## 6.2 Update order 1. Method and route: `POST /commands/orders/{orderId}/update` 2. Auth: required 3. Idempotency key: required 4. Purpose: policy-safe multi-entity order update 5. Replaces: - `apps/web/src/features/operations/orders/EditOrder.tsx` - `apps/mobile/packages/features/client/view_orders/lib/src/presentation/widgets/view_order_card.dart` ## 6.3 Cancel order 1. Method and route: `POST /commands/orders/{orderId}/cancel` 2. Auth: required 3. Idempotency key: required 4. Purpose: enforce cancellation policy and return explicit conflict code 5. Replaces: - `apps/web/src/features/operations/orders/OrderDetail.tsx` ## 6.4 Change shift status 1. Method and route: `POST /commands/shifts/{shiftId}/change-status` 2. Auth: required 3. Idempotency key: required 4. Purpose: enforce state transitions server-side 5. Replaces: - `apps/web/src/features/operations/tasks/TaskBoard.tsx` ## 6.5 Assign staff 1. Method and route: `POST /commands/shifts/{shiftId}/assign-staff` 2. Auth: required 3. Idempotency key: required 4. Purpose: assign + count update + conflict checks atomically 5. Replaces: - `apps/web/src/features/operations/orders/components/AssignStaffModal.tsx` ## 6.6 Accept shift 1. Method and route: `POST /commands/shifts/{shiftId}/accept` 2. Auth: required 3. Idempotency key: required 4. Purpose: application + counters + rollback-safe behavior in one command 5. Replaces: - `apps/mobile/packages/features/staff/shifts/lib/src/data/repositories_impl/shifts_repository_impl.dart` ## 7) Locked defaults before coding starts 1. Idempotency keys are stored in Cloud SQL with 24-hour retention. 2. Request validation library is `zod`. 3. Validation schema location is `backend//src/contracts/`. 4. Storage buckets are: - `krow-workforce-dev-public` - `krow-workforce-dev-private` 5. Model provider is Vertex AI Gemini with a 20-second timeout for `/core/invoke-llm`. ## 8) Target response-time objectives (p95) 1. `/healthz` under 200ms 2. `/core/create-signed-url` under 500ms 3. `/commands/*` under 1500ms 4. `/core/invoke-llm` under 15000ms