v2.0.0OpenAPI 3.1.0Download openapi.json

Virtnumber SMS API & MCP Server

Buy and manage virtual phone numbers, check pricing, and receive SMS by webhook.

REST resources, one URL/verb per action, RFC 9457 application/problem+json error bodies, and RateLimit-* response headers on every request.

Authentication

Every request needs both headers below. Server: https://www.virtnumber.com

x-api-userYour user ID. Find it in the developer panel.
x-api-tokenGenerate in the developer panel. Shown once, right after generation. The panel can't display an existing token again.
Developer API connection status

No data

Operational
Degraded
Down

Countries

Read-only catalog. No balance required.

get/api/v2/developer/countries

List available countries

Every country currently on sale, with its ISO2 code and calling code. No account balance required.

Responses

200OK
{
  "countries": [
    {
      "countryid": "GB",
      "countryfull": "United Kingdom",
      "countrycode": "44"
    },
    {
      "countryid": "US",
      "countryfull": "United States",
      "countrycode": "1"
    }
  ]
}
401Missing or invalid API credentials.
{
  "type": "https://virtnumber.com/developer/errors/unauthorized",
  "title": "Missing or invalid API credentials",
  "status": 401
}
429Too many requests: 20 per 15 minutes, shared with the legacy v1 endpoint.
cURL
curl -X GET 'https://www.virtnumber.com/api/v2/developer/countries' \
  -H 'x-api-user: YOUR_USER_ID' \
  -H 'x-api-token: YOUR_API_TOKEN'

Pricing

Read-only catalog. No balance required.

get/api/v2/developer/pricing

List pricing plans

Every plan (7/30/180/360-day, etc.) grouped by country. No account balance required.

Query parameters

NameInDescription
countryidqueryFilter to one country (case-insensitive).

Responses

200OK
{
  "pricing": [
    {
      "countryid": "GB",
      "countryfull": "United Kingdom",
      "countrycode": "44",
      "plans": [
        {
          "id": 51,
          "days": 30,
          "price": "9.90",
          "salestatus": "yes",
          "requiresAddress": false
        }
      ]
    }
  ]
}
400Request failed validation.
401Missing or invalid API credentials.
{
  "type": "https://virtnumber.com/developer/errors/unauthorized",
  "title": "Missing or invalid API credentials",
  "status": 401
}
429Too many requests: 20 per 15 minutes, shared with the legacy v1 endpoint.
cURL
curl -X GET 'https://www.virtnumber.com/api/v2/developer/pricing?countryid=GB' \
  -H 'x-api-user: YOUR_USER_ID' \
  -H 'x-api-token: YOUR_API_TOKEN'

Numbers

Buy, list, and cancel numbers. Requires ≥1 EUR balance.

get/api/v2/developer/numbers

List your active numbers

Responses

200OK
{
  "numbers": [
    {
      "number": "447911123456",
      "numberstatus": "active",
      "firstbuy": "2026-08-01 10:00:00",
      "expirationday": "2026-08-30 22:00:00",
      "webhook": "https://example.com/webhook"
    }
  ]
}
401Missing or invalid API credentials.
{
  "type": "https://virtnumber.com/developer/errors/unauthorized",
  "title": "Missing or invalid API credentials",
  "status": 401
}
403Account balance below the 1 EUR minimum required to use the API.
{
  "type": "https://virtnumber.com/developer/errors/low-balance",
  "title": "Account balance below minimum required to use the API",
  "status": 403
}
429Too many requests: 20 per 15 minutes, shared with the legacy v1 endpoint.
cURL
curl -X GET 'https://www.virtnumber.com/api/v2/developer/numbers' \
  -H 'x-api-user: YOUR_USER_ID' \
  -H 'x-api-token: YOUR_API_TOKEN'
post/api/v2/developer/numbers

Buy a number

Orders the next available number for the given plan. Get valid id/countryid pairs from GET /api/v2/developer/pricing first.

