8.9 KiB
8.9 KiB
Unified API V2
Frontend should use this service as the single base URL:
https://krow-api-v2-933560802882.us-central1.run.app
The gateway keeps backend services separate internally, but frontend should treat it as one API.
1) Auth routes
Full auth behavior, including staff phone flow and refresh rules, is documented in Authentication.
Client auth
POST /auth/client/sign-inPOST /auth/client/sign-upPOST /auth/client/sign-out
Staff auth
POST /auth/staff/phone/startPOST /auth/staff/phone/verifyPOST /auth/staff/sign-out
Shared auth
GET /auth/sessionPOST /auth/sign-out
2) Client routes
Client reads
GET /client/sessionGET /client/dashboardGET /client/reordersGET /client/billing/accountsGET /client/billing/invoices/pendingGET /client/billing/invoices/historyGET /client/billing/current-billGET /client/billing/savingsGET /client/billing/spend-breakdownGET /client/coverageGET /client/coverage/statsGET /client/coverage/core-teamGET /client/coverage/incidentsGET /client/hubsGET /client/cost-centersGET /client/vendorsGET /client/vendors/:vendorId/rolesGET /client/hubs/:hubId/managersGET /client/team-membersGET /client/orders/viewGET /client/orders/:orderId/reorder-previewGET /client/reports/summaryGET /client/reports/daily-opsGET /client/reports/spendGET /client/reports/coverageGET /client/reports/forecastGET /client/reports/performanceGET /client/reports/no-show
Client writes
POST /client/devices/push-tokensDELETE /client/devices/push-tokensPOST /client/orders/one-timePOST /client/orders/recurringPOST /client/orders/permanentPOST /client/orders/:orderId/editPOST /client/orders/:orderId/cancelPOST /client/hubsPUT /client/hubs/:hubIdDELETE /client/hubs/:hubIdPOST /client/hubs/:hubId/assign-nfcPOST /client/hubs/:hubId/managersPOST /client/billing/invoices/:invoiceId/approvePOST /client/billing/invoices/:invoiceId/disputePOST /client/coverage/reviewsPOST /client/coverage/late-workers/:assignmentId/cancel
3) Staff routes
Staff reads
GET /staff/sessionGET /staff/dashboardGET /staff/profile-completionGET /staff/availabilityGET /staff/clock-in/shifts/todayGET /staff/clock-in/statusGET /staff/payments/summaryGET /staff/payments/historyGET /staff/payments/chartGET /staff/shifts/assignedGET /staff/shifts/openGET /staff/shifts/pendingGET /staff/shifts/cancelledGET /staff/shifts/completedGET /staff/shifts/:shiftIdGET /staff/profile/sectionsGET /staff/profile/personal-infoGET /staff/profile/industriesGET /staff/profile/skillsGET /staff/profile/documentsGET /staff/profile/attireGET /staff/profile/tax-formsGET /staff/profile/emergency-contactsGET /staff/profile/certificatesGET /staff/profile/bank-accountsGET /staff/profile/benefitsGET /staff/profile/time-cardGET /staff/profile/privacyGET /staff/faqsGET /staff/faqs/search
Staff writes
POST /staff/profile/setupPOST /staff/devices/push-tokensDELETE /staff/devices/push-tokensPOST /staff/clock-inPOST /staff/clock-outPOST /staff/location-streamsPUT /staff/availabilityPOST /staff/availability/quick-setPOST /staff/shifts/:shiftId/applyPOST /staff/shifts/:shiftId/acceptPOST /staff/shifts/:shiftId/declinePOST /staff/shifts/:shiftId/request-swapPUT /staff/profile/personal-infoPUT /staff/profile/experiencePUT /staff/profile/locationsPOST /staff/profile/emergency-contactsPUT /staff/profile/emergency-contacts/:contactIdPUT /staff/profile/tax-forms/:formTypePOST /staff/profile/tax-forms/:formType/submitPOST /staff/profile/bank-accountsPUT /staff/profile/privacy
4) Upload and verification routes
These are exposed as direct unified aliases even though they are backed by core-api-v2.
Generic core aliases
POST /upload-filePOST /create-signed-urlPOST /invoke-llmPOST /rapid-orders/transcribePOST /rapid-orders/parsePOST /verificationsGET /verifications/:verificationIdPOST /verifications/:verificationId/reviewPOST /verifications/:verificationId/retry
Staff upload aliases
POST /staff/profile/photoPOST /staff/profile/documents/:documentId/uploadPOST /staff/profile/attire/:documentId/uploadPOST /staff/profile/certificatesDELETE /staff/profile/certificates/:certificateId
5) Notes that matter for frontend
roleIdonPOST /staff/shifts/:shiftId/applyis the concreteshift_roles.idfor that shift, not the catalog role definition id.accountTypeonPOST /staff/profile/bank-accountsaccepts either lowercase or uppercase and is normalized by the backend.- File upload routes return a storage path plus a signed URL. Frontend uploads the file directly to storage using that URL.
- Verification upload and review routes are live and were validated through document, attire, and certificate flows. Do not rely on long-lived verification history durability until the dedicated persistence slice is landed in
core-api-v2. - Attendance policy is explicit. Reads now expose
clockInModeandallowClockInOverride. clockInModevalues are:NFC_REQUIREDGEO_REQUIREDEITHER
- For
POST /staff/clock-inandPOST /staff/clock-out:- send
nfcTagIdwhen clocking with NFC - send
latitude,longitude, andaccuracyMeterswhen clocking with geolocation - send
proofNonceandproofTimestampfor attendance-proof logging; these are most important on NFC paths - send
attestationProviderandattestationTokenonly when the device has a real attestation result to forward - send
overrideReasononly when the worker is bypassing a geofence failure and the shift/hub allows overrides
- send
POST /staff/location-streamsis for the background tracking loop after a worker is already clocked in.GET /client/coverage/incidentsis the review feed for geofence breaches, missing-location batches, and clock-in overrides.POST /client/coverage/late-workers/:assignmentId/cancelis the client-side recovery action when lateness is confirmed by incident evidence or elapsed grace time.- Raw location stream payloads are stored in the private v2 bucket; SQL only stores the summary and incident index.
- Push delivery is backed by:
- SQL token registry in
device_push_tokens - durable queue in
notification_outbox - per-attempt delivery records in
notification_deliveries - private Cloud Run worker service
krow-notification-worker-v2 - Cloud Scheduler job
krow-notification-dispatch-v2
- SQL token registry in
Push token request example
{
"provider": "FCM",
"platform": "IOS",
"pushToken": "expo-or-fcm-device-token",
"deviceId": "iphone-15-pro-max",
"appVersion": "2.0.0",
"appBuild": "2000",
"locale": "en-US",
"timezone": "America/Los_Angeles"
}
Push-token delete requests may send tokenId or pushToken either:
- as JSON in the request body
- or as query params on the
DELETEURL
Using query params is safer when the client stack or proxy is inconsistent about forwarding DELETE bodies.
Clock-in request example
{
"shiftId": "uuid",
"sourceType": "GEO",
"deviceId": "iphone-15-pro",
"latitude": 37.4221,
"longitude": -122.0841,
"accuracyMeters": 12,
"proofNonce": "nonce-generated-on-device",
"proofTimestamp": "2026-03-16T09:00:00.000Z",
"overrideReason": "Parking garage entrance is outside the marked hub geofence",
"capturedAt": "2026-03-16T09:00:00.000Z"
}
Location-stream batch example
{
"shiftId": "uuid",
"sourceType": "GEO",
"deviceId": "iphone-15-pro",
"points": [
{
"capturedAt": "2026-03-16T09:15:00.000Z",
"latitude": 37.4221,
"longitude": -122.0841,
"accuracyMeters": 12
},
{
"capturedAt": "2026-03-16T09:30:00.000Z",
"latitude": 37.4301,
"longitude": -122.0761,
"accuracyMeters": 20
}
],
"metadata": {
"source": "background-workmanager"
}
}
Coverage incidents response shape
{
"items": [
{
"incidentId": "uuid",
"assignmentId": "uuid",
"shiftId": "uuid",
"staffName": "Ana Barista",
"incidentType": "OUTSIDE_GEOFENCE",
"severity": "CRITICAL",
"status": "OPEN",
"clockInMode": "GEO_REQUIRED",
"overrideReason": null,
"message": "Worker drifted outside hub geofence during active monitoring",
"distanceToClockPointMeters": 910,
"withinGeofence": false,
"occurredAt": "2026-03-16T09:30:00.000Z"
}
],
"requestId": "uuid"
}
6) Why this shape
- frontend gets one host
- backend keeps reads, writes, and service helpers separated
- routing can change internally later without forcing frontend rewrites