Rent Virtual Phone Numbers Online – SMS Verification Service

← Back to Home

Reseller API

Rent virtual numbers, receive SMS, and get real-time webhooks — all over a simple REST API. Resell our 100+ country catalog through your own app.

API Features

Instant Rentals

Numbers provisioned in under a second.

100+ Countries

Full catalog across multiple servers.

Signed Webhooks

HMAC-SHA256 signatures on every event.

Real-time Events

sms.received, rental.expired, rental.cancelled.

Quickstart

  1. Sign in and visit API Keys to generate a key.
  2. Top up your wallet — every API rental charges your account balance.
  3. Send requests to https://rentalnumbers.com/functions/<endpoint> with header Authorization: Bearer <your_key>.
  4. Optionally register a webhook to receive real-time SMS events.
// Node.js — full reseller flow
// All endpoints go to /resellerApi with an "endpoint" field in the body.
const API = 'https://rentalnumbers.com/functions/resellerApi';
const KEY = process.env.RENTALNUMBERS_API_KEY;
const headers = { Authorization: `Bearer ${KEY}`, 'Content-Type': 'application/json' };

const call = (endpoint, params = {}) =>
  fetch(API, { method: 'POST', headers, body: JSON.stringify({ endpoint, ...params }) })
    .then(r => r.json());

// 1. Check balance
const bal = await call('getBalance');
console.log('Balance:', bal.balance);

// 2. Rent a US WhatsApp number
const rental = await call('rentNumber', { country: 'United States', service: 'WhatsApp', server: 1 });
console.log('Number:', rental.phone_number);

// 3. Poll for SMS (or use webhooks — see below)
let sms = null;
for (let i = 0; i < 30 && !sms; i++) {
  await new Promise(r => setTimeout(r, 5000));
  const res = await call('getSMS', { rental_id: rental.rental_id });
  if (res.sms_messages?.length) sms = res.sms_messages[0];
}
console.log('SMS:', sms);

Authentication

All endpoints (except apiCreateKey / apiListKeys / apiRevokeKey which use your session) authenticate via a Bearer token in the Authorization header.

Authorization: Bearer rk_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxx

Keys are stored as SHA-256 hashes — we cannot recover them. Lost a key? Revoke it and create a new one.

Endpoints

Base URL: https://rentalnumbers.com/functions

Server-14 is available for Walmart in Canada. Use server: 14 with checkPrice or rentNumber.

POSThttps://rentalnumbers.com/functions/apiCreateKey

Generate a new API key. Returns the key once — store it securely.

Auth: Session (logged in)
Request body
{
  "name": "Production server"
}
Response
{
  "success": true,
  "api_key": "rk_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxx",
  "id": "abc123",
  "key_prefix": "rk_live_xxxxxxxx"
}
GEThttps://rentalnumbers.com/functions/apiGetBalance

Returns the reseller wallet balance in USD.

Auth: Bearer <api_key>
Response
{
  "success": true,
  "balance": 42.5,
  "currency": "USD",
  "email": "reseller@example.com"
}
POSThttps://rentalnumbers.com/functions/resellerApi

Check live price + availability. Set endpoint="checkPrice".

Auth: Bearer <api_key>
Request body
{
  "endpoint": "checkPrice",
  "country": "United States",
  "service": "WhatsApp",
  "server": 1
}
Response
{
  "success": true,
  "country": "United States",
  "service": "WhatsApp",
  "server": 1,
  "price": 0.45,
  "stock": 124
}
POSThttps://rentalnumbers.com/functions/resellerApi

Rent a virtual number. Set endpoint="rentNumber". Charges your wallet at the displayed price.

Auth: Bearer <api_key>
Request body
{
  "endpoint": "rentNumber",
  "country": "United States",
  "service": "WhatsApp",
  "server": 1
}
Response
{
  "success": true,
  "rental_id": "rent_abc123",
  "phone_number": "+15551234567",
  "service": "WhatsApp",
  "country": "United States",
  "server": 1,
  "expires_at": "2026-05-01T14:00:00Z",
  "price": 0.45
}
POSThttps://rentalnumbers.com/functions/resellerApi

Fetch SMS messages received on a rented number. Set endpoint="getSMS". Poll every 5–10 seconds, or use webhooks.

Auth: Bearer <api_key>
Request body
{
  "endpoint": "getSMS",
  "rental_id": "rent_abc123"
}
Response
{
  "success": true,
  "rental_id": "rent_abc123",
  "phone_number": "+15551234567",
  "status": "active",
  "sms_messages": [
    {
      "from": "WhatsApp",
      "text": "Your code is 123-456",
      "received_at": "2026-05-01T13:31:00Z"
    }
  ]
}
POSThttps://rentalnumbers.com/functions/resellerApi

Cancel an active rental. Set endpoint="cancelRental". Refunds wallet if eligible (no SMS received yet).

Auth: Bearer <api_key>
Request body
{
  "endpoint": "cancelRental",
  "rental_id": "rent_abc123"
}
Response
{
  "success": true,
  "rental_id": "rent_abc123",
  "status": "cancelled",
  "refunded": true,
  "refund_amount": 0.45
}
POSThttps://rentalnumbers.com/functions/resellerApi

Register an HTTPS webhook URL. Set endpoint="setWebhook". Returns a signing secret used to verify HMAC-SHA256 signatures.

Auth: Bearer <api_key>
Request body
{
  "endpoint": "setWebhook",
  "webhook_url": "https://your-server.com/rentalnumbers-webhook",
  "events": [
    "sms.received",
    "rental.expired"
  ]
}
Response
{
  "success": true,
  "webhook_url": "https://...",
  "events": [
    "sms.received"
  ],
  "secret": "whsec_xxxxxxxxxxxx"
}
POSThttps://rentalnumbers.com/functions/resellerApi

