Identity
In Soxara, a user is their phone number. There is no password column anywhere in the system — not in the database, not in memory, not in any API.
identifier → +231881158457 (E.164)
session → JWT minted after OTP verification
authorize → PIN entered in the Soxara app (for sensitive operations)Why no passwords
A password adds friction without adding much security in a mobile-first market — most users forget them and reset via SMS, which means the SMS is the security boundary anyway. Soxara took the SMS step out of the loop entirely:
- First login: phone → OTP delivered via WhatsApp (not SMS) → JWT issued.
- Returning user on the same device: existing JWT or biometric unlock.
- Sensitive operations (send money, change limits, reveal card number): PIN entry inside the app, which mints a short-lived “step-up” token.
The OTP-by-WhatsApp choice is deliberate: if an attacker has SIM-swapped a user’s phone they’d also receive an SMS OTP, but they typically don’t have access to the WhatsApp account on the new SIM until it’s been re-verified — a slower path that gives the legitimate user time to react.
What you’ll see in API responses
Anywhere a user appears in an API response — as the payer of a payment, the recipient of a transfer, the buyer of a gift card — they’re identified by:
{
"id": "usr_8K2nP3...",
"phone_number": "+231881158457",
"country_code": "LR"
}phone_number is always in E.164 format. country_code is ISO-3166 alpha-2.
You’ll never see a user’s PIN, password hash, or biometric data in any response. Those don’t leave the user’s device or the auth service’s secure storage.
You don’t initiate user auth
The Soxara API doesn’t expose user OTP flows to integrators. Your customers authenticate to Soxara through Soxara’s own surfaces (WhatsApp or the mobile app). You authenticate to us with your merchant API key.
The one exception is the viral claim flow: when you send a payment to a phone number that isn’t yet a Soxara user, the recipient gets a WhatsApp claim link, completes KYC inside our flow, and once that finishes you get a payment.claimed webhook. You never handle their PIN, OTP, or biometric.
Phone format
Always E.164. Always with +. Always include the country code.
Good: +231881158457
Good: +12025551234
Bad: 0881158457 (missing country code)
Bad: 231 881 158 457 (spaces)
Bad: (231) 881-158-457 (formatting)
The API will reject malformed numbers with a VALIDATION_ERROR. There’s no auto-correction; we don’t try to guess the country.