Developers
Headless SMS Number API
A real US number, every SMS sent to it, one HTTP call. No account, no sign-up, no API key: the payment is the credential. Settled in USDC on Stellar with the x402 protocol.
Read this first
- No accounts, no recovery. A successful purchase returns a secret token exactly once. Lose it and the number is gone; we only store its hash and cannot reissue it.
- No refunds. Extensions must be bought before
expires_at. At expiry the number is deleted at the carrier and every message is purged. Nothing comes back. - We sell numbers, not services. Every SMS from any sender is delivered for the whole duration. Whether a third party accepts a number is up to them.
- Receive-only. No sending, no voice. Lawful use only (see Terms).
Plans
20m
$2.00
20 minutes · all SMS, any sender
POST /api/v1/numbers/20m
1d
$3.00
24 hours · all SMS, any sender
POST /api/v1/numbers/1d
7d
$5.00
7 days · all SMS, any sender
POST /api/v1/numbers/7d
Any plan can also be bought as an extension: its duration is added to the current expires_at. Prices are in USD and settled as USDC. GET /api/v1/plans returns this table and the payment network.
Flow
# 1. What is in stock (free)
curl https://receivesmsonline.us/api/v1/stock
# 2. Ask for a number → 402 Payment Required with a PAYMENT-REQUIRED header
curl -i -X POST "https://receivesmsonline.us/api/v1/numbers/20m?area_code=415"
# 3. Your x402 client signs a USDC payment on Stellar and retries with PAYMENT-SIGNATURE
# → 201 { id, number, token, expires_at }
# (see the Node example: the client library does steps 2 to 3 for you)
# 4. Wait for the code (long-poll up to 30 s)
curl -H "Authorization: Bearer rso_…" "https://receivesmsonline.us/api/v1/numbers/num_9f2c1a7e/messages?wait=30"
# 5. Need more time? Add 24 h to expires_at (paid, same x402 handshake)
curl -X POST -H "Authorization: Bearer rso_…" https://receivesmsonline.us/api/v1/numbers/num_9f2c1a7e/extend/1dimport { wrapFetchWithPayment } from "@x402/fetch";
import { x402Client } from "@x402/core/client";
import { ExactStellarScheme } from "@x402/stellar/exact/client";
import { createEd25519Signer } from "@x402/stellar";
// npm i @x402/fetch @x402/core @x402/stellar
// Any funded Stellar account holding USDC. Testnet: stellar:testnet, mainnet: stellar:pubnet.
const network = "stellar:pubnet";
const signer = createEd25519Signer(process.env.STELLAR_SECRET!, network);
// The client caps spend at $1 per payment by default; raise it to cover the plan you buy.
const client = new x402Client()
.register(network, new ExactStellarScheme(signer))
.setSpendControls({ maxAmountPerPayment: "$5.00" });
const fetchPaid = wrapFetchWithPayment(fetch, client);
// One call: 402 → sign → retry → 201. Keep the token: it is the only credential.
const r = await fetchPaid("https://receivesmsonline.us/api/v1/numbers/20m?area_code=415", { method: "POST" });
const { id, number, token, expires_at } = await r.json();
// Stream every SMS as it arrives (Server-Sent Events over fetch).
const es = await fetch(`https://receivesmsonline.us/api/v1/numbers/${id}/stream`, { headers: { Authorization: `Bearer ${token}` } });
for await (const chunk of es.body!.pipeThrough(new TextDecoderStream())) process.stdout.write(chunk);Endpoints
| Method · path | Auth | Returns |
|---|---|---|
GET /plans | none | plans, prices, payment network |
GET /stock | none | available numbers per area code |
POST /numbers/{20m|1d|7d}?area_code=415&webhook_url=https://… | x402 payment | 201 { id, number, plan, token, created_at, expires_at } · 409 out_of_stock (not charged) |
GET /numbers/{id} | Bearer token | status, expires_at, message_count |
GET /numbers/{id}/messages?since=<msg id | ISO>&wait=0–30 | Bearer token | messages oldest-first; long-poll with wait |
GET /numbers/{id}/stream | Bearer token | SSE: message, extended, expired; heartbeat every 15 s |
POST /numbers/{id}/extend/{20m|1d|7d} | Bearer + x402 | 200 { id, plan_added, expires_at } · 401/410 are not charged |
PUT /numbers/{id}/webhook | Bearer token | { url } or { url: null } |
GET /numbers/{id}/messages/{msgId}/media/{n} | Bearer token | MMS attachment, proxied |
DELETE /numbers/{id} | Bearer token | 204, immediate teardown, no refund |
Base URL https://receivesmsonline.us/api/v1. JSON everywhere, ISO 8601 UTC timestamps, CORS open to all origins. Free endpoints: 60 requests/min per IP. Long-poll: 5 concurrent per token. SSE: 2 per token. A token answers 410 Gone forever once its number expired.
Messages
code is a best-effort extraction of a 4–8 digit code (hyphenated codes are joined). It is generic (no per-service parsing) and null when nothing looks like a code. MMS attachments appear as media URLs on this API.
{
"messages": [
{
"id": "msg_01JB…",
"from": "+18005551234",
"text": "Your code is 482-913",
"code": "482913",
"received_at": "2026-10-23T05:06:12Z"
}
]
}Webhooks
Pass webhook_url at purchase or set it later. Each SMS is POSTed once, with up to 3 retries (5 s timeout) while the number is live. Verify the signature with sha256(token) as the HMAC key; we never store the raw token either. https and public hosts only.
POST https://your.app/hook
X-RSO-Signature: sha256=<HMAC-SHA256(body, key = sha256(token))>
{ "id": "num_9f2c1a7e", "number": "+14155550137", "message": { …same object as above… } }Payments
- Protocol x402, scheme
exact, asset USDC, networkstellar:pubnet(testnet during rollout; checkGET /plans). Facilitator: Built on Stellar by OpenZeppelin. - Settlement happens only after we successfully allocate. Out of stock, bad token, expired number → 4xx and no USDC moves.
- If you paid but lost the response, retry with the same
PAYMENT-SIGNATUREwithin 30 minutes: you get the identical body, including the token, and no second number is allocated. - Every settled payment is recorded with its Stellar transaction hash; after teardown nothing links a payment to a number or a message.
Errors
{ "error": { "code": "out_of_stock", "message": "No numbers available in area code 415." } }Codes: invalid_request 400 · payment_required 402 · invalid_token 401 · not_found 404 · out_of_stock 409 · expired 410 · rate_limited / too_many_streams 429 · payments_unconfigured 503.
Privacy
Message bodies and codes are encrypted at rest and hard-deleted the minute the number expires (or when you call DELETE). They never appear in our logs. Numbers are single-use: once yours expires it is deleted at the carrier and never resold. Read the Privacy Policy.
Prefer a number you keep? The monthly plan is $3.99 per month with an inbox.