Back to Blog

SMS Verification API for Developers: Build Secure Signups

May 18, 2026

Phone verification is the backbone of account security — but building it yourself means juggling SIMs, dealing with SMS gateways, and handling edge cases like expired codes and failed deliveries. A SMS verification API abstracts all of that away: you request a number, the user triggers a code, you fetch the OTP programmatically, and you verify the signup. Done.

This developer guide walks through the AgoVerify SMS Verification API — what it offers, how to authenticate, and working code examples for renting a number and retrieving an OTP.

What the AgoVerify API Offers

  • Rent a virtual number for any supported service and country
  • Retrieve the received OTP programmatically once it arrives
  • Check order status and auto-cancel/refund on failure
  • Manage account balance and transaction history
  • Place SMM orders (followers, likes, views) via the same API
  • Rate-limited, authenticated with API keys — safe for production

Full interactive documentation is available at /api/docs, and a Postman collection ships in docs/agoverify-api-postman.json.

Authentication

Every request is authenticated with an API key. Generate and rotate keys from the developer dashboard. Pass your key in the request header:

Authorization: Bearer YOUR_API_KEY
Accept: application/json

All endpoints are rate-limited per key. Hitting the limit returns 429 Too Many Requests with a Retry-After header.

Core Flow: Rent a Number and Get an OTP

The typical verification flow has three steps:

1. Rent a number

POST /api/v1/numbers
Content-Type: application/json

{
  "service": "whatsapp",
  "country": "us"
}

Response:

{
  "order_id": 10245,
  "number": "+12025550173",
  "service": "whatsapp",
  "country": "us",
  "status": "pending",
  "expires_at": "2026-08-23T18:05:00Z"
}

2. Trigger the SMS on the target platform

Hand number to your user (or your test harness) and have the target platform send the OTP to it. This step happens outside the API.

3. Poll for the OTP

GET /api/v1/numbers/10245

Response once the SMS arrives:

{
  "order_id": 10245,
  "number": "+12025550173",
  "status": "completed",
  "code": "372914",
  "received_at": "2026-08-23T18:02:11Z"
}

If the rental window expires with no SMS, the order moves to cancelled and the balance is refunded automatically — no extra call needed.

Code Example: PHP with Guzzle

$apiKey = 'YOUR_API_KEY';
$base = 'https://agoverify.com/api/v1';

// 1. Rent a number for WhatsApp in the US
$rent = $client->post("$base/numbers", [
    'headers' => ['Authorization' => "Bearer $apiKey"],
    'json' => ['service' => 'whatsapp', 'country' => 'us'],
]);
$order = json_decode($rent->getBody(), true);
echo "Number: {$order['number']}\n";

// 2. Poll until the OTP arrives (or the order expires)
while (true) {
    sleep(5);
    $status = $client->get("$base/numbers/{$order['order_id']}", [
        'headers' => ['Authorization' => "Bearer $apiKey"],
    ]);
    $res = json_decode($status->getBody(), true);
    if ($res['status'] === 'completed') {
        echo "OTP: {$res['code']}\n";
        break;
    }
    if ($res['status'] === 'cancelled') {
        echo "No SMS received — refunded.\n";
        break;
    }
}

Code Example: Python with requests

import requests, time

API_KEY = "YOUR_API_KEY"
BASE = "https://agoverify.com/api/v1"
HEADERS = {"Authorization": f"Bearer {API_KEY}"}

# Rent a number
order = requests.post(f"{BASE}/numbers",
    headers=HEADERS,
    json={"service": "whatsapp", "country": "us"},
).json()
print(f"Number: {order['number']}")

# Poll for the OTP
while True:
    time.sleep(5)
    res = requests.get(f"{BASE}/numbers/{order['order_id']}", headers=HEADERS).json()
    if res["status"] == "completed":
        print(f"OTP: {res['code']}")
        break
    if res["status"] == "cancelled":
        print("No SMS — refunded.")
        break

Best Practices for Production

  • Don't poll too aggressively. 5-second intervals are a good balance. The rental window is short, so don't sleep too long either.
  • Handle cancelled gracefully. Auto-refunds happen server-side — just retry with a different country if a number fails.
  • Store order_id so you can reconcile status later, even after your polling loop exits.
  • Keep your API key secret. Use environment variables or a secrets manager — never commit it to a repo.
  • Respect rate limits. On 429, back off using the Retry-After header.
  • Validate the service/country combo before presenting it to users — not every service is available in every country.

Use Cases

  • Phone-verified signups for your own app without storing real user numbers
  • Automated test accounts for QA across hundreds of services
  • Marketing at scale — create verified accounts per client or campaign
  • Reseller platforms — build your own number-rental storefront on top of the API
  • SMM automation — combine number rental with the SMM order endpoints to run full growth campaigns

Frequently Asked Questions

How long is the rental window?

Typically a few minutes — enough to receive a single OTP. The exact window is returned in expires_at on the rental response.

What happens if no SMS arrives?

The order auto-cancels at expiry and your balance is refunded. No support ticket required.

Can I rent the same number again?

Numbers are released after each rental. For persistent 2FA, use a long-term virtual line or your own SIM.

Is there a sandbox?

Use the lowest-cost service/country combo to test the flow end-to-end with minimal spend. Full interactive docs are at /api/docs.

Start Building

Generate an API key from the developer dashboard, grab the interactive docs, and ship phone-verified signups in an afternoon. The AgoVerify SMS Verification API handles the SIMs, gateways, and failover — you focus on your product.

Accepted Payment Methods

MTN
MoMo
ORANGE
MONEY