POST /v1/otp/request to generate a fresh numeric OTP and deliver it to a phone via SMS (default), voice call, or WhatsApp. Requests are scoped to the Developer App bound to your X-API-Key — Karibu resolves the app automatically; you do not send app_key in the body when the key is bound. Calling it always invalidates any prior unused, unexpired OTP for the same (phone, app) before issuing the new one, so there is never more than one active OTP for a phone within an app.
Each channel has its own payload shape. The fields sender_id and message_template are SMS-only — they exist for SMS branding/wording control and are silently ignored on "call" and "whatsapp". Voice reads the code via TTS; WhatsApp routes through the platform-managed briq_otp template with automatic sender resolution.
Default to "sms" for the broadest reach. Use "call" for SMS-restricted regions or accessibility needs, and "whatsapp" for app-installed users with chat-first habits.
Endpoint
X-API-Key (required — bind to a Developer App for OTP), Content-Type: application/json (required).
Common request fields
These fields are the same on every channel:callback_url and callback_secret are optional. When set, Karibu associates them with this OTP and POSTs flake.verified or flake.failed to your URL after verify outcomes. See Flake lifecycle callbacks for the full flow and testing guide.Success response
The same shape on every channel:Channel-specific payload & code samples
- SMS
- Voice call
- WhatsApp
Default channel. Customisable per call via
sender_id and message_template.Channel-specific fields:Exact payload:
Error responses
For the full cross-endpoint error reference, see Error scenarios.
Best practices
- Validate the phone client-side before calling the API: digits-only, country code present, plausible length.
- Store
data.expires_atso your UI can drive a countdown timer; consider polling/v1/otp/statusinstead of triggering re-sends speculatively. - Cascade channels for reliability. A common pattern: try
"whatsapp"first; on a dispatcher 400, fall back to"sms"; offer"call"as a manual third option. - Don’t promise custom WhatsApp wording. The
briq_otptemplate is fixed by Meta —sender_idandmessage_templateare silently ignored on"whatsapp"and"call". - Rate-limit your own users. The API does not enforce per-phone request limits — your application should.
- Never log the plaintext code. It only exists in transit to the recipient.
What’s next
- Once the code is sent, verify what the user submits — see Validating OTP codes.
- For “Resend code” buttons, lockouts on logout, and live countdowns, see Managing OTP lifecycle.