8.8 KiB
8.8 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
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