DEV Community

Dishant Singh
Dishant Singh

Posted on

Virtual Phone Numbers for Developers: Complete API Guide 2026

Virtual Phone Numbers for Developers: Complete API Guide 2026

Virtual phone numbers aren't just a privacy tool — for developers, they're infrastructure. From integration testing to multi-account management to production SMS workflows, a reliable virtual number API is something every developer building with phone-based services eventually needs.

This guide covers everything: how virtual numbers work at the carrier level, what the API landscape looks like, and a practical reference for integrating them into your stack.


How Virtual Phone Numbers Work

A virtual phone number is a PSTN-routable number without a physical SIM. The carrier assigns a DID (Direct Inward Dial) number that routes to an internet endpoint instead of a handset.

SMS Sender → Mobile Carrier Network
                    ↓
            DID Routing Table
                    ↓
        Virtual Number Provider API
                    ↓
         Your Webhook / Dashboard
Enter fullscreen mode Exit fullscreen mode

VoIP vs. Non-VoIP Numbers

This distinction matters enormously for verification use cases:

Type How it works Platform acceptance
VoIP Internet-based (SIP/VoIP) Blocked by Google, WhatsApp, Meta
Non-VoIP Real SIM-backed carrier Accepted everywhere

Services like Google Voice and Skype numbers are VoIP. NumberOTP provides SIM-backed non-VoIP numbers — which pass on platforms that reject VoIP.


Use Cases by Developer Type

Integration Testing

def test_phone_verification_flow():
    # Get a test number instead of hardcoding
    number_data = numberotp_client.get_number(country="us")

    # Trigger SMS verification in your app
    response = requests.post("/api/verify/send", json={
        "phone": number_data["number"]
    })
    assert response.status_code == 200

    # Verify the SMS was actually sent and received
    sms = numberotp_client.wait_for_sms(number_data["id"])
    assert "verification" in sms.lower()

    # Complete verification
    code = extract_otp(sms)
    complete = requests.post("/api/verify/confirm", json={"code": code})
    assert complete.status_code == 200
Enter fullscreen mode Exit fullscreen mode

Multi-Account Management

Developers building tools that manage multiple accounts across platforms need unique, reliable phone numbers per account. NumberOTP's virtual numbers are private (not shared), so each account gets a distinct number.

Webhook-Driven SMS Workflows

// Express.js webhook endpoint
app.post('/webhook/sms', express.json(), (req, res) => {
  const { from, to, body, timestamp } = req.body;

  const handler = smsRoutes.get(to);
  if (handler) {
    handler({ from, body, timestamp });
  }

  res.status(200).json({ received: true });
});
Enter fullscreen mode Exit fullscreen mode

NumberOTP API Reference

The NumberOTP API follows standard REST conventions. Base URL: https://numberotp.com/api

Authentication

All endpoints require an X-API-Key header:

X-API-Key: your_api_key_here
Enter fullscreen mode Exit fullscreen mode

Core Endpoints

GET /numbers — Request a virtual number

curl -X GET "https://numberotp.com/api/numbers" \
  -H "X-API-Key: YOUR_KEY" \
  -G \
  --data-urlencode "country=us" \
  --data-urlencode "service=google"
Enter fullscreen mode Exit fullscreen mode

Response:

{
  "id": "num_abc123",
  "number": "+12025551234",
  "country": "us",
  "service": "google",
  "expires_at": "2026-05-19T15:30:00Z",
  "credits_used": 0.10
}
Enter fullscreen mode Exit fullscreen mode

GET /sms/{number_id} — Poll for incoming SMS

curl "https://numberotp.com/api/sms/num_abc123" \
  -H "X-API-Key: YOUR_KEY"
Enter fullscreen mode Exit fullscreen mode

Response:

{
  "number_id": "num_abc123",
  "messages": [
    {
      "id": "sms_xyz789",
      "from": "+12125550000",
      "body": "Your Google verification code is 847291",
      "received_at": "2026-05-19T15:12:33Z"
    }
  ]
}
Enter fullscreen mode Exit fullscreen mode

DELETE /numbers/{number_id} — Cancel / trigger refund

curl -X DELETE "https://numberotp.com/api/numbers/num_abc123" \
  -H "X-API-Key: YOUR_KEY"
