api: 99.99%

OTPs not
Complexity

Deliver OTPs across Africa in real time
in one request.

copy AI prompt
POST /v1/otp/send HTTP/1.1
Host: api.tambua.me
Authorization: Bearer $TAMBUA_KEY
Content-Type: application/json

{
  "phone": "+254712345678",
  "purpose": "login"
}
200 OK · 142msverified
id: "tambua_otp_8f3a9c12"
channel: "sms"
expires: "5m"
// AI SKILL

Skip the docs.
Brief your AI.

One paste into Cursor, Claude or ChatGPT and your assistant knows the endpoints, auth, bulk body shape and channel rules. No SDK required — works with plain fetch / requests / cURL.

tambua-api.prompt
Drop into your AI assistant's system prompt or skill folder
// QUICKSTART

As easy,
As send, see, tick.

No SDK required, no SIM pools to provision, no carrier contracts. Use cURL if you want.

01

Send the code

One endpoint, every channel. We pick the carrier route for the destination country.

POST /v1/otp/send
phone="+254712345678"
channel="sms"
02

User receives it

Carrier-graded SMS, email, WhatsApp or voice — same payload, one signed receipt.

> "482910 is your Lendeka
>  verification code.
>  Expires in 5 minutes."
03

Verify in one call

POST the code back. Get verified, expired, or attempts-left in a single response.

POST /v1/otp/verify
id="tambua_otp_8f3a9c12"
code="482910"
// DELIVERY JOURNEY

If one channel misses,
the next one delivers.

Set an ordered fallback for each app: SMS first, then WhatsApp, then Voice. One code, one token, one verify call.

1SMS
if it fails
2WhatsApp
if it fails
3Voice
  • Instant or timed. Fall back the moment a channel fails, or after 1, 2, 5 or 10 minutes without a delivery receipt.
  • One OTP. The same code and the same otp_token across every attempt, so you verify once.
  • Pay for what lands. Only attempts a carrier accepts are billed. Failed attempts are free.
  • Fully visible. Every attempt is logged, and an otp.fallback_triggered webhook tells your backend.
  • Stay in control. Leave out channel to run your journey, or pass channel= to force one.
POST /v1/otp/send
# no channel: your journey runs
{ "phone": "+254712345678", "purpose": "login" }
201 Created
{
  "otp_id": "tambua_otp_8f3a9c12",
  "channel": "whatsapp",
  "journey": {
    "step": 2,
    "steps": 3,
    "attempts": [
      { "step": 1, "channel": "sms",      "status": "failed" },
      { "step": 2, "channel": "whatsapp", "status": "sent"   }
    ]
  },
  "otp_token": "…"
}
channel=sms

SMS

Local routes in Kenya, with more African markets to follow. Auto carrier failover.

channel=email

Email

Transactional sending with sub-second deliverability.

channel=whatsapp

WhatsApp

Approved templates with native verification flows.

channel=voice

Voice

Spoken codes for landlines and accessibility.

channel=mpesa

M-PESA

Verify Kenyan users with an M-PESA PIN prompt confirmed by Safaricom — no code to type.

channel=reverse

Reverse OTP

The user sends an SMS or places a missed call to verify themselves. Inbound, code-free.

coming soon

Telegram

Verification through the Telegram bot platform.

coming soon

USSD

Session-based codes over USSD — no data plan needed.

coming soon

Shortcode

Dedicated short codes for high-throughput sender IDs.

// CONSOLE

Every OTP, accounted for.

Live delivery rates, verification logs, per-environment balance and failure breakdowns. The console mirrors the API — what you see is what your code sees.

Overview
Sample data, updating live
Live
Delivery journey1SMS→2WhatsApp→3Voice6.1% of today's codes were recovered by a fallback
Wallet balance Live
KES 42,860.40
≈ 11 days at your current usage
Verifications · 24h
18,420
+12.4% vs yesterday
Delivery rate
98.8%
+0.4 pts vs last 7d
Verification success
94.9%
+1.8 pts vs last 7d
Delivery by channelLast 24h · 18,420 sent
ChannelSentDelivered
SMS8,10599.1%
WhatsApp4,42199.4%
Email2,02698.9%
Voice1,47497.8%
M-PESA1,65899.7%
Reverse OTP73799.2%
Needs attention0 open
✓
All clear

Failures and warnings show up here with a fix.

1,124

codes delivered by a fallback channel in the last 24h that a single channel would have missed

Recent requestsView all logs →
  • Verified+254 712 ••• 412SMS3s ago
  • Verified+234 803 ••• 075WhatsApp7s ago
  • Delivered+254 722 ••• 908M-PESA12s ago
  • Verifiedj•••@g•••.comEmail18s ago
  • Verified+233 244 ••• 631Fallback usedWhatsApp26s ago
  • Verified+256 772 ••• 190Voice35s ago
// WEBHOOKS

Signed events.
Replay any time.

POST'd as JSON with an HMAC signature. We retry failed deliveries with exponential backoff up to 24h, and you can replay any event from the dashboard.

otp.createdCode generated
otp.deliveredCarrier DLR
otp.verifiedUser entered code
otp.failedMax attempts
otp.expiredTTL elapsed
otp.undeliveredCarrier error
otp.fallback_triggeredMoved to next channel
otp.verified · sample payload 200 OK
POST https://yourapp.com/webhooks/tambua
Content-Type: application/json
X-Tambua-Signature: t=1716305544,v1=5257a8…
X-Tambua-Event: otp.verified

{
  "id": "tambua_evt_88f0a64",
  "type": "otp.verified",
  "created": "2026-05-25T14:32:24.110Z",
  "data": {
    "otp_id": "tambua_otp_8f3a9c12",
    "purpose": "login",
    "channel": "sms",
    "verified_at": "2026-05-25T14:32:24.108Z"
  }
}

Send your first OTP
before this page reloads.

Test keys are free and need no card. The code comes back in the API response, so you can build and test without a phone.

Get the AI prompt
# in your terminal, right now

$ export TAMBUA_KEY=tambua_live_…
$ curl -X POST https://api.tambua.me/v1/otp/send \
    -H "Authorization: Bearer $TAMBUA_KEY" \
    -d '[{"phone":"+254712345678"}]'

→ otp_8f3a9c12 sent · 142ms