Files
Krow-workspace/docs/BACKEND/API_GUIDES/V2/mobile-frontend-implementation-spec.md

9.6 KiB

Mobile Frontend Implementation Spec

This is the shortest path for frontend to implement the v2 mobile clients against the unified backend.

Base URL:

  • https://krow-api-v2-e3g6witsvq-uc.a.run.app

Use this doc together with:

1) Global rules

  • Use unified routes only.
  • Send Authorization: Bearer <firebase-id-token> on protected routes.
  • Send Idempotency-Key on all write routes.
  • Do not call /query/*, /commands/*, or /core/* directly from frontend.

2) Core model frontend should assume

  • order is the client-facing request for staffing.
  • shift is the concrete scheduled unit of work under an order.
  • shiftRole is the role slot inside a shift that staff apply to.
  • assignment is the worker-to-shift record once a worker is attached.

Important consequences:

  • GET /staff/shifts/open returns open shift-role opportunities.
  • POST /staff/shifts/:shiftId/apply must send the roleId from that response.
  • GET /staff/orders/available returns grouped order opportunities for atomic booking.
  • POST /staff/orders/:orderId/book must send the roleId from that response.
  • GET /client/shifts/scheduled is the canonical timeline/read model for the client app.
  • GET /client/orders/view is a deprecated compatibility alias.
  • POST /client/orders/:orderId/edit and POST /client/orders/:orderId/cancel only affect future shifts.

3) Auth implementation

Client app

  • sign in with POST /auth/client/sign-in
  • sign up with POST /auth/client/sign-up
  • hydrate session with GET /auth/session
  • sign out with POST /auth/client/sign-out

Staff app

  • start phone auth with POST /auth/staff/phone/start
  • complete phone auth with POST /auth/staff/phone/verify
  • hydrate session with GET /auth/session
  • sign out with POST /auth/staff/sign-out

Token refresh:

  • keep using Firebase client SDK refresh behavior
  • there is no backend /auth/refresh route

4) Client app screen mapping

Home / dashboard

  • GET /client/session
  • GET /client/dashboard
  • GET /client/reorders

Billing / payments

  • GET /client/billing/accounts
  • GET /client/billing/invoices/pending
  • GET /client/billing/invoices/history
  • GET /client/billing/current-bill
  • GET /client/billing/savings
  • GET /client/billing/spend-breakdown
  • POST /client/billing/invoices/:invoiceId/approve
  • POST /client/billing/invoices/:invoiceId/dispute

Coverage

  • GET /client/coverage?date=YYYY-MM-DD
  • GET /client/coverage/stats?date=YYYY-MM-DD
  • GET /client/coverage/core-team?date=YYYY-MM-DD
  • GET /client/coverage/incidents?startDate=YYYY-MM-DD&endDate=YYYY-MM-DD
  • GET /client/coverage/blocked-staff
  • GET /client/coverage/swap-requests?status=OPEN
  • GET /client/coverage/dispatch-teams
  • GET /client/coverage/dispatch-candidates?shiftId=uuid&roleId=uuid
  • POST /client/coverage/reviews
  • POST /client/coverage/late-workers/:assignmentId/cancel
  • POST /client/coverage/swap-requests/:swapRequestId/resolve
  • POST /client/coverage/swap-requests/:swapRequestId/cancel
  • POST /client/coverage/dispatch-teams/memberships
  • DELETE /client/coverage/dispatch-teams/memberships/:membershipId

Use POST /client/coverage/reviews when the business is rating a worker after coverage review.

Payload may include:

{
  "staffId": "uuid",
  "assignmentId": "uuid",
  "rating": 4,
  "feedback": "Strong performance on the shift",
  "markAsFavorite": true,
  "markAsBlocked": false
}

If markAsFavorite is true, backend adds that worker to the business favorites list. If markAsFavorite is false, backend removes them from that list. If markAsBlocked is true, backend blocks that worker for that business and rejects future apply or assign attempts until a later review sets markAsBlocked: false.

Swap-management rule:

  • use GET /client/coverage/swap-requests as the client review feed
  • use GET /client/coverage/dispatch-candidates for the ranked replacement list
  • use POST /client/coverage/swap-requests/:swapRequestId/resolve when ops selects a replacement
  • use POST /client/coverage/swap-requests/:swapRequestId/cancel when ops wants to close the swap request without replacement

Dispatch-priority rule:

  1. CORE
  2. CERTIFIED_LOCATION
  3. MARKETPLACE

Orders

  • GET /client/shifts/scheduled
  • GET /client/orders/view deprecated alias
  • GET /client/orders/:orderId/reorder-preview
  • POST /client/orders/one-time
  • POST /client/orders/recurring
  • POST /client/orders/permanent
  • POST /client/orders/:orderId/edit
  • POST /client/orders/:orderId/cancel

Rapid-order flow:

  • use POST /rapid-orders/process for the single-call transcribe-and-parse flow

Hubs and managers

  • GET /client/hubs
  • GET /client/cost-centers
  • GET /client/hubs/:hubId/managers
  • GET /client/team-members
  • POST /client/shift-managers
  • POST /client/hubs
  • PUT /client/hubs/:hubId
  • DELETE /client/hubs/:hubId
  • POST /client/hubs/:hubId/assign-nfc
  • POST /client/hubs/:hubId/managers

POST /client/shift-managers is the fastest path to create an invited manager identity for a business. If hubId is provided, backend also links that manager to the hub.

Reports

  • GET /client/reports/summary?date=YYYY-MM-DD
  • GET /client/reports/daily-ops?date=YYYY-MM-DD
  • GET /client/reports/spend?date=YYYY-MM-DD
  • GET /client/reports/coverage?date=YYYY-MM-DD
  • GET /client/reports/forecast?date=YYYY-MM-DD
  • GET /client/reports/performance?date=YYYY-MM-DD
  • GET /client/reports/no-show?date=YYYY-MM-DD

5) Staff app screen mapping

Home / dashboard

  • GET /staff/session
  • GET /staff/dashboard
  • GET /staff/profile-completion

Availability

  • GET /staff/availability
  • PUT /staff/availability
  • POST /staff/availability/quick-set

Find shifts

  • GET /staff/orders/available
  • POST /staff/orders/:orderId/book
  • GET /staff/shifts/open
  • POST /staff/shifts/:shiftId/apply

Rule:

  • send the roleId from the order-available response when booking an order
  • this roleId is the role catalog id for grouped order booking
  • send the roleId from the open-shifts response only when applying to one shift
  • that route still uses the concrete shift_roles.id

My shifts

  • GET /staff/shifts/pending
  • GET /staff/shifts/assigned
  • GET /staff/shifts/cancelled
  • GET /staff/shifts/completed
  • GET /staff/shifts/:shiftId
  • POST /staff/shifts/:shiftId/accept
  • POST /staff/shifts/:shiftId/decline
  • POST /staff/shifts/:shiftId/request-swap
  • POST /staff/shifts/:shiftId/submit-for-approval

Current swap behavior:

  • backend records the swap request
  • assignment moves to SWAP_REQUESTED
  • shift becomes visible in the replacement pool
  • client/ops can review and resolve swap requests through the coverage endpoints
  • if the swap request expires without coverage, backend auto-cancels it and alerts both the manager path and the original worker

Clock in / clock out

  • GET /staff/clock-in/shifts/today
  • GET /staff/clock-in/status
  • POST /staff/clock-in
  • POST /staff/clock-out
  • POST /staff/location-streams

Frontend should respect:

  • clockInMode
  • allowClockInOverride
  • latitude
  • longitude
  • geofenceRadiusMeters
  • nfcTagId

Clock-in proof rules:

  • use nfcTagId for NFC clocking
  • use latitude, longitude, and accuracyMeters for geolocation clocking
  • send overrideReason only when a geofence override is allowed
  • send proofNonce and proofTimestamp on attendance writes

Payments

  • GET /staff/payments/summary
  • GET /staff/payments/history
  • GET /staff/payments/chart

Profile

  • GET /staff/profile/sections
  • GET /staff/profile/personal-info
  • GET /staff/profile/industries
  • GET /staff/profile/skills
  • GET /staff/profile/documents
  • GET /staff/profile/attire
  • GET /staff/profile/tax-forms
  • GET /staff/profile/emergency-contacts
  • GET /staff/profile/certificates
  • GET /staff/profile/bank-accounts
  • GET /staff/profile/benefits
  • GET /staff/profile/benefits/history
  • GET /staff/profile/time-card
  • GET /staff/profile/privacy
  • PUT /staff/profile/personal-info
  • PUT /staff/profile/experience
  • PUT /staff/profile/locations
  • POST /staff/profile/emergency-contacts
  • PUT /staff/profile/emergency-contacts/:contactId
  • PUT /staff/profile/tax-forms/:formType
  • POST /staff/profile/tax-forms/:formType/submit
  • POST /staff/profile/bank-accounts
  • PUT /staff/profile/privacy

Document model rule:

  • GET /staff/profile/documents returns only documents
  • GET /staff/profile/attire returns attire items
  • GET /staff/profile/tax-forms returns tax-form rows
  • GET /staff/profile/certificates returns certificates

FAQ

  • GET /staff/faqs
  • GET /staff/faqs/search?q=...

6) Upload implementation

For documents, attire, and certificates:

  1. POST /upload-file
  2. POST /create-signed-url
  3. upload file bytes to storage with the signed URL
  4. POST /verifications
  5. finalize with:
    • PUT /staff/profile/documents/:documentId/upload
    • PUT /staff/profile/attire/:documentId/upload
    • POST /staff/profile/certificates

Use the verification-linked file as the source of truth.

7) What frontend should not assume

  • do not assume order edit mutates past shifts
  • do not assume swap resolution is complete beyond the request step
  • do not assume raw /query/* or /commands/* routes are stable for app integration
  • do not assume blocked workers can still apply to future shifts for that business

8) Demo reset

To reset dev demo data:

source ~/.nvm/nvm.sh
nvm use 23.5.0
cd backend/command-api
npm run seed:v2-demo