Temp Number API - Phone Number, SMS & OTP
A clean, production-ready REST API to provision virtual phone numbers, receive SMS in real time, and automate OTP verification - built for verification flows, automated onboarding, and any product that needs an inbound SMS or phone number API at scale.
https://api.temp-number.com/v1
Introduction
The Temp Number API is organised around predictable resources, uses standard HTTP verbs, and returns JSON for every response. A single bearer token authorises read and write access to your account only - there is no cross-account access.
Acceptable Use
The API is built for developers: verification and OTP flows, automated onboarding, QA and system testing, and any product that needs inbound SMS or phone numbers at scale.
- Use it for legitimate verification, development and testing only.
- No scams, spam, fraud, or deception. Numbers used for scams or other unusual, abusive activity get the account banned immediately and without notice, associated numbers cancelled, and no refund is due.
- Not for regulated or identity-bound accounts. Our shared, temporary numbers do not support SMS verification for banking, payment, cryptocurrency, government, or other services that verify your legal identity (KYC/AML) — use your own personal mobile number for those.
Authentication
Every request must carry a personal access token in the standard Authorization header:
Authorization: Bearer YOUR_API_TOKEN
- Generate your token from your dashboard under API Access. It is shown in full exactly once at creation - store it safely.
- Tokens are scoped with the
api:accessability and must be sent over HTTPS. Requests without a valid bearer token are rejected with401. - Use a dedicated token per integration so you can revoke one without breaking the others.
Base URL & Versioning
All endpoints live under the permanent /v1 prefix:
https://api.temp-number.com/v1
Additive changes (new fields, new endpoints, new optional parameters) ship without a version bump. Any breaking change ships under a new prefix (/v2) - your integration is never silently moved.
Requests & Responses
- All requests and responses are
application/json. SendAccept: application/jsonto opt into structured error bodies. - Successful responses follow
{ "success": true, "data": …, "meta": {…} }. - Errors follow
{ "success": false, "message": "…" }with the matching HTTP status. - Times are ISO 8601 in UTC. Money values are in USD with two decimals - and are always the user-facing price you pay.
Rate Limits
The API runs under a per-token limit of 60 requests per minute. High-cost endpoints (buy, renew, cancel) have an additional per-action limit on top. Every response carries:
X-RateLimit-Limit- your ceiling for the current window.X-RateLimit-Remaining- calls left in the window.Retry-After- seconds to wait when the response is429.
429. Retry-After is the floor, not the ceiling.Idempotency
State-changing endpoints (POST /numbers/buy, /renew, /cancel) accept an Idempotency-Key header. Send a unique UUID per logical request; retries with the same key are safely de-duplicated within a 24-hour window - even if your network drops mid-request, retrying never charges you twice.
Errors
Errors use standard HTTP status codes with a JSON body:
{
"success": false,
"message": "Insufficient funds to complete this purchase."
}
AI Agents & LLMs
Building with an AI coding assistant (Claude, ChatGPT, Cursor, Copilot)? Hand it the context below and it can integrate this API correctly in one shot - auth, idempotency, rate-limit handling and all.
Ready-to-paste prompt
You are integrating the Temp Number REST API. Read the full, machine-readable reference before writing any code:
- API reference (llms.txt): https://temp-number.com/llms.txt
- OpenAPI spec: https://api.temp-number.com/api.json
- Base URL: https://api.temp-number.com/v1
Rules: authenticate every request with `Authorization: Bearer <YOUR_API_TOKEN>` (created in the dashboard → API Access); send and accept JSON over HTTPS; add a unique `Idempotency-Key` (UUID) header on every POST; on HTTP 429, back off using the `Retry-After` header. All prices are final USD.
Task: <describe what you want to build - e.g. "buy a US number, poll for the OTP, then cancel it">.
https://temp-number.com/llms.txt for an always-current, machine-readable summary of every endpoint, or the OpenAPI spec for a typed contract. Both update automatically with the API.Account
Read your wallet balance and settlement currency.
Get account balance
Returns the authenticated account's available wallet balance and currency. Use it before a purchase to confirm sufficient funds.
Example request
curl --request GET "https://api.temp-number.com/v1/account" \
--header "Accept: application/json" \
--header "Authorization: Bearer $YOUR_API_TOKEN"
Example response
{
"success": true,
"balance": 124.50,
"currency": "USD"
}
Discovery & Pricing
Browse live markets, the exact price you pay per duration, and real-time stock.
List pricing for all countries
The complete live pricing catalog, grouped by country. The `price` field is the final user-facing rate in USD - exactly what your wallet is debited. Upstream provider cost is never exposed.
Example request
curl --request GET "https://api.temp-number.com/v1/pricing" \
--header "Accept: application/json" \
--header "Authorization: Bearer $YOUR_API_TOKEN"
Example response
{
"success": true,
"data": [
{
"country_code": "US",
"country_name": "United States",
"packages": [
{
"number_type": "voip",
"duration": "oneMonth",
"duration_label": "1 Month",
"price": 4.99,
"original_price": 5.99,
"updated_at": null
},
{
"number_type": "voip",
"duration": "threeMonths",
"duration_label": "3 Months",
"price": 12.99,
"original_price": null,
"updated_at": null
},
{
"number_type": "voip",
"duration": "sixMonths",
"duration_label": "6 Months",
"price": 22.99,
"original_price": null,
"updated_at": null
}
]
}
],
"meta": { "count": 1 }
}
Get pricing for one country
Live pricing for a single country. Returns `404` when the country code is valid but has no active route right now - treat it as a transient "out of stock" signal.
Parameters
| Name | In | Required | Description |
|---|---|---|---|
countryCode |
path | Required | ISO 3166-1 alpha-2 country code, e.g. US, GB, CA. |
Example request
curl --request GET "https://api.temp-number.com/v1/pricing/GB" \
--header "Accept: application/json" \
--header "Authorization: Bearer $YOUR_API_TOKEN"
Example response
{
"success": true,
"data": {
"country_code": "GB",
"country_name": "United Kingdom",
"packages": [
{
"number_type": "voip",
"duration": "oneMonth",
"duration_label": "1 Month",
"price": 5.49,
"original_price": null,
"updated_at": null
}
]
}
}
Check inventory availability
Real-time stock for a country + duration so you can preflight a purchase. A green check is a strong signal but the purchase itself is the authoritative check.
Parameters
| Name | In | Required | Description |
|---|---|---|---|
country_code |
query | Required | ISO 3166-1 alpha-2 country code for the market. |
duration |
query | Optional | Package duration key (see /pricing/{country}). Omit for the route default. |
number_type |
query | Optional | Inventory type: voip or non_voip. |
Example request
curl --request GET "https://api.temp-number.com/v1/inventory?country_code=US&duration=oneMonth" \
--header "Accept: application/json" \
--header "Authorization: Bearer $YOUR_API_TOKEN"
Example response
{
"success": true,
"data": {
"country_code": "US",
"duration": "oneMonth",
"number_type": "voip",
"stock": 47,
"available": true,
"status": "In Stock"
}
}
Number Lifecycle
Buy a private number, extend it, or release it back. Money-moving calls are idempotent and replay-safe.
Purchase a private number
Allocates a new private number and settles the order against your wallet atomically. Send an Idempotency-Key so a dropped retry never charges twice. The response shows the exact amount debited and your balance after.
Parameters
| Name | In | Required | Description |
|---|---|---|---|
country_code |
body | Required | A country returned by GET /pricing. |
duration |
body | Required | A duration key from that country's packages[] (e.g. oneMonth). |
number_type |
body | Optional | voip or non_voip. Omit to use the route default. |
Example request
curl --request POST "https://api.temp-number.com/v1/numbers/buy" \
--header "Authorization: Bearer $YOUR_API_TOKEN" \
--header "Content-Type: application/json" \
--header "Idempotency-Key: 5f9b1b3a-c4e9-4f7c-a3b3-1c8b3e8f8f8f" \
--data '{"country_code":"US","duration":"oneMonth","number_type":"voip"}'
Example response
{
"success": true,
"data": {
"id": 1482,
"phone_number": "+14035551234",
"country_code": "US",
"country_name": "United States",
"number_type": "voip",
"status": "active",
"purchase_date": "2026-05-13T17:42:09Z",
"expire_date": "2026-06-13T17:42:09Z"
},
"meta": {
"charged": 4.99,
"currency": "USD",
"wallet_balance_after": 119.51
}
}
Renew a number
Extends a number by the requested package. The new expiry is added to the current expiry, so you can renew early. The renewal is priced at the current site rate for that duration (computed server-side - no client-set amount).
Parameters
| Name | In | Required | Description |
|---|---|---|---|
id |
path | Required | Number id from GET /numbers. |
package |
body | Optional | oneMonth (default), threeMonths, sixMonths, oneYear. |
Example request
curl --request POST "https://api.temp-number.com/v1/numbers/1482/renew" \
--header "Authorization: Bearer $YOUR_API_TOKEN" \
--header "Content-Type: application/json" \
--header "Idempotency-Key: 7f3e8c4a-2d1b-4e8f-91a4-3b9c2d8e1f4a" \
--data '{"package":"threeMonths"}'
Example response
{
"success": true,
"data": {
"id": 1482,
"phone_number": "+14035551234",
"status": "active",
"expire_date": "2026-09-13T17:42:09Z"
},
"meta": {
"charged": 12.99,
"currency": "USD",
"wallet_balance_after": 106.52
}
}
Cancel a number (refund if eligible)
Releases a number and stops further SMS. A full wallet refund is issued when the cancel is requested within 120 minutes of purchase AND the number received no SMS AND it is still active. Outside that window the number is still released, but no refund - check meta.refunded.
Parameters
| Name | In | Required | Description |
|---|---|---|---|
id |
path | Required | Number id from GET /numbers. |
Example request
curl --request POST "https://api.temp-number.com/v1/numbers/1482/cancel" \
--header "Authorization: Bearer $YOUR_API_TOKEN" \
--header "Idempotency-Key: 9a1c7d2e-5f8b-4c3a-9e2d-6b4f1a8c3e7d"
Example response
{
"success": true,
"data": {
"id": 1482,
"phone_number": "+14035551234",
"status": "cancelled"
},
"meta": {
"refunded": 4.99,
"currency": "USD",
"wallet_balance_after": 124.50
}
}
Your Numbers & SMS
List the numbers you own and read the SMS they receive.
List your numbers
Every number on your account, newest first. Filter by lifecycle with ?status= - use expiring_soon (within 10 days of expiry) to drive renewal prompts.
Parameters
| Name | In | Required | Description |
|---|---|---|---|
status |
query | Optional | active, expiring_soon, expired, cancelled, or all (default). |
Example request
curl --request GET "https://api.temp-number.com/v1/numbers?status=expiring_soon" \
--header "Accept: application/json" \
--header "Authorization: Bearer $YOUR_API_TOKEN"
Example response
{
"success": true,
"data": [
{
"id": 1482,
"phone_number": "+14035551234",
"country_code": "US",
"country_name": "United States",
"number_type": "voip",
"status": "active",
"purchase_date": "2026-05-13T17:42:09Z",
"expire_date": "2026-06-13T17:42:09Z"
}
],
"meta": { "count": 1, "status": "expiring_soon" }
}
Get number details + recent SMS
Full details of one number together with the SMS it has received, newest first. You receive the raw message body - OTP parsing is up to you. Returns 404 (not 403) if the id isn't yours.
Parameters
| Name | In | Required | Description |
|---|---|---|---|
id |
path | Required | Number id from GET /numbers. |
Example request
curl --request GET "https://api.temp-number.com/v1/numbers/1482/sms" \
--header "Accept: application/json" \
--header "Authorization: Bearer $YOUR_API_TOKEN"
Example response
{
"success": true,
"data": {
"number": {
"id": 1482,
"phone_number": "+14035551234",
"country_code": "US",
"country_name": "United States",
"number_type": "voip",
"status": "active",
"purchase_date": "2026-05-13T17:42:09Z",
"expire_date": "2026-06-13T17:42:09Z"
},
"messages": [
{
"id": 9912,
"from": "+18005550199",
"body": "Your code is 432901",
"received_at": "2026-05-13T17:43:14Z"
}
]
},
"meta": { "count": 1 }
}
Receive SMS by phone number
Cursor-paginated SMS for a number you own, addressed by its E.164 phone number rather than its id. Best for high-volume polling. Cursors are opaque - pass meta.nextCursor back to page forward.
Parameters
| Name | In | Required | Description |
|---|---|---|---|
phoneNumber |
query | Required | The number in E.164 (or digits), e.g. +14035551234. |
limit |
query | Optional | Page size 1-100 (default 50). |
cursor |
query | Optional | Opaque pagination cursor from a previous response. |
Example request
curl --request GET "https://api.temp-number.com/v1/receive-sms?phoneNumber=%2B14035551234" \
--header "Accept: application/json" \
--header "Authorization: Bearer $YOUR_API_TOKEN"
Example response
{
"success": true,
"data": {
"phoneNumber": "+14035551234",
"purchaseStatus": "active",
"messages": [
{
"id": 1842,
"from": "WhatsApp",
"to": "+14035551234",
"message": "Your verification code is 483920.",
"receivedAt": "2026-05-13T17:43:14Z"
}
]
},
"meta": {
"count": 1,
"pageSize": 50,
"hasMore": false,
"nextCursor": null,
"prevCursor": null,
"requestedAt": "2026-05-13T17:43:20Z"
}
}
Ready to build?
Generate a token and make your first call in under a minute.