Request body

idrequiredPlan ID from the pricing endpoint.
countryidrequired
webhookWhere incoming SMS to this number get POSTed. Can be set/changed later in number settings.

Responses

200Purchased
{
  "phone": "447911123456",
  "plan": "30d",
  "price": 9.9,
  "days": 30
}
400Request failed validation.
401Missing or invalid API credentials.
{
  "type": "https://virtnumber.com/developer/errors/unauthorized",
  "title": "Missing or invalid API credentials",
  "status": 401
}
402Balance too low for this specific purchase.
{
  "type": "https://virtnumber.com/developer/errors/insufficient-balance",
  "title": "Balance too low for this purchase",
  "status": 402,
  "detail": "This purchase costs 9.90 EUR; your balance is 3.20 EUR.",
  "price": 9.9,
  "balance": 3.2
}
403Account balance below the 1 EUR minimum required to use the API.
{
  "type": "https://virtnumber.com/developer/errors/low-balance",
  "title": "Account balance below minimum required to use the API",
  "status": 403
}
404Resource not found.
429Too many requests: 20 per 15 minutes, shared with the legacy v1 endpoint.
502Upstream number provider couldn't fulfill the request.
cURL
curl -X POST 'https://www.virtnumber.com/api/v2/developer/numbers' \
  -H 'x-api-user: YOUR_USER_ID' \
  -H 'x-api-token: YOUR_API_TOKEN' \
  -H 'Content-Type: application/json' \
  -d '{"id":51,"countryid":"GB","webhook":"https://example.com/webhook"}'

Example request body

{
  "id": 51,
  "countryid": "GB",
  "webhook": "https://example.com/webhook"
}
delete/api/v2/developer/numbers

Cancel a number

Query parameters

NameInDescription
numberrequiredquery

Responses

200Deleted
{
  "message": "Number has been deleted"
}
400Request failed validation.
401Missing or invalid API credentials.
{
  "type": "https://virtnumber.com/developer/errors/unauthorized",
  "title": "Missing or invalid API credentials",
  "status": 401
}
403Account balance below the 1 EUR minimum required to use the API.
{
  "type": "https://virtnumber.com/developer/errors/low-balance",
  "title": "Account balance below minimum required to use the API",
  "status": 403
}
404Resource not found.
429Too many requests: 20 per 15 minutes, shared with the legacy v1 endpoint.
502Upstream number provider couldn't fulfill the request.
cURL
curl -X DELETE 'https://www.virtnumber.com/api/v2/developer/numbers?number=...' \
  -H 'x-api-user: YOUR_USER_ID' \
  -H 'x-api-token: YOUR_API_TOKEN'

Messages

Send SMS from an owned number. Only virtual numbers can send.

get/api/v2/developer/send-pricing

List send pricing

For every country you can send *from* (virtual numbers only), every destination that number is allowed to send to and the price per message. No account balance required.

Responses

200OK
{
  "sendPricing": [
    {
      "countryid": "US",
      "countryfull": "United States",
      "destinations": [
        {
          "destination": "US",
          "destinationName": "United States",
          "price": 0.0284
        },
        {
          "destination": "CA",
          "destinationName": "Canada",
          "price": 0.0284
        },
        {
          "destination": "MX",
          "destinationName": "Mexico",
          "price": 0.6219
        }
      ]
    }
  ]
}
401Missing or invalid API credentials.
{
  "type": "https://virtnumber.com/developer/errors/unauthorized",
  "title": "Missing or invalid API credentials",
  "status": 401
}
429Too many requests: 20 per 15 minutes, shared with the legacy v1 endpoint.
cURL
curl -X GET 'https://www.virtnumber.com/api/v2/developer/send-pricing' \
  -H 'x-api-user: YOUR_USER_ID' \
  -H 'x-api-token: YOUR_API_TOKEN'
post/api/v2/developer/messages

Send a message