Enter fullscreen mode Exit fullscreen mode

Returns 200 with refund confirmation if no SMS was received.


Country Coverage Reference

Country Code Notes
United States us Widest service support
United Kingdom gb Good EU service support
India in Required for IN-only apps
Germany de Strong EU banking support
Canada ca US-adjacent coverage
Brazil br Large inventory

NumberOTP covers 150+ countries →


Comparing Virtual Number APIs

Provider API Docs Non-VoIP Auto-Refund Free Credits Per-Use Pricing
NumberOTP Full REST Yes Yes $0.10 Yes
Twilio Full REST Yes No $15 trial Monthly rental
5sim Basic Some No No Yes
TextVerified Yes Yes No Limited Yes

For verification use cases (one-time numbers, OTP testing): NumberOTP is the cleaner option — no monthly number rental, pay per use, auto-refund on failure.

For production inbound SMS infrastructure (permanent numbers, high volume): Twilio or Plivo are better suited.


TypeScript SDK Example

class SMSVerificationService {
  private baseUrl = 'https://numberotp.com/api';

  constructor(private apiKey: string) {}

  async getNumber(country = 'us', service = 'any'): Promise<{ id: string; number: string }> {
    const res = await fetch(
      `${this.baseUrl}/numbers?country=${country}&service=${service}`,
      { headers: { 'X-API-Key': this.apiKey } }
    );
    if (!res.ok) throw new Error(`API error: ${res.status}`);
    return res.json();
  }

  async waitForOTP(numberId: string, timeoutMs = 120000): Promise<string | null> {
    const deadline = Date.now() + timeoutMs;
    let interval = 3000;

    while (Date.now() < deadline) {
      await new Promise(r => setTimeout(r, interval));

      const res = await fetch(`${this.baseUrl}/sms/${numberId}`, {
        headers: { 'X-API-Key': this.apiKey }
      });
      const data = await res.json();

      if (data.messages?.length > 0) {
        const otp = data.messages[0].body.match(/\b(\d{4,8})\b/)?.[1];
        return otp ?? null;
      }

      interval = Math.min(interval * 1.5, 15000);
    }

    // Trigger refund on timeout
    await fetch(`${this.baseUrl}/numbers/${numberId}`, {
      method: 'DELETE',
      headers: { 'X-API-Key': this.apiKey }
    });
    return null;
  }
}

// Usage
const sms = new SMSVerificationService(process.env.NUMBEROTP_API_KEY!);
const { id, number } = await sms.getNumber('us', 'google');
console.log(`Use: ${number}`);
const otp = await sms.waitForOTP(id);
console.log(`OTP: ${otp}`);
Enter fullscreen mode Exit fullscreen mode

Frequently Asked Questions

What is a virtual phone number API?

A virtual phone number API lets you programmatically request, manage, and receive SMS to temporary or permanent phone numbers without physical SIM cards. Services like NumberOTP expose REST endpoints that return real carrier numbers you can use for any SMS verification or inbound SMS workflow.

How do I get a non-VoIP number for Google verification via API?

Use a service that specifically provides SIM-backed non-VoIP numbers. NumberOTP guarantees this — VoIP numbers from standard telephony providers will fail Google's verification check.

What is the difference between a virtual number API and Twilio?

Twilio is a full-scale communications platform with long-term number rentals, voice, SMS, and many features. Virtual number APIs like NumberOTP are optimized for one-time verification use cases — lower cost per verification, no monthly number fees, and auto-refund if no SMS arrives.

Is there a free virtual phone number API?

Most services offer trial credits. NumberOTP gives $0.10 in free credits on signup. Twilio gives $15 in trial credits. There is no sustainably free unlimited API, but free-tier credits are sufficient for development testing.

Can virtual phone numbers receive calls as well as SMS?

It depends on the provider. Most SMS verification APIs (including NumberOTP) focus on inbound SMS only. For two-way voice and SMS, providers like Twilio and Plivo are more appropriate.


Conclusion

Virtual number APIs have matured significantly. For developers building anything that touches SMS verification — integration tests, automation pipelines, multi-account tools, or just testing your own OTP flow — the NumberOTP API is the fastest path to a working implementation.

Clean REST interface, real SIM-backed numbers, auto-refund on failure, and $0.10 free to try. Get your API key →

Top comments (0)