5.1 KiB
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-e3g6witsvq-uc.a.run.app
Read routes
GET /staff/orders/availableGET /staff/shifts/assignedGET /staff/shifts/openGET /staff/shifts/pendingGET /staff/shifts/cancelledGET /staff/shifts/completedGET /staff/shifts/:shiftId
Write routes
POST /staff/orders/:orderId/bookPOST /staff/shifts/:shiftId/applyPOST /staff/shifts/:shiftId/acceptPOST /staff/shifts/:shiftId/declinePOST /staff/shifts/:shiftId/request-swapPOST /staff/shifts/:shiftId/submit-for-approval
All write routes require:
Authorization: Bearer <firebase-id-token>Idempotency-Key: <unique-per-action>
Shift lifecycle
Find work by order
GET /staff/orders/available
- use this for grouped recurring or permanent work cards
- each item represents one order plus one role
- this feed is already filtered to the current worker context
schedulegives the preview for the whole booking window
Example response:
{
"orderId": "uuid",
"orderType": "RECURRING",
"roleId": "uuid",
"roleCode": "BARISTA",
"roleName": "Barista",
"clientName": "Google Mountain View Cafes",
"location": "Google MV Cafe Clock Point",
"locationAddress": "1600 Amphitheatre Pkwy, Mountain View, CA",
"hourlyRateCents": 2300,
"hourlyRate": 23,
"requiredWorkerCount": 1,
"filledCount": 0,
"instantBook": false,
"dispatchTeam": "CORE",
"dispatchPriority": 1,
"schedule": {
"totalShifts": 3,
"startDate": "2026-03-24",
"endDate": "2026-03-28",
"daysOfWeek": ["WED", "FRI"],
"startTime": "09:00",
"endTime": "15:00",
"timezone": "America/Los_Angeles",
"firstShiftStartsAt": "2026-03-25T16:00:00.000Z",
"lastShiftEndsAt": "2026-03-27T22:00:00.000Z"
}
}
POST /staff/orders/:orderId/book
- use this when the worker books the full order instead of one shift
- booking is atomic across the future shifts in that order for the selected role
- backend returns
PENDINGwhen the booking is reserved but not instant-booked - backend returns
CONFIRMEDwhen every future shift in that booking path is instant-booked
Example request:
{
"roleId": "uuid"
}
Important:
roleIdfor the order-booking flow is the role catalog id returned byGET /staff/orders/available- it is not the same thing as the per-shift
shift_roles.id
Find shifts
GET /staff/shifts/open
- use this for the worker marketplace feed
- the worker applies to a concrete shift role
- send the
roleIdreturned by the open-shifts response roleIdhere meansshift_roles.id, not the role catalog id
Apply request example:
{
"roleId": "uuid",
"instantBook": false
}
Pending shifts
GET /staff/shifts/pending
- use
POST /staff/shifts/:shiftId/acceptto accept - use
POST /staff/shifts/:shiftId/declineto decline
Assigned shifts
GET /staff/shifts/assigned
Each item now includes:
clientNamehourlyRatetotalRatestartTimeendTime
Shift detail
GET /staff/shifts/:shiftId
Each detail response now includes:
clientNamelatitudelongitudehourlyRatetotalRate
Use this as the source of truth for the shift detail screen.
Request swap
POST /staff/shifts/:shiftId/request-swap
Example:
{
"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-requestsGET /client/coverage/dispatch-candidatesPOST /client/coverage/swap-requests/:swapRequestId/resolvePOST /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:
{
"note": "Worked full shift and all tasks were completed"
}
Current backend behavior:
- only allows shifts in
CHECKED_OUTorCOMPLETED - creates or updates the assignment timesheet
- sets the timesheet to
SUBMITTEDunless it is alreadyAPPROVEDorPAID - emits
TIMESHEET_SUBMITTED_FOR_APPROVAL
Example response:
{
"assignmentId": "uuid",
"shiftId": "uuid",
"timesheetId": "uuid",
"status": "SUBMITTED",
"submitted": true
}
Completed shifts
GET /staff/shifts/completed
Each item now includes:
dateclientNamestartTimeendTimehourlyRatetotalRatetimesheetStatuspaymentStatus
Clock-in support fields
GET /staff/clock-in/shifts/today
Each item now includes:
clientNamehourlyRatetotalRatelatitudelongitudeclockInModeallowClockInOverride
Frontend rule
Use the unified routes only.
Do not build new mobile work on:
/query/*/commands/*/core/*