Fetch SMSAPI v1

Introduction

The Fetch SMS API lets you rent real US non-VOIP phone numbers and receive SMS verification codes programmatically. It is a JSON REST API over HTTPS.

Conventions
Base URLstringhttps://api.fetchsms.com/v1
MoneyintegerEvery amount is in integer US cents (7000 = $70.00).
TimestampsstringISO-8601 in UTC, e.g. 2026-06-17T22:14:05Z.
IDsstringResource ids are UUIDs; services also have a short numeric id.

The fastest path: list services, create a verification, then poll it until the code arrives.

# 1. Pick a service id
curl https://api.fetchsms.com/v1/services

# 2. Rent a number for it
curl https://api.fetchsms.com/v1/verifications \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"service": 4}'

# 3. Poll until "code" is populated (most codes arrive in seconds)
curl https://api.fetchsms.com/v1/verifications/<id> \
  -H "Authorization: Bearer YOUR_API_KEY"

Authentication

Authenticate programmatic verification and rental requests with an API key in the Authorization header as a bearer token. Create and rotate keys on the API page of your dashboard. Keys are shown only once, so store them securely.

Authorization: Bearer YOUR_API_KEY

Dashboard, account, wallet, support, admin, and API-key management routes require a dashboard session token and reject API keys. The public catalog endpoints (GET /v1/services and GET /v1/services/quote) do not require a key.

Errors & rate limits

Errors use standard HTTP status codes and a JSON body with a single field:

{ "detail": "Telegram is out of stock for short-term verifications" }
Status codes
200 / 201successRequest succeeded (201 on resource creation).
400bad requestMalformed input or a business-rule violation.
401unauthorizedMissing, invalid, or revoked credential.
402payment requiredInsufficient wallet balance for the purchase.
403forbiddenCredential is valid but not allowed for the endpoint.
404not foundUnknown service, or a resource you do not own.
409conflictOut of stock, or code already received (cannot cancel).
422unprocessableInvalid duration or parameter value.
429rate limitedToo many requests — slow down and retry.

Rate limit: 100 requests/second per API key. Poll for codes at a sane interval (every 2–5 seconds is plenty).

Services

Fetch SMS has two separate products — short-term and long-term are priced and sold independently:

Products
Short-term verificationper serviceA number for one code, priced per service (WhatsApp, Telegram, …). Each has its own numeric id — see Short-term services.
Long-term rentalsingle productOne flat-priced number that works for any service — the "unlimited-services" product (id 1). There is no per-service long-term option.

List the catalog with GET /v1/services. Anywhere the API takes a service, pass the stable numeric id. Slugs like telegram are also accepted for compatibility.

GET/v1/services

Returns an array of services ordered for display. No authentication required.

Response — each item
idintegerStable numeric public id (1…N) — the recommended reference for every endpoint.
slugstringCompatibility reference, e.g. "telegram".
namestringDisplay name, e.g. "Telegram".
price_centsintegerShort-term verification price (also the long-term base daily rate).
long_pricesobjectLong-term price map {"1":300,…} in cents — empty {} except on the Unlimited service.
short_availableintegerNumbers available right now for verifications.
long_availableintegerPristine numbers available right now for Unlimited rentals.
curl https://api.fetchsms.com/v1/services
[
  {
    "id": 2,
    "slug": "whatsapp",
    "name": "WhatsApp",
    "price_cents": 140,
    "long_prices": {},
    "short_available": 200,
    "long_available": 100
  }
]

Long-term rentals are the single Unlimited product, so only it carries a populated long_prices map — every short-term service returns {}. See the full id ↔ service mapping under Short-term services.

GET/v1/services/area-codes

The US area codes available in the pool right now — the options when renting with a custom area code (+$0.10). No authentication required.

Query
modestring"short" (default) or "long". Long-term lists only pristine, never-used numbers.
serviceinteger or stringOptional service reference — returns the codes available for that specific short-term service.
curl "https://api.fetchsms.com/v1/services/area-codes?mode=short&service=2"
["212", "332", "415", "628", "917"]

