Authentication
Every authenticated endpoint expects a JWT access token in the
Authorization header:
Authorization: Bearer <access_token>
Requests without a valid token get a 401 with the standard
error envelope.
Logging in
POST /v1/auth/login exchanges credentials for a token pair:
curl -X POST https://api.getroja.com/v1/auth/login \
-H "Content-Type: application/json" \
-d '{ "identifier": "08123456789", "password": "your-password" }'
{
"access_token": "eyJhbGciOi...",
"refresh_token": "def50200ab...",
"expires_at": "2026-07-09T12:00:00Z",
"twofa_required": false
}
identifieraccepts the user's phone number or email address.- Repeated failures return
429(per account and per IP) — back off before retrying. - A deactivated account returns
423 Lockedwith acan_reactivateflag; usePOST /v1/auth/reactivateif it'strue.
Two-factor authentication
When the account has 2FA enabled, twofa_required comes back true and the
issued token is a temporary token that can only complete the challenge:
Ask the user for the 6-digit TOTP code from their authenticator app (or a backup code).
Call POST /v1/auth/2fa/verify with the temporary token in the
Authorization header and the code in the body. The response contains the
real access/refresh token pair.
Manage 2FA itself with POST /v1/auth/2fa/setup,
POST /v1/auth/2fa/verify-setup, GET /v1/auth/2fa/status,
POST /v1/auth/2fa/disable and GET /v1/auth/2fa/backup-codes.
Refreshing tokens
Access tokens are short-lived (see expires_at). Rotate them without
re-prompting for credentials:
curl -X POST https://api.getroja.com/v1/auth/refresh \
-H "Content-Type: application/json" \
-d '{ "refresh_token": "def50200ab..." }'
Refresh proactively — a minute or two before expiry — rather than waiting for
a 401 mid-flow.
Logging out
POST /v1/auth/logout revokes the current session's tokens. Call it whenever
the user explicitly signs out.
Other sign-in methods
- Social sign-in —
POST /v1/auth/googleandPOST /v1/auth/appleexchange provider identity tokens for Roja tokens. - Passkeys (WebAuthn) — begin/finish pairs at
/v1/auth/passkey/register/*and/v1/auth/passkey/login/*, with management atGET /v1/auth/passkeysandDELETE /v1/auth/passkeys/{id}.
Keep your tokens safe
Treat access and refresh tokens like passwords. Store them in secure platform storage (Keychain/Keystore), never in plain localStorage on shared devices, never in logs, and never in client-side analytics.