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-user | Your user ID. Find it in the developer panel. |
x-api-token | Generate in the developer panel. Shown once, right after generation. The panel can't display an existing token again. |
No data
Countries
Read-only catalog. No balance required.
/api/v2/developer/countriesList 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 -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.
/api/v2/developer/pricingList pricing plans
Every plan (7/30/180/360-day, etc.) grouped by country. No account balance required.
Query parameters
| Name | In | Description |
|---|---|---|
countryid | query | Filter 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 -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.
/api/v2/developer/numbersList 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 -X GET 'https://www.virtnumber.com/api/v2/developer/numbers' \
-H 'x-api-user: YOUR_USER_ID' \
-H 'x-api-token: YOUR_API_TOKEN'/api/v2/developer/numbersBuy 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
idrequired | Plan ID from the pricing endpoint. |
countryidrequired | |
webhook | Where 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 -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"
}/api/v2/developer/numbersCancel a number
Query parameters
| Name | In | Description |
|---|---|---|
numberrequired | query |
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 -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.
/api/v2/developer/send-pricingList 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 -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'/api/v2/developer/messagesSend 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 requests | 20 / 15 min |
| New conversations | 4 / day, per sending number |
| Replies to an existing contact | 2 / min, per sending number |
Request body
numberrequired | One of your owned, active phone numbers. With or without a leading +. |
torequired | Destination 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 -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 | |
from | Sender's number. |
to | Your virtnumber number. |
text | |
datetime |
{
"status": "ok",
"from": "",
"to": "",
"text": "",
"datetime": "2030-05-06 21:37:28"
}MCP server for AI agents
| URL | https://www.virtnumber.com/mcp |
| Auth | OAuth 2.1 + PKCE, Bearer token |
Tools
| Tool | Scope |
|---|---|
get_pricing | pricing:read |
list_my_numbers | numbers:read |
buy_number | numbers:buy |
delete_number | numbers:delete |
send_sms | messages: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.