List all valid country names. Set endpoint="listCountries".

Auth: Bearer <api_key>
Request body
{
  "endpoint": "listCountries"
}
Response
{
  "success": true,
  "count": 100,
  "countries": [
    "Argentina",
    "Australia",
    "Brazil",
    "Canada",
    "..."
  ]
}
POSThttps://rentalnumbers.com/functions/resellerApi

List the popular service names accepted by the API. Set endpoint="listServices". Names are case-insensitive.

Auth: Bearer <api_key>
Request body
{
  "endpoint": "listServices"
}
Response
{
  "success": true,
  "count": 90,
  "services": [
    "WhatsApp",
    "Telegram",
    "Google",
    "Facebook",
    "..."
  ]
}

Country & service names

checkPrice and rentNumber accept human-readable names for country and service — no need to memorize any codes. Just use the full name as shown by listServices.

  • Use listCountries to fetch all valid country names per server.
  • Use listServices to fetch the popular service catalog.
  • Names are case-insensitive (e.g. "whatsapp" = "WhatsApp").
  • Use full country names: "United States" (not "USA"), "United Kingdom" (not "UK").
  • If a service isn't available on a given server/country, checkPrice returns available: 0 — try another server.

⚠️ Always use full service names

Always pass the full human-readable service name (e.g. "Walmart", "WhatsApp"). Short codes or abbreviations like "wr" or "wa" are not accepted and will result in "No numbers available" errors. When in doubt, call listServices first to get the exact accepted strings.

Recommended flow

const API = 'https://rentalnumbers.com/functions/resellerApi';

const call = (endpoint, params = {}) =>
  fetch(API, { method: 'POST', headers, body: JSON.stringify({ endpoint, ...params }) })
    .then(r => r.json());

// 1. Fetch valid countries for the server you want
const { countries } = await call('listCountries', { server: 3 });

// 2. Fetch service catalog
const { services } = await call('listServices', { server: 3, country: 'United Kingdom' });

// 3. Confirm price + availability before renting
const price = await call('checkPrice', { country: 'United Kingdom', service: 'WhatsApp', server: 3 });
// → { success: true, price: 0.45, available: 124 }

Webhooks

Register your HTTPS endpoint via apiSetWebhook. We'll POST signed JSON payloads when these events fire:

  • sms.received — a new SMS landed on a rented number
  • rental.expired — a rental's time window ended
  • rental.cancelled — a rental was cancelled (refunded if eligible)

Headers we send

X-RentalNumbers-Event: sms.received
X-RentalNumbers-Signature: sha256=<hex>
Content-Type: application/json

Verifying signatures

Compute HMAC-SHA256 of the raw request body using your signing secret, then compare against the signature header.

// Node.js — verify incoming webhook
const crypto = require('crypto');
const SECRET = process.env.RENTALNUMBERS_WEBHOOK_SECRET; // whsec_...

app.post('/rentalnumbers-webhook', express.raw({ type: 'application/json' }), (req, res) => {
  const sig = req.header('X-RentalNumbers-Signature') || '';
  const expected = 'sha256=' + crypto.createHmac('sha256', SECRET)
    .update(req.body).digest('hex');
  if (sig !== expected) return res.status(401).send('bad signature');

  const event = JSON.parse(req.body.toString());
  // event.event = "sms.received" | "rental.expired" | "rental.cancelled"
  // event.data = { rental_id, phone_number, sms?, ... }
  console.log('Webhook:', event.event, event.data);
  res.sendStatus(200);
});

SMS delivery latency

How fast you receive an SMS depends on two things: how the underlying network delivers it to us, and how you fetch it from us.

How we receive SMS

ServerLatency
Server-1~1–3 s
Server-2~1–3 s
Server-3~1–3 s
Server-4~1–3 s
Server-5~1–3 s
Server-6~1–3 s

You can call getSMS as often as you want (up to your key rate limit), or register a webhook for push delivery.

Webhooks vs polling — pick one

Webhooks (recommended)

  • Fastest: ~1–2 s from delivery to your endpoint
  • Zero polling load on your server
  • Won't burn your rate limit
  • Signed with HMAC-SHA256

Polling getSMS

  • Poll every 10–15 s for a good balance
  • Do not poll faster than 5 s — wasteful, hits rate limit
  • Default rate limit: 60 req/min per key
  • Use exponential backoff once you receive the SMS

Bottom line: if you're building production, register a webhook via setWebhook for the lowest latency. Polling is fine for quick scripts and prototypes.

Error responses

StatusMeaning
400Bad request — missing/invalid parameters
401Missing, invalid, or revoked API key
403Resource doesn't belong to your account
404Resource not found
429Rate limit exceeded (default: 60 req/min)
500Server error — retry with backoff

All error responses follow the shape { "error": "message" }.

"Did you mean?" suggestions

When you pass a service or country value that doesn't match any known name, the API attempts a fuzzy match and returns a suggestion so you can self-correct:

// You sent: { endpoint: "checkPrice", service: "wr", server: 1, country: "United States" }
// Response (400):
{
  "error": "Service 'wr' not found on Server-1.",
  "suggestion": "Did you mean 'Walmart'? Use listServices to fetch all accepted names."
}

Ready to integrate?

Generate your first key and start reselling our numbers in minutes.

Cookie & Data Privacy

We use cookies and similar technologies to enhance your experience, analyze traffic, and serve relevant ads. By clicking "Accept", you consent to the use of these technologies as described in our Privacy Policy.