Pricing & quotes

Short-term verifications are priced per service — each costs that service's verification price (price_cents).

Long-term rentals are a single flat-priced product: one dedicated number that works for any service, billed per term. The price does not depend on which services you use the number for.

Long-term rental price · one number, any service
1 day$3.00
7 days$6.00
30 days$12.00
90 days$25.00
365 days$90.00

A custom area code adds a flat $0.10 surcharge to either product.

GET/v1/services/quote

Compute the exact price before you buy. No authentication required.

Parameters
serviceinteger or string · requiredStable numeric id recommended; slug accepted for compatibility. Use id 1 for long mode.
modestring · required"short" for a verification, "long" for a rental.
daysintegerTerm length for long mode: 1, 7, 30, 90, or 365.
custom_area_codebooleantrue to include the $0.10 area-code surcharge (default false).
curl "https://api.fetchsms.com/v1/services/quote?service=4&mode=short&custom_area_code=true"
{
  "service": "telegram",
  "mode": "short",
  "days": null,
  "base_daily_cents": 70,
  "discount_pct": 0,
  "per_day_cents": null,
  "surcharge_cents": 10,
  "total_cents": 80
}
curl "https://api.fetchsms.com/v1/services/quote?service=1&mode=long&days=30"
{
  "service": "unlimited-services",
  "mode": "long",
  "days": 30,
  "base_daily_cents": 300,
  "discount_pct": 87,
  "per_day_cents": 40,
  "surcharge_cents": 0,
  "total_cents": 1200
}

Verifications (short-term)

A verification reserves a number for a single code inside a fixed 15-minute window. The wallet is debited up front; if the window closes (or you cancel) before any code arrives, the charge is automatically refunded — you are only charged on receipt.

Verifications are per service: the code is released only when the inbound SMS matches the service you purchased — a code for a different service is not shown and the verification keeps waiting. The response and webhook carry the code only, never the message body.

POST/v1/verifications
Body
serviceinteger or string · requiredStable numeric id from GET /v1/services is recommended; slug accepted for compatibility.
area_codestringOptional 3-digit US area code, e.g. "332" (+$0.10).
curl https://api.fetchsms.com/v1/verifications \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"service": 4, "area_code": "332"}'
{
  "id": "9f3e1c2a-…",
  "ref": "v_8R3p2K",
  "service": "telegram",
  "service_name": "Telegram",
  "number": "(332) 555-0184",
  "code": null,
  "status": "waiting",
  "cost_cents": 70,
  "created_at": "2026-06-17T22:14:05Z",
  "expires_at": "2026-06-17T22:29:05Z"
}

status is one of waiting, received, expired, cancelled. Errors: 402 insufficient balance, 404 unknown service, 409 out of stock.

GET/v1/verifications/{id}

Fetch one verification. Poll this until code is non-null and status is received.

curl https://api.fetchsms.com/v1/verifications/9f3e1c2a-… \
  -H "Authorization: Bearer YOUR_API_KEY"
{ "id": "9f3e1c2a-…", "status": "received", "code": "482910", … }
GET/v1/verifications?tab=active

List your verifications. tab is active (default) or history.

curl "https://api.fetchsms.com/v1/verifications?tab=active" \
  -H "Authorization: Bearer YOUR_API_KEY"
POST/v1/verifications/{id}/cancel

Cancel a waiting verification and refund the charge. Returns 409 once a code has arrived.

curl -X POST https://api.fetchsms.com/v1/verifications/9f3e1c2a-…/cancel \
  -H "Authorization: Bearer YOUR_API_KEY"

Rentals (long-term)

A rental gives you an exclusive number for 1–365 days that works for any service and receives unlimited codes for the whole term — a single flat-priced product (priced per term, not per service). A rental that ends without ever receiving a code is refunded.

