Skip to Content
Authentication and access

Source document · API/docs/AUTHENTICATION.md

Authentication and access control

The API issues its own signed access and refresh tokens. A successful password check alone does not create a session: email verification and sign-in use one-time codes. Protected endpoints also apply role, ownership, and workflow checks in the relevant module.

Account and session lifecycle

Registration creates an account pending email verification. Login sends a six-digit sign-in code with a 15-minute lifetime. Codes are single-use and stored hashed. Resend requests are throttled. Password recovery sends a one-time code and changes the password only after confirmation.

OperationEndpointPurpose
RegisterPOST /api/v1/auth/registerCreate a member account and initiate email verification.
Verify emailPOST /api/v1/auth/verify-emailConsume the verification code for user_id.
Start loginPOST /api/v1/auth/loginValidate credentials and send a sign-in code.
Complete loginPOST /api/v1/auth/login/verifyConsume the code and issue a session.
RefreshPOST /api/v1/auth/refreshRotate a refresh token and issue the next session.
LogoutPOST /api/v1/auth/logoutRevoke the supplied refresh token.
Password recoveryPOST /api/v1/auth/password-reset/request, then /confirmRequest and consume a reset code.
Current userGET /api/v1/auth/meRead the authenticated account.
ProfilePATCH /api/v1/auth/meChange username and display name.
Delete accountDELETE /api/v1/auth/meDelete the authenticated account.

Access tokens default to 15 minutes; refresh tokens default to 30 days. Refresh tokens rotate on use and are single-use. A client should atomically replace the stored token pair after refresh and clear it on logout or an unrecoverable authentication error. The Android app encrypts its session using Android Keystore.

Authorization layers

Authentication means the API knows which account made the request. Authorization is the separate check that decides whether that account can act on a resource. Possessing a valid bearer token does not grant provider or administrator privileges.

ActorTypical access
MemberTheir own profile, bookings, payments, notifications, conversations, and community actions.
ProviderTheir provider profile, owned listing/menu, provider dashboard, eligible orders, and manual sales. Provider approval and listing subscription determine public listing visibility.
AccountantScoped reporting and permitted read access, based on explicit service assignments.
AdministratorAdministrative operations such as moderation, role/status changes, payment review, provider approval, and report export.
GuestCreate an order without an account and read that booking only with its one-time guest access token.

Rules are enforced per use case. For example, an order is readable by its customer, its provider, and authorized staff; only its provider owner or an administrator can perform management transitions. Payment confirmation accepts a provider or administrator where applicable; payment rejection is administrator-only. Admin routes require both a valid bearer token and the required staff role.

Guest booking capability

POST /api/v1/orders accepts either an authenticated bearer token or guest contact details. A guest omits the Authorization header and sends an Idempotency-Key; a malformed or expired bearer token returns 401 instead of silently falling back to guest mode. The server ignores client-supplied totals, provider IDs, and currencies, and derives the price from the selected active menu item. Guest creation returns a one-time access capability. The database stores its hash, not the raw token. Recover the booking with:

GET /api/v1/guest/orders/{id} X-Guest-Access-Token: <guest-access-token>

Treat this token like a password: anyone who has it can access that guest booking. Store it securely and do not place it in analytics, logs, or shared links.

The guest capability is independent of email verification and account login. It grants access only to the specific guest order and expires after 90 days. It does not grant permission to list guest orders or create payment claims as another account.

Client handling checklist

  • Use HTTPS outside local development.
  • Send access tokens only in the Authorization header.
  • Keep the MailAfrica API key, database URL, AUTH_TOKEN_SECRET, and LiveKit secret on the server.
  • Never treat hidden UI controls as authorization; the API owns every permission decision.
  • On 401, refresh once if possible, then return to sign-in if refresh fails. On 403, show that the account is authenticated but lacks permission.
  • Use optimistic version fields only with the latest returned resource version; reload after a 409 conflict.
  • Do not store or reuse a guest token beyond the booking-recovery flow.