Privacy settings

Select the cookie categories you allow. You can change your choice at any time via Privacy settings at the bottom of every page.

Necessary

These cookies are necessary for the website to function and cannot be switched off. They enable core functions such as secure sign-in, account sessions and protection against fraud, and store your cookie preferences.

Always on

Statistics

These cookies help us understand how visitors interact with the website by collecting information about the pages visited, navigation and loading times. We use this information to improve the website and our services.

Marketing

These cookies measure the effectiveness of our advertising, for example whether a visit from a Google Ads advertisement leads to a registration or a purchase. They are not used to show you advertising or to build an advertising profile.

Every cookie, with its purpose and how long it is kept, is listed in our Cookie Policy.

Skip to content
v2.1.0OpenAPI 3.1.0Download openapi.json

Virtnumber SMS API & MCP Server

Rent virtual phone numbers, read the SMS they receive, send SMS, and check pricing, paid from your prepaid balance.

REST resources, one URL/verb per action, RFC 9457 application/problem+json error bodies, and RateLimit-* response headers on every request. The same operations are available to AI agents through the MCP server at https://www.virtnumber.com/mcp.

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

Operational (~28ms avg response)

Operational
Degraded
Down

Countries

Read-only catalog. Requires ≥1 EUR balance, like every API call except the balance.

get/api/v2/developer/countries

List available countries

Every country currently on sale, with its ISO2 code and calling code. Requires ≥1 EUR balance.

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
}
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/countries' \
  -H 'x-api-user: YOUR_USER_ID' \
  -H 'x-api-token: YOUR_API_TOKEN'

Pricing

Read-only catalog. Requires ≥1 EUR balance, like every API call except the balance.

get/api/v2/developer/pricing

List pricing plans

Every plan (7/30/180/360-day, etc.) grouped by country. Requires ≥1 EUR balance.

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
}
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/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,
  "numberstatus": "active"
}
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
}
403Balance below the 1 EUR API minimum, or no billing details saved on the account (every number needs the buyer on record; plans with requiresAddress need an address in that country instead).
{
  "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.
409The number is still being set up and can't be cancelled yet.
{
  "type": "https://virtnumber.com/developer/errors/number-pending",
  "title": "This number is still being set up",
  "status": 409,
  "detail": "The number is still being set up and cannot be deleted yet."
}
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 SMS. One SMS is up to 160 characters, or up to 70 if the text has non-Latin characters; a longer text is billed as several SMS (153 or 67 characters each). Requires ≥1 EUR balance.

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
}
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/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. Every message is checked automatically before it is sent; a message that may break the messaging rules is held (422) and still charged. A recipient who replied STOP to the number is blocked permanently (403).

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,
  "segments": 1
}
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
}
403Recipient opted out: they replied STOP to this number, so it can no longer send them messages (problem type recipient-opted-out). Not charged.
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"
}
422Message held by the automatic content check and not sent (problem type message-held): status pending_review or rejected, with a reason. The price is still charged.
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."
}
get/api/v2/developer/messages

Read messages

Reads SMS received on (and sent from) one of your numbers, newest first. With after_id, returns only newer messages, oldest first. With wait (1 to 55 seconds) the request waits until a new incoming message arrives and returns it, so one request replaces repeated polling.

Limits

API requests20 / 15 min

Query parameters

NameInDescription
numberrequiredqueryOne of your numbers, with or without +.
after_idqueryOnly messages with a larger id.
fromqueryOnly messages whose sender contains this text.
directionquery
limitquery
waitqueryWait up to this many seconds for the next incoming message.

Responses

200OK
{
  "number": "447911123456",
  "messages": [
    {
      "id": 48213,
      "direction": "in",
      "from": "Google",
      "to": "447911123456",
      "text": "G-482913 is your Google verification code.",
      "receivedAt": "2026-09-24T10:15:02.000Z",
      "codes": [
        "482913"
      ]
    }
  ],
  "latestId": 48213
}
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.
cURL
curl -X GET 'https://www.virtnumber.com/api/v2/developer/messages?number=...&after_id=...&from=...&direction=...&limit=...&wait=...' \
  -H 'x-api-user: YOUR_USER_ID' \
  -H 'x-api-token: YOUR_API_TOKEN'

Balance

Your prepaid balance. The account owner tops it up on the website. The only call that also works below 1 EUR.

get/api/v2/developer/balance

Get balance

Your balance in EUR. 1 credit = 1 EUR. The account owner tops up the balance on the website; API clients and agents spend the existing balance only.

Responses

200OK
{
  "balanceEur": 12.5
}
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/balance' \
  -H 'x-api-user: YOUR_USER_ID' \
  -H 'x-api-token: YOUR_API_TOKEN'

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 with PKCE, set up automatically by the client. Headless agents can send x-api-user and x-api-token headers instead.

Tools

ToolScope
get_balance(any)
get_pricingpricing:read
list_my_numbersnumbers:read
list_messagesmessages:read
wait_for_smsmessages:read
buy_numbernumbers:buy
send_smsmessages:send
delete_numbernumbers:delete

Connect

Claude (web and desktop)

Settings, Connectors, Add custom connector, paste the server URL.

Claude Code
claude mcp add --transport http virtnumber https://www.virtnumber.com/mcp
Cursor (~/.cursor/mcp.json)
{
  "mcpServers": {
    "virtnumber": { "url": "https://www.virtnumber.com/mcp" }
  }
}
VS Code (.vscode/mcp.json)
{
  "servers": {
    "virtnumber": { "type": "http", "url": "https://www.virtnumber.com/mcp" }
  }
}
Headless agent (API key)
POST https://www.virtnumber.com/mcp
x-api-user: <your user id>
x-api-token: <your API token>

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 Getcom OU #14263772. All rights reserved.

Marati 5, 11713 Tallinn, Estonia · +372 5382 8793