POST/v1/rentals
Body
serviceinteger or string · requiredLong-term product id 1. The slug "unlimited-services" is accepted for compatibility.
daysinteger · requiredTerm: 1, 7, 30, 90, or 365.
area_codestringOptional 3-digit US area code (+$0.10).
curl https://api.fetchsms.com/v1/rentals \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"service": 1, "days": 30}'
{
  "id": "1a2b3c4d-…",
  "ref": "r_K9m2Lp",
  "service": "unlimited-services",
  "service_name": "Unlimited Services",
  "number": "(415) 555-0142",
  "duration_days": 30,
  "last_code": null,
  "status": "waiting",
  "cost_cents": 1200,
  "created_at": "2026-06-17T22:14:05Z",
  "expires_at": "2026-07-17T22:14:05Z"
}

Errors: 402 insufficient balance, 404 unknown service, 409 out of stock, 422 unsupported duration.

GET/v1/rentals/{id}

Fetch one rental. last_code holds the most recent code received on the number.

curl https://api.fetchsms.com/v1/rentals/1a2b3c4d-… \
  -H "Authorization: Bearer YOUR_API_KEY"
GET/v1/rentals/{id}/messages

Every SMS received on the rental number, newest first.

curl https://api.fetchsms.com/v1/rentals/1a2b3c4d-…/messages \
  -H "Authorization: Bearer YOUR_API_KEY"
[
  {
    "id": "…",
    "sender": "WhatsApp",
    "body": "Your WhatsApp code: 821-193",
    "code": "821-193",
    "received_at": "2026-06-17T22:31:10Z"
  }
]
GET/v1/rentals?tab=active

List your rentals. tab is active (default) or history.

curl "https://api.fetchsms.com/v1/rentals?tab=active" \
  -H "Authorization: Bearer YOUR_API_KEY"
POST/v1/rentals/{id}/cancel

Cancel a rental that has not received a code yet (refunded). Otherwise returns 409.

curl -X POST https://api.fetchsms.com/v1/rentals/1a2b3c4d-…/cancel \
  -H "Authorization: Bearer YOUR_API_KEY"

Wallet

Purchases are paid from your prepaid wallet balance. API-key requests can spend from that balance through verification and rental purchases, but wallet balance, deposits, and ledger history are dashboard-only and do not accept API keys.

Webhooks

Instead of polling, register an endpoint to receive events the moment they happen. Add and manage endpoints on the API page. Each delivery is a POST with a JSON body.

Events
sms.receivedeventA code/SMS arrived on a verification or rental number.
rental.expiredeventA long-term rental reached the end of its term.

Delivery headers:

Parameters
X-FetchSMS-EventstringThe event type, e.g. "sms.received".
X-FetchSMS-SignaturestringHMAC-SHA256 hex of the raw body, keyed by your endpoint secret.

Example sms.received payload:

{
  "event": "sms.received",
  "data": {
    "verification_id": "9f3e1c2a-…",
    "ref": "v_8R3p2K",
    "number": "(332) 555-0184",
    "sender": "Telegram",
    "code": "482910",
    "detected_service": "Telegram",
    "received_at": "2026-06-17T22:15:30Z"
  },
  "created_at": "2026-06-17T22:15:30Z"
}

Short-term verification events carry the code only — never the message body. A long-term rental event carries rental_id (instead of verification_id) and includes the full body. A rental.expired payload carries rental_id, ref, and number.

Verify the signature before trusting a delivery:

import crypto from 'node:crypto'

function verify(rawBody, signature, endpointSecret) {
  const expected = crypto
    .createHmac('sha256', endpointSecret)
    .update(rawBody)
    .digest('hex')
  return crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(signature))
}

Short-term services

Every short-term verification service with its stable numeric id, slug, and price — pass the id to POST /v1/verifications. Live per-service stock is returned by GET /v1/services (the short_available field). The long-term unlimited-services rental product is not a short-term service and is excluded here (see Pricing).

IDSlugServiceVerification price
Loading catalog…