Skip to main content

Authentication

Two credential types, for two audiences:

CredentialForHeader
JWTpeople (apps with a signed-in user)Authorization: Bearer <access>
API keysystems (your backend, integrations)Authorization: Api-Key adas_test_…

People: phone + password

Accounts are phone-first — no email required. SMS one-time codes are deliberately not the login mechanism (SMS costs money on every African route; passwords are free forever). OTP exists as a separate one-time phone-verification step and is currently disabled while pre-launch (503 OTP_DISABLED).

POST /v1/auth/register {phone, password} → 201 {access, refresh, user}
POST /v1/auth/login {phone, password} → 200 {access, refresh, user}
POST /v1/auth/token/refresh {refresh} → 200 {access}
POST /v1/auth/password/change {current_password, new_password} (JWT)
GET /v1/auth/me (JWT)

Phones must be E.164 (+260971234567); spacing and dashes are tolerated. Access tokens live 30 minutes; refresh tokens 30 days and rotate on use.

user.phone_verified is false until a verification event (OTP when SMS launches, or in-person agent attestation). Treat it as a trust signal, not a gate.

Systems: API keys

Stripe-style: adas_test_… / adas_live_…, shown once at creation, stored hashed. Manage them with a JWT:

GET /v1/keys/ list your keys (prefixes only)
POST /v1/keys/ {name, mode: "test"|"live"} → includes "key" ONCE
DELETE /v1/keys/{id} revoke
Test vs live

Both modes hit the same data today. Sandbox data isolation for test keys ships with the billing milestone — build against test keys now and nothing will change for you.