# Staff Shifts V2 This document is the frontend handoff for the `staff/shifts/*` routes on the unified v2 API. Base URL: - `https://krow-api-v2-933560802882.us-central1.run.app` ## Read routes - `GET /staff/shifts/assigned` - `GET /staff/shifts/open` - `GET /staff/shifts/pending` - `GET /staff/shifts/cancelled` - `GET /staff/shifts/completed` - `GET /staff/shifts/:shiftId` ## Write routes - `POST /staff/shifts/:shiftId/apply` - `POST /staff/shifts/:shiftId/accept` - `POST /staff/shifts/:shiftId/decline` - `POST /staff/shifts/:shiftId/request-swap` - `POST /staff/shifts/:shiftId/submit-for-approval` All write routes require: - `Authorization: Bearer ` - `Idempotency-Key: ` ## Shift lifecycle ### Find shifts `GET /staff/shifts/open` - use this for the worker marketplace feed - the worker applies to a concrete shift role - send the `roleId` returned by the open-shifts response - `roleId` here means `shift_roles.id`, not the role catalog id Apply request example: ```json { "roleId": "uuid", "instantBook": false } ``` ### Pending shifts `GET /staff/shifts/pending` - use `POST /staff/shifts/:shiftId/accept` to accept - use `POST /staff/shifts/:shiftId/decline` to decline ### Assigned shifts `GET /staff/shifts/assigned` Each item now includes: - `clientName` - `hourlyRate` - `totalRate` - `startTime` - `endTime` ### Shift detail `GET /staff/shifts/:shiftId` Each detail response now includes: - `clientName` - `latitude` - `longitude` - `hourlyRate` - `totalRate` Use this as the source of truth for the shift detail screen. ### Request swap `POST /staff/shifts/:shiftId/request-swap` Example: ```json { "reason": "Need coverage for a family emergency" } ``` Current backend behavior: - marks the assignment as `SWAP_REQUESTED` - stores the reason - emits `SHIFT_SWAP_REQUESTED` - exposes the shift in the replacement pool - starts the swap-expiry window used by backend auto-cancellation Manager/ops review happens through: - `GET /client/coverage/swap-requests` - `GET /client/coverage/dispatch-candidates` - `POST /client/coverage/swap-requests/:swapRequestId/resolve` - `POST /client/coverage/swap-requests/:swapRequestId/cancel` If the swap request expires without coverage, backend auto-cancels it and alerts the manager path plus the original worker. ### Submit completed shift for approval `POST /staff/shifts/:shiftId/submit-for-approval` Use this after the worker has clocked out. Example: ```json { "note": "Worked full shift and all tasks were completed" } ``` Current backend behavior: - only allows shifts in `CHECKED_OUT` or `COMPLETED` - creates or updates the assignment timesheet - sets the timesheet to `SUBMITTED` unless it is already `APPROVED` or `PAID` - emits `TIMESHEET_SUBMITTED_FOR_APPROVAL` Example response: ```json { "assignmentId": "uuid", "shiftId": "uuid", "timesheetId": "uuid", "status": "SUBMITTED", "submitted": true } ``` ## Completed shifts `GET /staff/shifts/completed` Each item now includes: - `date` - `clientName` - `startTime` - `endTime` - `hourlyRate` - `totalRate` - `timesheetStatus` - `paymentStatus` ## Clock-in support fields `GET /staff/clock-in/shifts/today` Each item now includes: - `clientName` - `hourlyRate` - `totalRate` - `latitude` - `longitude` - `clockInMode` - `allowClockInOverride` ## Frontend rule Use the unified routes only. Do not build new mobile work on: - `/query/*` - `/commands/*` - `/core/*`