FlashVerify API Documentation
Everything you need to integrate phone number verification using flash calls, voice OTP and SMS OTP. A service by 9Eons Limited, a UK-based telecommunications carrier.
Quick Start Guide
Get phone number verification working in your app in under 5 minutes. FlashVerify uses a simple REST API with HTTP Basic Authentication.
1. Create an account
Sign up at flashverify.net/signup. Your account will be reviewed and approved (usually within 1 hour). You will receive an email once approved.
2. Get your API keys
Once approved, log into your dashboard to find your API Key (32 hex characters) and API Secret (64 hex characters). Keep these secure.
3. Top up your balance
Add credit from the dashboard. Minimum top-up is $10 / £10 / €10. FlashVerify is prepaid with no monthly fees or contracts.
4. Send your first verification
Make an API call to initiate a flash call verification. The phone will ring once and the last 4 digits of the caller ID will contain the verification code.
curl -X POST https://api.flashverify.net/v1/verify \
-u "YOUR_API_KEY:YOUR_API_SECRET" \
-H "Content-Type: application/json" \
-d '{"phone_number": "+447700900000", "method": "flash_call"}'
5. Verify the code
Once the user has observed the code (from the caller ID, voice call or SMS), submit it to the check endpoint to confirm the verification.
curl -X POST https://api.flashverify.net/v1/verify/check \
-u "YOUR_API_KEY:YOUR_API_SECRET" \
-H "Content-Type: application/json" \
-d '{"request_id": "a1b2c3d4-...", "code": "1234"}'
Authentication
All API requests require HTTP Basic Authentication. Use your API Key as the username and API Secret as the password.
Authorization: Basic base64(API_KEY:API_SECRET)
Your API Key is a 32-character hex string. Your API Secret is a 64-character hex string. You can regenerate the secret from your dashboard at any time. The key stays the same.
Base URL: https://api.flashverify.net/v1
All requests and responses use JSON. Set Content-Type: application/json for POST requests. All responses include appropriate Content-Type and rate limit headers.
Verification Methods
FlashVerify supports three phone number verification methods. All three use the same API endpoints: just change the method parameter in your request. This makes it easy to implement fallback strategies.
Flash Call Verification
A flash call is a single ring where the last 4 digits of the caller ID contain the verification code. The call is never answered, making it the cheapest and fastest way to verify a phone number. Flash calls cost from just 0.4p per verification (UK).
| Property | Detail |
|---|---|
| method | "flash_call" |
| Code length | 4 digits (fixed, embedded in caller ID) |
| How it works | We call the number from a CLI like +441908731234. The last 4 digits (1234) are the code. The phone rings once and we hang up. |
| User experience | User sees a missed call. On Android, your app can auto-read the caller ID from the call log. On iOS, the user checks recent calls for the last 4 digits. |
| Delivery speed | Sub-second. The call is placed immediately and rings within 1-3 seconds. |
| Cost | From 0.4p per verification (UK). Flat rate, no volume tiers. See pricing. |
| Best for | Mobile apps (especially Android), cost-sensitive use cases, high-volume verification |
| Limitations | Does not work on landlines. Some carriers may block short-duration calls. Code length fixed at 4 digits. |
Platform behaviour: Android vs iOS
Android (seamless, zero-tap verification): With the READ_CALL_LOG and READ_PHONE_STATE permissions, your app can automatically read the incoming caller ID from the call log, extract the last 4 digits, and complete verification without any user interaction. The user does not need to answer the call or type anything. This makes flash call the best verification method for Android apps.
iOS (manual entry required): Apple does not allow apps to access the call log or read incoming caller IDs. The user will see a missed call notification and must manually open their recent calls (Phone app), find the missed call from the FlashVerify number, note the last 4 digits, and enter them in your app. Your UI should clearly instruct the user: "Check your recent calls and enter the last 4 digits of the number that just called you." For iOS-heavy audiences, consider using SMS OTP as the primary method with flash call as a cost-saving option for Android users.
Voice OTP Verification
Voice OTP is an automated phone call that reads a verification code aloud to the user. It works on all phone types including landlines, making it the most universal call-based verification method. Voice OTP starts from 2p per verification (UK) with volume discounts.
| Property | Detail |
|---|---|
| method | "voice" |
| Code length | 4 to 6 digits (configurable via code_length parameter) |
| How it works | We call the number, wait for the user to answer, then read the code aloud twice using text-to-speech: "Your verification code is: 4. 8. 2. 9. Again: 4. 8. 2. 9." |
| User experience | User answers the call and listens to the code. Clear, language-neutral digit-by-digit readout. The code is repeated twice for clarity. |
| Cost | From 2p per verification (UK, tier 1). Volume discounts at 10k and 100k+ monthly verifications. See pricing. |
| Best for | Landline verification, fallback when flash calls fail, users who prefer voice, accessibility requirements |
| Limitations | User must answer the call. Per-destination pricing varies by country. |
// Voice OTP example request
{
"phone_number": "+442071234567",
"method": "voice",
"code_length": 6,
"expiry_seconds": 300
}
SMS OTP Verification
SMS OTP sends a text message containing the verification code. It provides universal compatibility across all devices, networks and phone types. Both Android and iOS support auto-fill for SMS verification codes. SMS OTP starts from 3p per verification (UK) with volume discounts.
| Property | Detail |
|---|---|
| method | "sms" |
| Code length | 4 to 6 digits (configurable via code_length parameter) |
| How it works | We send an SMS to the number containing the code. The message format is: "Your FlashVerify code is: 482916" |
| User experience | User receives an SMS. On both Android and iOS, the keyboard auto-fill feature can detect and suggest the code automatically from the message. |
| Cost | From 3p per verification (UK, tier 1). Volume discounts at 10k and 100k+ monthly verifications. See pricing. |
| Best for | Universal fallback, markets where flash calls are not reliable, regulatory requirements for SMS, iOS-heavy audiences |
| Limitations | Most expensive method. Delivery dependent on mobile network SMS routing. Per-destination pricing varies by country. |
// SMS OTP example request
{
"phone_number": "+919876543210",
"method": "sms",
"code_length": 6,
"expiry_seconds": 300
}
Choosing a Verification Method
The best approach depends on your audience and budget. We recommend a fallback strategy that starts with the cheapest method and falls back to more universal options:
// Recommended fallback strategy:
// 1. Try flash_call first (cheapest at 0.4p, fastest delivery)
// 2. If user doesn't verify within 30s, retry with voice OTP
// 3. If voice call not answered, fall back to SMS
// Step 1: Flash call (cheapest)
POST /v1/verify {"phone_number": "+44...", "method": "flash_call"}
// ... wait 30 seconds, user didn't verify ...
// Step 2: Voice OTP (works on landlines too)
POST /v1/verify {"phone_number": "+44...", "method": "voice"}
// ... voice call not answered ...
// Step 3: SMS (universal fallback)
POST /v1/verify {"phone_number": "+44...", "method": "sms"}
Important: Each method call is a separate verification with its own request_id and is billed independently. Only the methods actually used are charged.
API Reference
The FlashVerify REST API uses standard HTTP methods. All endpoints require authentication. All request and response bodies use JSON.
Initiate a phone number verification. Sends a flash call, voice call, or SMS to the specified number. The phone number must be in E.164 format.
Request Body Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
| phone_number | string | Required | Phone number in E.164 format, e.g. +447700900000 or +919876543210 |
| method | string | Optional | flash_call (default), voice, or sms |
| code_length | integer | Optional | 4 for flash calls (fixed), 4-6 for voice/SMS. Default: 4 |
| expiry_seconds | integer | Optional | Code expiry in seconds. Default: 300 (5 minutes). Max: 600 (10 minutes) |
Success Response (201 Created)
{
"request_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"phone_number": "+919876543210",
"method": "flash_call",
"status": "sent",
"code_length": 4,
"cost": {
"amount": 0.004,
"currency": "GBP"
},
"expires_at": "2026-03-04T15:05:00Z"
}
Security note: The verification code is never returned in the API response. The user must observe the code from the caller ID (flash call), voice message (voice OTP) or text message (SMS OTP), and your app submits it to the check endpoint below.
Verify the code entered by the user. The user has a maximum of 3 attempts before the verification expires automatically.
Request Body Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
| request_id | string | Required | The request_id returned from the POST /v1/verify response |
| code | string | Required | The verification code entered by the user |
Success Response (200 OK)
{
"request_id": "a1b2c3d4-e5f6-...",
"status": "verified",
"phone_number": "+919876543210"
}
Failure Response (400 Bad Request)
{
"error": "invalid_code",
"message": "Incorrect code",
"attempts_remaining": 2
}
Check the current status of a verification request. Useful for polling or auditing.
Response (200 OK)
{
"request_id": "a1b2c3d4-...",
"phone_number": "+919876543210",
"method": "flash_call",
"status": "verified",
"cost": {"amount": 0.004, "currency": "GBP"},
"created_at": "2026-03-04T15:00:00Z",
"verified_at": "2026-03-04T15:00:45Z",
"expires_at": "2026-03-04T15:05:00Z"
}
Possible status values: sent, delivered, verified, expired, failed
Get your current prepaid balance. Use this to monitor your account credit and trigger top-up alerts.
{
"balance": {
"amount": 42.50,
"currency": "GBP"
}
}
Get usage summary for a date range, broken down by verification method. Useful for billing reconciliation and analytics.
Query Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
| from | date | Optional | Start date in YYYY-MM-DD format. Default: 30 days ago |
| to | date | Optional | End date in YYYY-MM-DD format. Default: today |
{
"from": "2026-03-01",
"to": "2026-03-04",
"total_verifications": 1250,
"successful": 1180,
"success_rate": 94.4,
"total_cost": {"amount": 6.25, "currency": "GBP"},
"by_method": {
"flash_call": {"count": 1000, "cost": 4.00},
"voice": {"count": 150, "cost": 3.00},
"sms": {"count": 100, "cost": 3.00}
}
}
Webhooks
Configure a webhook URL in your dashboard to receive real-time status updates for verifications. Webhooks are sent as HTTP POST requests with a JSON body. Your endpoint must respond with a 2xx status code within 5 seconds.
Webhook Payload
{
"event": "verification.delivered",
"request_id": "a1b2c3d4-...",
"phone_number": "+919876543210",
"method": "flash_call",
"status": "delivered",
"timestamp": "2026-03-04T15:00:02Z"
}
Webhook Events
| Event | Description |
|---|---|
| verification.sent | Verification initiated, call or SMS is in progress |
| verification.delivered | Call connected or SMS delivered to the handset |
| verification.verified | User submitted the correct code, verification complete |
| verification.expired | Code expired or maximum 3 attempts reached |
| verification.failed | Delivery failure: invalid number, unreachable, network error |
Verifying Webhook Signatures
Each webhook includes an X-FlashVerify-Signature header. Verify it using HMAC-SHA256 with your API Secret to ensure the request is authentic and has not been tampered with:
// PHP webhook signature verification
$signature = hash_hmac('sha256', $requestBody, $apiSecret);
$valid = hash_equals('sha256=' . $signature, $_SERVER['HTTP_X_FLASHVERIFY_SIGNATURE']);
Code Examples
Complete working examples for sending a phone verification request in popular languages.
Send a Verification
curl -X POST https://api.flashverify.net/v1/verify \
-u "YOUR_API_KEY:YOUR_API_SECRET" \
-H "Content-Type: application/json" \
-d '{
"phone_number": "+447700900000",
"method": "flash_call"
}'
import requests
response = requests.post(
"https://api.flashverify.net/v1/verify",
auth=("YOUR_API_KEY", "YOUR_API_SECRET"),
json={
"phone_number": "+447700900000",
"method": "flash_call"
}
)
data = response.json()
print(f"Request ID: {data['request_id']}")
print(f"Status: {data['status']}")
print(f"Cost: {data['cost']['currency']} {data['cost']['amount']}")
const response = await fetch("https://api.flashverify.net/v1/verify", {
method: "POST",
headers: {
"Content-Type": "application/json",
"Authorization": "Basic " + btoa("YOUR_API_KEY:YOUR_API_SECRET")
},
body: JSON.stringify({
phone_number: "+447700900000",
method: "flash_call"
})
});
const data = await response.json();
console.log(`Request ID: ${data.request_id}`);
console.log(`Cost: ${data.cost.currency} ${data.cost.amount}`);
$ch = curl_init("https://api.flashverify.net/v1/verify");
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_USERPWD => "YOUR_API_KEY:YOUR_API_SECRET",
CURLOPT_HTTPHEADER => ["Content-Type: application/json"],
CURLOPT_POSTFIELDS => json_encode([
"phone_number" => "+447700900000",
"method" => "flash_call"
])
]);
$response = json_decode(curl_exec($ch), true);
echo "Request ID: " . $response["request_id"] . "\n";
echo "Cost: " . $response["cost"]["currency"] . " " . $response["cost"]["amount"];
Error Codes
All errors return a JSON object with error and message fields. Use the HTTP status code and error code to handle errors programmatically.
{"error": "insufficient_balance", "message": "Your balance is too low for this request"}
| HTTP Status | Error Code | Description |
|---|---|---|
| 400 | invalid_phone | Phone number is not in valid E.164 format |
| 400 | invalid_code | Incorrect verification code submitted |
| 400 | verification_expired | Code has expired or maximum 3 attempts reached |
| 401 | unauthorized | Invalid or missing API key/secret |
| 402 | insufficient_balance | Account balance too low for this verification |
| 403 | account_pending | Account has not been approved yet |
| 403 | account_suspended | Account has been suspended by admin |
| 404 | not_found | Verification request ID not found |
| 429 | rate_limited | Too many requests. Respect your rate limit. |
| 500 | internal_error | Something went wrong on our end. Contact support if persistent. |
Rate Limiting
The default rate limit is 10 requests per second per API key. Every response includes rate limit headers so your application can adapt:
X-RateLimit-Limit: 10
X-RateLimit-Remaining: 7
X-RateLimit-Reset: 1709564400
Need a higher rate limit? Contact us to increase your limit for high-volume use cases.
Frequently Asked Questions
What is a flash call and how does it verify a phone number?
A flash call is a verification method where we place a single ring to the user's phone from a number whose last 4 digits contain the verification code. For example, if the code is 1234, the phone will show a missed call from +441908731234. The call is never answered, so there is no call charge to the user. It is the cheapest phone verification method available, starting from just 0.4p per verification.
Does flash call verification work on both Android and iOS?
Yes, but the experience differs. On Android, your app can use the READ_CALL_LOG and READ_PHONE_STATE permissions to automatically read the caller ID from the call log and extract the code, providing seamless zero-tap verification. On iOS, Apple does not allow apps to access the call log, so the user must manually check their recent calls in the Phone app, find the missed call, and enter the last 4 digits of the calling number into your app.
What is the difference between flash call, voice OTP and SMS OTP?
Flash call is the cheapest (from 0.4p): a missed call where the code is in the caller ID. Voice OTP (from 2p) is an automated call that reads the code aloud, works on landlines too. SMS OTP (from 3p) sends a text message with the code, with auto-fill support on both Android and iOS. All three use the same API, just change the method parameter.
How long does delivery take?
Flash calls are delivered in under 3 seconds (sub-second initiation). Voice OTP calls are placed within 2-5 seconds. SMS delivery depends on the destination network but is typically under 10 seconds for Tier 1 countries.
Is there a minimum spend or monthly fee?
No monthly fees, no contracts, no minimum spend. FlashVerify is entirely pay-as-you-go. Top up your balance from just £10 / $10 / €10 and pay only for verifications you actually send. Unused balance does not expire.
Which countries are supported?
FlashVerify supports phone verification to 200+ countries. Flash call availability depends on the destination carrier. Voice OTP and SMS OTP have near-universal coverage. Check the pricing page for per-country rates, or contact us for rates to specific destinations.
How do I handle verification failures?
We recommend a fallback strategy: try flash call first (cheapest), then voice OTP if the user does not verify within 30 seconds, then SMS as a final fallback. Each attempt uses its own request_id and is billed independently. Only methods actually used are charged.
Is FlashVerify GDPR compliant?
Yes. FlashVerify is operated by 9Eons Limited, a UK-based company. All data is processed in compliance with GDPR and UK data protection laws. Phone numbers are encrypted at rest using AES-256-GCM. See our privacy policy for details.