Sends an SMS from one of your owned numbers. Only virtual numbers can send, and only to destinations listed for that number's country in GET /api/v2/developer/send-pricing.

Limits

API requests20 / 15 min
New conversations4 / day, per sending number
Replies to an existing contact2 / min, per sending number

Request body

numberrequiredOne of your owned, active phone numbers. With or without a leading +.
torequiredDestination number, E.164 or local format.
textrequired

Responses

200Sent
{
  "sid": "SM1234567890abcdef1234567890abcdef",
  "to": "+14155551234",
  "price": 0.0284
}
400Request failed validation.
401Missing or invalid API credentials.
{
  "type": "https://virtnumber.com/developer/errors/unauthorized",
  "title": "Missing or invalid API credentials",
  "status": 401
}
402Balance too low for this specific purchase.
{
  "type": "https://virtnumber.com/developer/errors/insufficient-balance",
  "title": "Balance too low for this purchase",
  "status": 402,
  "detail": "This purchase costs 9.90 EUR; your balance is 3.20 EUR.",
  "price": 9.9,
  "balance": 3.2
}
404Resource not found.
409This number can't send messages.
{
  "type": "https://virtnumber.com/developer/errors/cannot-send",
  "title": "This number cannot send messages",
  "status": 409,
  "detail": "Only virtual numbers can send messages"
}
429One of three limits: the general 20-per-15-minute API limit (`RateLimit-*` headers), the 4-new-conversations-per-day cap, or the 2-replies-per-minute cap.
{
  "type": "https://virtnumber.com/developer/errors/rate-limited",
  "title": "Too many requests",
  "status": 429,
  "detail": "Rate limit exceeded. Please slow down and retry later.",
  "resetSeconds": 300
}
502Upstream number provider couldn't fulfill the request.
cURL
curl -X POST 'https://www.virtnumber.com/api/v2/developer/messages' \
  -H 'x-api-user: YOUR_USER_ID' \
  -H 'x-api-token: YOUR_API_TOKEN' \
  -H 'Content-Type: application/json' \
  -d '{"number":"447911123456","to":"+14155551234","text":"Your table is ready."}'

Example request body

{
  "number": "447911123456",
  "to": "+14155551234",
  "text": "Your table is ready."
}

Webhooks

Incoming SMS

Sent to the webhook URL set on a number (via numbers, or later in number settings) every time it receives an SMS.

Payload fields

status
fromSender's number.
toYour virtnumber number.
text
datetime
Every webhook request carries an `X-Virtnumber-Signature` header: `sha256=` + HMAC-SHA256 of the raw request body, keyed by `sha256(your API token)`. Recompute and compare (constant-time) before trusting the payload.
Example payload
{
  "status": "ok",
  "from": "",
  "to": "",
  "text": "",
  "datetime": "2030-05-06 21:37:28"
}

MCP server for AI agents

URLhttps://www.virtnumber.com/mcp
AuthOAuth 2.1 + PKCE, Bearer token

Tools

ToolScope
get_pricingpricing:read
list_my_numbersnumbers:read
buy_numbernumbers:buy
delete_numbernumbers:delete
send_smsmessages:send

Frequently asked questions

Does the API support bulk SMS or mass texting?
No. A number may start four new conversations per day, so the API is built for transactional messages and replies, not campaigns. If you need to reach thousands of recipients at once, a bulk SMS provider is the right tool.
What are the rate limits?
Twenty requests per fifteen minutes per token, plus the four new conversations per number per day noted above. Reading messages and listing numbers count against the request limit only.
Can an AI agent use this directly?
Yes. The MCP server above exposes the same operations as tool calls, so an agent can buy a number, read messages and check pricing without you wrapping the REST API yourself.
Which numbers can send SMS?
Numbers in the United States send to the US, Canada and Mexico. Swedish numbers send across Europe. Every number receives SMS, and the panel shows the sending price per destination before you buy.

© 2019–2026 Virtnumber. All rights reserved.