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).

PropertyDetail
method"flash_call"
Code length4 digits (fixed, embedded in caller ID)
How it worksWe 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 experienceUser 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 speedSub-second. The call is placed immediately and rings within 1-3 seconds.
CostFrom 0.4p per verification (UK). Flat rate, no volume tiers. See pricing.
Best forMobile apps (especially Android), cost-sensitive use cases, high-volume verification
LimitationsDoes 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.

PropertyDetail
method"voice"
Code length4 to 6 digits (configurable via code_length parameter)
How it worksWe 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 experienceUser answers the call and listens to the code. Clear, language-neutral digit-by-digit readout. The code is repeated twice for clarity.
CostFrom 2p per verification (UK, tier 1). Volume discounts at 10k and 100k+ monthly verifications. See pricing.
Best forLandline verification, fallback when flash calls fail, users who prefer voice, accessibility requirements
LimitationsUser 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.

PropertyDetail
method"sms"
Code length4 to 6 digits (configurable via code_length parameter)
How it worksWe send an SMS to the number containing the code. The message format is: "Your FlashVerify code is: 482916"
User experienceUser receives an SMS. On both Android and iOS, the keyboard auto-fill feature can detect and suggest the code automatically from the message.
CostFrom 3p per verification (UK, tier 1). Volume discounts at 10k and 100k+ monthly verifications. See pricing.
Best forUniversal fallback, markets where flash calls are not reliable, regulatory requirements for SMS, iOS-heavy audiences
LimitationsMost 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.

POST /v1/verify

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

ParameterTypeRequiredDescription
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.

POST /v1/verify/check

Verify the code entered by the user. The user has a maximum of 3 attempts before the verification expires automatically.

Request Body Parameters

ParameterTypeRequiredDescription
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
}
GET /v1/verify/{request_id}

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 /v1/balance

Get your current prepaid balance. Use this to monitor your account credit and trigger top-up alerts.

{
  "balance": {
    "amount": 42.50,
    "currency": "GBP"
  }
}
GET /v1/usage

Get usage summary for a date range, broken down by verification method. Useful for billing reconciliation and analytics.

Query Parameters

ParameterTypeRequiredDescription
fromdateOptionalStart date in YYYY-MM-DD format. Default: 30 days ago
todateOptionalEnd 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

EventDescription
verification.sentVerification initiated, call or SMS is in progress
verification.deliveredCall connected or SMS delivered to the handset
verification.verifiedUser submitted the correct code, verification complete
verification.expiredCode expired or maximum 3 attempts reached
verification.failedDelivery 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 StatusError CodeDescription
400invalid_phonePhone number is not in valid E.164 format
400invalid_codeIncorrect verification code submitted
400verification_expiredCode has expired or maximum 3 attempts reached
401unauthorizedInvalid or missing API key/secret
402insufficient_balanceAccount balance too low for this verification
403account_pendingAccount has not been approved yet
403account_suspendedAccount has been suspended by admin
404not_foundVerification request ID not found
429rate_limitedToo many requests. Respect your rate limit.
500internal_errorSomething 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.