Auth
Base path: /auth
Register
POST /auth/register — Public
{
"email": "you@example.com",
"password": "Str0ngPass!",
"full_name": "Jane Doe",
"company_name": "Mama Mboga Supplies",
"phone": "0712345678",
"business_type": "retail",
"country": "Kenya"
}Password must be 8+ characters with at least one uppercase letter and one digit.
201 response — includes api_key, shown only this once:
{
"id": "e7b1...",
"email": "you@example.com",
"full_name": "Jane Doe",
"company_name": "Mama Mboga Supplies",
"api_key": "sk_live_xxxxxxxxxxxxxxxxxxxx",
"api_key_prefix": "sk_live_xxxxxxxx",
"is_active": true,
"is_verified": false,
"wallet": { "balance_kes": 0 },
"created_at": "2026-07-01T10:00:00Z"
}409 if the email is already registered.
Login
POST /auth/login — Public
{ "email": "you@example.com", "password": "Str0ngPass!" }{
"access_token": "eyJ...",
"refresh_token": "eyJ...",
"token_type": "bearer",
"expires_in": 1800
}401 on bad credentials. 403 if the account has been suspended.
Refresh
POST /auth/refresh — Public
{ "refresh_token": "eyJ..." }Returns a new token pair in the same shape as login.
Verify email
Two independent ways to confirm an account — either completes verification and credits the one-time welcome bonus (5 free SMS):
GET /auth/verify-email?token=...— the link emailed at registration; redirects to the dashboard on success.- OTP flow, for the dashboard’s blocking verification modal:
POST /auth/send-verification-code(authenticated) — emails a 6-digit code, valid 10 minutes.POST /auth/verify-codewith{ "code": "123456" }— max 5 attempts before the code is locked out and a new one must be requested.
POST /auth/resend-verification re-sends the email-link flow: { "email": "..." }.
Forgot / reset password
POST /auth/forgot-password—{ "email": "..." }. Always returns a generic success message, whether or not the email exists.POST /auth/reset-password—{ "token": "...", "new_password": "..." }. Token expires after 1 hour.
Current user
GET /auth/me — returns the authenticated user, including their wallet balance.
Profile & password
PATCH /auth/profile— updatefull_name,company_name,phone,business_type,country. Email cannot be changed here (see/auth/pending-emailfor unverified accounts).PATCH /auth/change-password—{ "current_password": "...", "new_password": "..." }.
Rotate API key
POST /auth/rotate-api-key — issues a brand-new key and immediately invalidates the old one.
The new key is returned once, in the response — store it immediately.