OTP API

OTP API for Ghana

Protect signups, transactions, and logins with one-time passwords delivered in under 3 seconds. Built for Ghana’s banks, fintechs, and e-commerce platforms.

send-otp.sh
# Send an OTP in one API call
curl -X POST https://sms.arkesel.com/api/v2/otp/send \
  -H "api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "expiry": 5,
    "length": 6,
    "medium": "sms",
    "message": "Your verification code is %otp_code%. It expires in 5 minutes.",
    "number": "+233244000000",
    "sender_id": "MyApp",
    "type": "numeric"
  }'
200 OK — {"code":"1000","message":"Successful, OTP is being processed for delivery"}

Trusted by 10,000+ businesses across Africa

Ebits Arkbank OyaGhana UDS AppSol ShrinQ Ashfoam Tospino
< 3s
Average Delivery
High
Availability
3
Channels (SMS · Voice · USSD)
5
African Markets

Everything you need to verify users

A complete OTP infrastructure so you can focus on building your product, not managing verification logic.

Multi-Channel Delivery

Deliver OTPs via SMS, Voice call, or USSD. Automatic voice fallback when SMS fails.

Configurable Expiry & Length

Set OTP length (4–8 digits) and expiry time (1–30 minutes) per request. Different flows, different rules.

Rate Limiting & Fraud Protection

Built-in rate limiting per phone number. Prevent OTP bombing and brute-force verification attempts.

Delivery Receipts & Webhooks

Real-time delivery status callbacks. Know when each OTP is delivered, expired, or verified.

Custom Sender ID

Send from your brand name instead of a random number. Build trust with every verification message.

Verify a user in 2 API calls

One POST to send the OTP, another to verify it. Arkesel handles code generation, delivery, expiry, and multi-channel fallback.

  • Generate and send with one POST
  • Verify with a second POST
  • SMS, Voice, and USSD delivery
  • Automatic expiry handling
Full API Reference
send-otp.sh
# Step 1: Send OTP
curl -X POST https://sms.arkesel.com/api/v2/otp/send \
  -H "api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "expiry": 5,
    "length": 6,
    "medium": "sms",
    "message": "Your code is %otp_code%",
    "number": "+233244000000",
    "sender_id": "MyApp",
    "type": "numeric"
  }'

# Step 2: Verify OTP
curl -X POST https://sms.arkesel.com/api/v2/otp/verify \
  -H "api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"code": "173882", "number": "+233244000000"}'
200 OK — {"code":"1100","message":"Successful"}
import requests

API_KEY = "YOUR_API_KEY"
BASE = "https://sms.arkesel.com/api/v2/otp"
headers = {"api-key": API_KEY, "Content-Type": "application/json"}

# Step 1: Send OTP
send = requests.post(f"{BASE}/send", json={
    "expiry": 5, "length": 6, "medium": "sms",
    "message": "Your code is %otp_code%",
    "number": "+233244000000",
    "sender_id": "MyApp", "type": "numeric"
}, headers=headers)

# Step 2: Verify OTP
verify = requests.post(f"{BASE}/verify", json={
    "code": "173882",
    "number": "+233244000000"
}, headers=headers)
print(verify.json())
200 OK — {"code":"1100","message":"Successful"}
const API_KEY = "YOUR_API_KEY";
const BASE = "https://sms.arkesel.com/api/v2/otp";
const headers = { "api-key": API_KEY, "Content-Type": "application/json" };

// Step 1: Send OTP
const send = await fetch(`${BASE}/send`, {
  method: "POST", headers,
  body: JSON.stringify({
    expiry: 5, length: 6, medium: "sms",
    message: "Your code is %otp_code%",
    number: "+233244000000",
    sender_id: "MyApp", type: "numeric"
  })
});

// Step 2: Verify OTP
const verify = await fetch(`${BASE}/verify`, {
  method: "POST", headers,
  body: JSON.stringify({ code: "173882", number: "+233244000000" })
});
console.log(await verify.json());
200 OK — {"code":"1100","message":"Successful"}
$apiKey = "YOUR_API_KEY";
$base = "https://sms.arkesel.com/api/v2/otp";
$headers = ["api-key: $apiKey", "Content-Type: application/json"];

// Step 1: Send OTP
$ch = curl_init("$base/send");
curl_setopt_array($ch, [
    CURLOPT_POST => true,
    CURLOPT_HTTPHEADER => $headers,
    CURLOPT_POSTFIELDS => json_encode([
        "expiry" => 5, "length" => 6, "medium" => "sms",
        "message" => "Your code is %otp_code%",
        "number" => "+233244000000",
        "sender_id" => "MyApp", "type" => "numeric"
    ]),
    CURLOPT_RETURNTRANSFER => true,
]);
curl_exec($ch);

// Step 2: Verify OTP
curl_setopt($ch, CURLOPT_URL, "$base/verify");
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode([
    "code" => "173882", "number" => "+233244000000"
]));
echo curl_exec($ch);
curl_close($ch);
200 OK — {"code":"1100","message":"Successful"}

OTP verification for every industry

From banking to SaaS, secure your users with phone-based verification that works across Ghana.

Bank Transaction Verification

Confirm wire transfers, card payments, and account changes with instant OTP verification.

E-Commerce Checkout

Verify buyers at checkout to reduce fraud and chargebacks. One-tap verification on mobile.

Fintech Account Onboarding

KYC phone verification for mobile money, digital wallets, and lending platforms.

Ride-Hailing Verification

Verify drivers and riders during signup. Confirm identity before every trip for safety.

Healthcare Patient Portals

Secure patient data access with OTP login. Protect health records with multi-channel verification.

SaaS Passwordless Login

Replace passwords with OTP-based magic links. Faster login, fewer support tickets.

Why build OTP with Arkesel?

Ship in Minutes, Not Weeks

Building OTP from scratch means token generation, secure storage, expiry logic, retry mechanisms, and multi-channel routing. With Arkesel, it’s two API calls and you’re live.

Three Channels, One Integration

SMS fails? OTP retries via voice call automatically. Voice unavailable? Fall back to USSD. Three delivery channels behind a single API — higher verification rates without extra code.

Security Without the Engineering

Cryptographically random codes, server-side rate limiting, automatic expiry, and brute-force protection. All handled for you — no security audit needed on your OTP logic.

USSD Verification — No App Required

Verify users via USSD on any phone, no internet needed. A channel most OTP providers don’t offer, built into the same API.

Simple, transparent OTP pricing

Pay per verification. No monthly fees, no hidden charges.

Voice OTP
GHS 0.200
per minute
Per-minute billing. Charged only for answered calls.
View full pricing →
No monthly fees
No minimum commitment
Free test credits

Go live in 3 steps

From sign-up to first OTP in under 5 minutes.

1

Create an Account

Sign up for free and get instant access to your dashboard and API credentials.

2

Get Your API Key

Generate an API key from the dashboard. Use it in the api-key header for all requests.

3

Send Your First OTP

Copy a code sample, replace the API key, and verify your first user in seconds.

Start verifying users today

Free to sign up. No credit card required. Get your API key and send your first OTP in under 5 minutes.

Scroll to Top