# VertexSMS — full documentation This file contains the complete REST API and MCP server documentation for VertexSMS in plain Markdown, intended for ingestion by LLMs and AI assistants. For the navigation index, see [llms.txt](https://vertexsms.com/llms.txt). For the rendered documentation site, see https://vertexsms.com/. Sections: 1. REST API — Introduction 2. REST API — Authentication 3. REST API — Sending SMS 4. REST API — Sending Viber message 5. REST API — Number Lookup (HLR) 6. REST API — Sender ID 7. REST API — Error codes 8. REST API — Other endpoints (Operator, Prices, MCC/MNC, Prefixes, Number Correction) 9. MCP server — Introduction 10. MCP server — Quickstart 11. MCP server — Authentication 12. MCP server — Tools reference 13. MCP server — Errors --- # REST API — Introduction Source: https://vertexsms.com/en/api/introduction **Building an AI integration?** See the [MCP server documentation](https://vertexsms.com/en/mcp/introduction) — it lets Claude, Cursor, VS Code, and other AI assistants use VertexSMS without any glue code. The VertexSMS API is based on REST principles. To use it you need a VertexSMS account and an API access token. You can generate them inside your VertexSMS account. You must supply a `Content-type: application/json` header on all PUT or POST requests. ## HTTP headers and codes The REST API uses standard HTTP status codes: | Code | Description | |------|-------------| | 200 | Success. | | 400 | General error when fulfilling the request would cause an invalid state. Domain validation errors, missing data, etc. | | 401 | Similar to 403, but specifically when authentication is possible but has failed or has not yet been provided. | | 403 | Server understood the request but refuses to fulfil it. Authorisation will not help and the request SHOULD NOT be repeated. | | 404 | Server has not found anything matching the Request-URI. No indication is given whether the condition is temporary or permanent. | | 405 | Method specified in the Request-Line is not allowed for the resource identified by the Request-URI. | | 409 | Request could not be completed due to a conflict with the current state of the resource. | | 500 | Server error, please try again. | | 501 | Server error, please try again. | | 503 | Server is currently unable to handle the request due to temporary overloading or maintenance. Please try again. | ## Handling errors If the API rejects your request, an error is returned as a 4xx (or 500 if our systems fail) HTTP status code with a JSON-encoded body describing the error. Bad request example: ``` POST /sms HTTP/1.1 Host: api.vertexsms.com Content-Type: application/json Accept: application/json X-VertexSMS-Token: eB52vNTPL9fO3rDrx8pYmVnj6nqceHNhnqceHNh { "to": "37069912345", "from": "invalid sender ID", "message": "Test SMS 001" } ``` Response: ``` HTTP/1.1 400 Bad Request Content-Type: application/json { "message": "Invalid value for field 'from'. Sender ID must either be a valid MSISDN or an alpha-numeric string (max. length: 11 characters), which may consist only of upper+lower-case latin letters, digits, spaces and dots." } ``` ## Security Use HTTPS for all VertexSMS API requests. All callbacks from VertexSMS are made only from the IP ranges `178.33.133.192/28` and `178.32.167.92`. --- # REST API — Authentication Source: https://vertexsms.com/en/api/authentication Most API actions require an access token. Generate it once and store it safely. Supply the token via the `X-VertexSMS-Token` HTTP header (used in all examples), or via the `at` query-string parameter: ``` GET https://api.vertexsms.com/someaction?at=eB52vNTPL9fO3rDrx8pYmVnj6nqceHNhnqceHNh ``` ## Generating a token Sign in to your VertexSMS account, then go to **MY ACCOUNT → API**. ## Known limitations Currently only one access token at a time is supported per account. Support for multiple tokens with different permissions and IP access blocking is on the roadmap. --- # REST API — Sending SMS Source: https://vertexsms.com/en/api/sms ``` POST https://api.vertexsms.com/sms ``` Submits message(s) for sending. On success returns HTTP `200 OK` and an array of IDs of the messages added to the sending queue. ## Required parameters | Field | Type | Description | |-------|------|-------------| | to | string | Destination address (recipient). | | from | string | Source address (originator). | | message | string | Message body. If `udh` is not used, length is unlimited — messages are split automatically. With `udh`, max length depends on encoding. | ## Optional parameters | Field | Type | Description | |-------|------|-------------| | dlrUrl | url | Where to deliver the delivery report for each submitted message. The report contains the same message ID returned at submission. | | priority | string | `high` (registration codes, password reminders, urgent SMS), `normal` (default), `low` (mass messages). | | scheduled | string | Schedule sending in ISO 8601 format, e.g. `2015-01-01T13:00:00+02:00`. | | udh | string | User Data Header for long/concatenated messages. Each hex pair must be prefixed with `%`. If you specify `udh`, automatic splitting is disabled and you must also include `coding`. | | coding | integer | Message encoding. `0` = GSM-7 (default), `1` = 8-bit, `2` = UCS-2. If you specify `coding`, automatic splitting is disabled and you must also include `udh` if the message exceeds the per-encoding character limit (160 GSM-7 / 70 UCS-2). | | testMode | string | Test the API without sending a real message. `1` = emulate success delivery, `2` = emulate failed delivery. | | expireIn | integer | Seconds after which the message expires. Range `[360, 432000]`. | | correctBy | string | Fix recipient number for a given country. Example: `6xxxxxxx` → `3706xxxxxxx` if `LT` is passed. ISO 3166-1 alpha-2 country code. | ### Request example ``` POST /sms HTTP/1.1 Host: api.vertexsms.com Content-Type: application/json Accept: application/json X-VertexSMS-Token: eB52vNTPL9fO3rDrx8pYmVnj6nqceHNhnqceHNh { "to": "37069912345", "from": "API", "message": "Test SMS 001" } ``` ### Response example ``` HTTP/1.1 200 OK Content-Type: application/json Cache-control: no-cache X-VertexSMS-Amount-Sent: 1 ["1281532560"] ``` ## Message text, encoding and length A standard SMS using GSM-7 contains up to 160 characters. If you include unicode characters (Chinese, Cyrillic, etc.) the API switches to UCS-2 (`coding=2`) and the maximum shrinks to 70 characters per part. Longer text is split into parts. Each part is billed as a separate SMS at the same per-destination rate. When split, a User Data Header (UDH) is added to each part for transparent reassembly on the recipient's device, reducing per-part capacity to 153 (GSM-7) or 67 (UCS-2) characters. If the message contains at least one non-GSM-7 character, the entire message is treated as unicode (UCS-2). The `X-VertexSMS-Amount-Sent` response header reports the actual number of SMS parts sent. Some GSM-7 characters take 14 bits and count as 2 characters: `[`, `]`, `~`, `€`, and others. ## Delivery reports (DLRs) After a send attempt, VertexSMS performs a POST to your `dlrUrl` with a JSON delivery receipt. Example (when `dlrUrl=http://yourserver.com/your_script.php`): ``` POST /your_script.php HTTP/1.1 Host: yourserver.com Content-Type: application/json { "id": "1281532560", "status": "1", "error": 0, "mcc": "246", "mnc": "021" } ``` DLR fields: | Field | Type | Description | |-------|------|-------------| | id | string | Unique message identifier returned at submission. | | status | integer | `1` = delivered. `2` = not delivered (see `error`). `16` = sent, but delivery period expired. | | error | integer | VertexSMS error code (see Error codes section). | | mcc | string | Mobile country code, when available. | | mnc | string | Mobile network code, when available. | **Your DLR endpoint MUST respond `200 OK` with body `OK`.** Otherwise the callback is considered failed and is retried until it succeeds. ## Scheduled sendings ``` GET https://api.vertexsms.com/sms?scheduled ``` Request: ``` GET /sms?scheduled HTTP/1.1 Host: api.vertexsms.com Accept: application/json X-VertexSMS-Token: eB52vNTPL9fO3rDrx8pYmVnj6nqceHNhnqceHNh ``` Response: ``` HTTP/1.1 200 OK Content-Type: application/json [ { "id": "1695684253", "scheduled": "2016-03-16 18:00:00", "from": "Test", "to": "37069559295", "message": "Hello!", "dlrUrl": "http://vertexsms.com" }, { "id": "1695684559", "scheduled": "2016-03-16 18:00:00", "from": "Test", "to": "37069559295", "message": "Hello!", "dlrUrl": "http://vertexsms.com" } ] ``` Scheduled sending fields: `id` (sms identifier), `scheduled` (UTC datetime), `from` (originator), `to` (recipient), `message` (body), `dlrUrl` (delivery-report URL). --- # REST API — Sending Viber message Source: https://vertexsms.com/en/api/viber ``` POST https://api.vertexsms.com/viber ``` Submits Viber message(s) for sending. On success returns HTTP `200 OK` and an array of IDs of messages added to the sending queue. ## Required parameters | Field | Type | Description | |-------|------|-------------| | to | string | Destination address (recipient). | | from | string | Source address (originator). The `from` must be approved in advance by VertexSMS. Register new senders via the [senderID API](https://vertexsms.com/en/api/senderid). | | message | string | Message body. Maximum length 1000 characters. | ## Optional parameters | Field | Type | Description | |-------|------|-------------| | dlrUrl | url | Delivery-report URL. | | priority | string | `high`, `normal` (default), `low`. | | scheduled | string | ISO 8601 timestamp. | | testMode | string | `1` = emulate success, `2` = emulate failure. | | correctBy | string | Country-based number correction; ISO 3166-1 alpha-2 code. | ### Request example ``` POST /viber HTTP/1.1 Host: api.vertexsms.com Content-Type: application/json Accept: application/json X-VertexSMS-Token: eB52vNTPL9fO3rDrx8pYmVnj6nqceHNhnqceHNh { "to": "37069912345", "from": "Test", "message": "Test Viber message" } ``` ### Response example ``` HTTP/1.1 200 OK Content-Type: application/json Cache-control: no-cache X-VertexSMS-Amount-Sent: 1 ["1281532560"] ``` ## Button To send a message with a button, supply the `im` (interactive message) option: ```json "im": { "action": { "url": "https://example.com", "title": "go to example.com" } } ``` Button parameters: `url` (valid URL), `title` (button label). Full request example with a button: ```json { "to": "+370...", "from": "Test", "message": "Hello World!", "im": { "action": { "url": "https://example.com", "title": "go to example.com" } } } ``` ## Image ```json "im": { "image": { "url": "https://example-cdn.com/image.png" } } ``` `url` must be a valid URL whose last path segment ends in `.jpeg`, `.png`, or `.gif`. Max image size 1 MB. Image and button can be combined: ```json { "to": "+370...", "from": "Test", "message": "Hello World!", "im": { "image": { "url": "https://example-cdn.com/image.png" }, "action": { "url": "https://example.com", "title": "go to example.com" } } } ``` --- # REST API — Number Lookup (HLR) Source: https://vertexsms.com/en/api/hlr HLR (Home Location Register) lookup determines the current service provider of a mobile subscriber. ``` POST https://api.vertexsms.com/hlr ``` Submits the provided `msisdn` for HLR lookup. On success returns HTTP `200 OK`. ## Required parameters | Field | Type | Description | |-------|------|-------------| | msisdn | string | International subscriber number to look up. | | callBackUrl | url | Where to deliver the HLR result. | ### Request example ``` POST /hlr HTTP/1.1 Host: api.vertexsms.com Content-Type: application/json Accept: application/json X-VertexSMS-Token: eB52vNTPL9fO3rDrx8pYmVnj6nqceHNhnqceHNh { "msisdn": "37069912345", "callBackUrl": "http://api.vertexsms.com/hlr_callback?myRequestId=123456" } ``` ### Response example ``` HTTP/1.1 200 OK Content-Type: application/json Cache-control: no-cache [1203877133] ``` ## HLR lookup callback After the lookup completes, VertexSMS POSTs the result to your `callBackUrl`: ``` POST /your_script.php HTTP/1.1 Host: yourserver.com Content-Type: application/json { "id": "1203877133", "error": "0", "imsi": "2460210051600001", "country": "LT", "mcc": "246", "mnc": "021" } ``` Callback fields: | Field | Type | Description | |-------|------|-------------| | id | string | Unique HLR lookup identifier returned at submission. | | error | integer | VertexSMS error code (see Error codes). | | imsi | integer | International mobile subscriber identity. | | country | string | ISO 3166-1 alpha-2 country code. | | operatorId | integer | Internal VertexSMS operator identifier. | | mcc | string | Mobile country code. | | mnc | string | Mobile network code. | | ported | array | Present if the number is ported. Contains `operatorId`, `operator` (origin operator name), `country`. | **Your callback endpoint MUST respond `200 OK` with body `OK`.** Otherwise the callback is retried until it succeeds. --- # REST API — Sender ID Source: https://vertexsms.com/en/api/senderid The name of your company, brand, or customer-support number is displayed as the sender on outgoing messages. ## Register an alphanumeric sender Request: ``` POST /senderId HTTP/1.1 Host: api.vertexsms.com Content-Type: application/json Accept: application/json X-VertexSMS-Token: eB52vNTPL9fO3rDrx8pYmVnj6nqceHNhnqceHNh { "name": "TestSender", "type": "AlphaNumeric", "category": "Other", "categoryDescription": "Some description", "notificationUrl": "http://client.com/senderIdCallBack" } ``` Response: ``` HTTP/1.1 200 OK Content-Type: plain/text Cache-control: no-cache 123 ``` On success returns `200 OK` and the new sender's numeric ID (e.g. `123`). Parameters: | Field | Type | Description | |-------|------|-------------| | name | string | Sender name, 3–11 characters. Standard alphanumeric (upper/lower) recommended. The symbols `- _ & # !` are accepted but some operators do not display them correctly. | | type | string | `AlphaNumeric` (for this flow). | | category | string | One of `Company`, `Product`, `Brand`, `Shortcode`, `Landline`, `Other`. | | categoryDescription | string | Comments / description shown to the reviewer. Required for sender-name verification. | | notificationUrl | string | Webhook URL for sender-status notifications. | ## Register a mobile number as a sender Your mobile number is displayed as a sender so recipients can reply to you. Request: ``` POST /senderId HTTP/1.1 Host: api.vertexsms.com Content-Type: application/json Accept: application/json X-VertexSMS-Token: eB52vNTPL9fO3rDrx8pYmVnj6nqceHNhnqceHNh { "name": "37069555555", "type": "MSISDN" } ``` Response: `200 OK` + the new sender ID. You then receive a 5-digit PIN by SMS. Confirm the sender with that PIN: ``` POST /senderId/confirm/123 HTTP/1.1 Host: api.vertexsms.com Content-Type: application/json Accept: application/json X-VertexSMS-Token: eB52vNTPL9fO3rDrx8pYmVnj6nqceHNhnqceHNh { "code": "12345" } ``` --- # REST API — Error codes Source: https://vertexsms.com/en/api/errors These error codes appear in callbacks from VertexSMS to your endpoints (delivery reports, HLR results). Errors on outgoing API calls (requests you make to VertexSMS) are reported via standard HTTP status codes — see the Introduction. | Code | Description | |------|-------------| | 0 | No error. | | 1 | Error from MSC: illegal subscriber. | | 2 | Message not delivered — validity period expired. | | 20 | Country or operator not configured for your account. | | 21 | SMS blocked by filter (e.g. number blacklisted). For details contact `support@vertexsms.com`. | | 22 | Duplicate SMS. | | 23 | Limit of max SMS to one number reached. | | 24 | Account balance limit reached. | | 40 | HLR error: subscriber unknown (probably not in operator database). It is normal to retry after some time; if it persists, the MSISDN is likely retired. | | 41 | HLR error: SMS service barred for the subscriber (operator blocking P2P SMS). | | 43 | HLR error: subscriber absent (out of network range or phone off). | | 51 | Other / unknown HLR error — contact VertexSMS support. | | 53 | Invalid MSISDN. | | 999 | Unknown VertexSMS API error. | --- # REST API — Other endpoints (Operator, Prices, MCC/MNC, Prefixes, Number Correction) Source: https://vertexsms.com/en/api/other ## Operator Get information about an operator from the VertexSMS internal database. ``` GET https://api.vertexsms.com/operators/{operatorId} ``` Returned fields: `name` (string, operator name), `country` (ISO 3166-1 alpha-2), `mcc` (int), `mnc` (array). Request: ``` GET /operators/493 HTTP/1.1 Host: api.vertexsms.com Accept: application/json X-VertexSMS-Token: eB52vNTPL9fO3rDrx8pYmVnj6nqceHNhnqceHNh ``` Response: ``` HTTP/1.1 200 OK Content-Type: application/json Cache-control: no-cache { "name": "BITE", "country": "LT", "mcc": "245", "mnc": ["020", "028"] } ``` ## Prices ``` GET https://api.vertexsms.com/rates/?format={format} ``` Input: `format` = `json` or `csv`. Returned fields: `CountryName` (e.g. `Taiwan`), `CountryCode` (ISO 3166-1 alpha-2), `Operator` (e.g. `VIBO Telecom`), `Network` (e.g. `VIBO`), `mcc` (int), `mnc` (string, may be null), `Rate` (price as string). `Network` and `Operator` may also be `All` or `All other carriers`. `All` is the single default route in a country; `All other carriers` indicates more than one default route exists. Request: ``` GET /rates/?format=json HTTP/1.1 Host: api.vertexsms.com Accept: application/json X-VertexSMS-Token: eB52vNTPL9fO3rDrx8pYmVnj6nqceHNhnqceHNh ``` Response: ``` HTTP/1.1 200 OK Content-Type: application/json Cache-control: no-cache [ { "CountryName": "Abkhazia", "CountryCode": "AB", "Operator": "Default", "Network": "Default", "MCC": "289", "MNC": null, "Rate": "0.039" }, { "CountryName": "Abkhazia", "CountryCode": "AB", "Operator": "Aquafon JSC", "Network": "Aquafon", "MCC": "289", "MNC": "67", "Rate": "0.039" } ] ``` ## MCC / MNC list ``` GET https://api.vertexsms.com/mccmnc/{country}?Page={Page} ``` Input: `country` (ISO 3166-1 alpha-2), `Page` (int). Returned fields: `country`, `mcc`, `mnc`, `operatorId`. Request: ``` GET /mccmnc/LT?Page=1 HTTP/1.1 Host: api.vertexsms.com Accept: application/json X-VertexSMS-Token: eB52vNTPL9fO3rDrx8pYmVnj6nqceHNhnqceHNh ``` Response: ``` HTTP/1.1 200 OK Content-Type: application/json Cache-control: no-cache [ { "country": "LT", "MCC": "246", "MNC": "01", "operatorId": "1891" }, { "country": "LT", "MCC": "246", "MNC": "02", "operatorId": "493" } ] ``` ## Mobile prefix list ``` GET https://api.vertexsms.com/prefixes/{country} ``` Input: `country` (ISO 3166-1 alpha-2). Returned fields: `prefix`, `country`, `operatorId`. Request: ``` GET /prefixes/LT HTTP/1.1 Host: api.vertexsms.com Accept: application/json X-VertexSMS-Token: eB52vNTPL9fO3rDrx8pYmVnj6nqceHNhnqceHNh ``` Response: ``` HTTP/1.1 200 OK Content-Type: application/json Cache-control: no-cache [ { "prefix": "3706000", "country": "LT", "operatorId": "2536" }, { "prefix": "3706001", "country": "LT", "operatorId": "2536" } ] ``` ## Number correction Validate and normalize a list of phone numbers. ``` GET https://api.vertexsms.com/numberCorrection ``` Input: an array of `{ Number, country }` objects. `country` is ISO 3166-1 alpha-2. Returned per number: `Error` (description or null), `Number` (original), `NumberType` (`mobile`, `landline`, or `unknown`), `CountryIso`, `Mobile` (bool), `NumberE164` (corrected E.164 number). Request: ``` POST /numberCorrection HTTP/1.1 Host: api.vertexsms.com Content-Type: application/json Accept: application/json X-VertexSMS-Token: eB52vNTPL9fO3rDrx8pYmVnj6nqceHNhnqceHNh [ { "Number": "861860698", "CountryIso": "LT" }, { "Number": "61860698", "CountryIso": "LT" }, { "Number": "(370)-618-60698", "CountryIso": "LT" } ] ``` Response: ``` HTTP/1.1 200 OK Content-Type: application/json Cache-control: no-cache [ { "Error": null, "Number": "378611463155463", "NumberType": "unknown", "CountryIso": "LT", "Mobile": false, "NumberE164": "+370378611463155463" }, { "Error": null, "Number": "61860698", "NumberType": "mobile", "CountryIso": "LT", "Mobile": true, "NumberE164": "+37061860698" }, { "Error": null, "Number": "37056684554775", "NumberType": "unknown", "CountryIso": "LT", "Mobile": false, "NumberE164": "+37056684554775" } ] ``` --- # MCP server — Introduction Source: https://vertexsms.com/en/mcp/introduction The VertexSMS MCP server lets AI assistants like Claude, Cursor, and VS Code Copilot use your VertexSMS account directly — no glue code, no API plumbing. The assistant sees a set of tools and calls them on your behalf. **Model Context Protocol (MCP)** is an open standard published by Anthropic for connecting AI applications to external systems. See the [protocol spec](https://modelcontextprotocol.io) if you want to understand how it works under the hood; you do not need to know it to use the server. ## Endpoint ``` https://mcp.vertexsms.com/mcp ``` The server speaks the MCP *Streamable HTTP* transport. Both standard bearer-token auth and full OAuth 2.1 are supported — see Authentication. ## Tools Ten tools wrapping the VertexSMS REST API: | Tool | Category | Description | |------|----------|-------------| | send_sms | SMS | Send an SMS message. | | get_sms_rates | SMS | Look up per-country SMS pricing. | | correct_phone_number | Numbers | Validate and convert phone numbers to E.164. | | get_operator | Numbers | Look up a mobile operator by VertexSMS ID. | | get_mcc_mnc_list | Numbers | List MCC/MNC codes for a country. | | get_mobile_prefixes | Numbers | List mobile number prefixes for a country. | | lookup_hlr | HLR | Run a synchronous HLR lookup on a phone number. | | register_sender_id | Sender ID | Submit an alphanumeric Sender ID for approval. | | register_msisdn_sender | Sender ID | Register a mobile number as a sender. | | confirm_msisdn_sender | Sender ID | Confirm a mobile-number sender via the PIN sent by SMS. | ## Why use this instead of the REST API directly? For traditional integrations (your application calls our API from server code), the REST API is the right tool. The MCP server is for the case where the caller is an AI assistant that does not have a hand-coded integration with VertexSMS — you want the assistant to *discover* what is possible and use it on demand. Concrete examples: asking Claude Desktop to send a verification code to a phone number; letting Cursor validate a CSV of phone numbers as part of a code-generation task; using a custom internal AI agent to price-check campaigns before bulk sending. ## Get started If you have a VertexSMS account, head to the Quickstart — you can be running tool calls from Claude Desktop in about 60 seconds. If you do not have an account, [contact us through the contact form](https://vertexsms.com/en/contact); registration is currently invite-only. --- # MCP server — Quickstart Source: https://vertexsms.com/en/mcp/quickstart Get an AI assistant talking to your VertexSMS account in under a minute. You will need a VertexSMS account and an API token — if you do not have a token yet, see Authentication first. ## Claude Desktop Open `claude_desktop_config.json`: | OS | Path | |----|------| | macOS | `~/Library/Application Support/Claude/claude_desktop_config.json` | | Windows | `%APPDATA%\Claude\claude_desktop_config.json` | | Linux | `~/.config/Claude/claude_desktop_config.json` | Add a `vertexsms` entry under `mcpServers`: ```json { "mcpServers": { "vertexsms": { "url": "https://mcp.vertexsms.com/mcp", "headers": { "Authorization": "Bearer YOUR_VERTEXSMS_TOKEN" } } } } ``` Replace `YOUR_VERTEXSMS_TOKEN` with your VertexSMS API token. Save and restart Claude Desktop. The ten VertexSMS tools appear in the tools menu. ## Cursor Open **Cursor → Settings → MCP**, or edit `~/.cursor/mcp.json`: ```json { "mcpServers": { "vertexsms": { "url": "https://mcp.vertexsms.com/mcp", "headers": { "Authorization": "Bearer YOUR_VERTEXSMS_TOKEN" } } } } ``` Restart Cursor. Tools become available to the agent immediately. ## VS Code (GitHub Copilot Chat) VS Code's MCP support lives in `settings.json` under `mcp.servers`: ```json { "mcp.servers": { "vertexsms": { "url": "https://mcp.vertexsms.com/mcp", "headers": { "Authorization": "Bearer YOUR_VERTEXSMS_TOKEN" } } } } ``` Reload the window — the tools are then available to Copilot Chat in agent mode. ## Claude.ai (web) For users on Claude paid plans, MCP servers can be added in **Settings → Connectors**. Choose *"Add custom connector"*, paste the server URL, and select OAuth (recommended) or API key. If you choose OAuth, you are redirected to the VertexSMS dashboard to approve the connection — no token paste required. See Authentication → OAuth for details. ## Smoke test Ask the assistant a free, read-only question: ``` "What is the SMS rate to Lithuania?" ``` The assistant should call `get_sms_rates` with country `LT` and report per-operator pricing in EUR. An auth error means the bearer token is wrong; a "tool not found" means the config file did not load — recheck the path and restart the client. --- # MCP server — Authentication Source: https://vertexsms.com/en/mcp/authentication The MCP server supports two authentication paths. ## Bearer token (BYO) For self-hosted clients, scripts, CI pipelines, and the standard config-file flow used by Claude Desktop, Cursor, and VS Code. Supply your VertexSMS API token via the `Authorization` header on every request: ``` Authorization: Bearer YOUR_VERTEXSMS_TOKEN ``` The MCP server forwards the token to the VertexSMS API. It is never stored, logged, or shared between sessions. Tokens scoped at the API level (per-IP whitelist, per-route permissions) keep their scope when used through MCP. ### Get a token Sign in to your VertexSMS account, open **Settings → API** in the dashboard, create a token with the routes you need (typically `POST /sms` and `GET /rates`), then paste it into your MCP client's config (see Quickstart). Don't have an account yet? [Request access through the contact form](https://vertexsms.com/en/contact) — registration is invite-only. ## OAuth 2.1 (one-click connect) For desktop and cloud MCP clients that support automatic OAuth discovery (Claude.ai, Claude Desktop with custom connectors, and others), the MCP server advertises an authorization server. The user clicks "Connect VertexSMS" inside the client, gets redirected to a VertexSMS consent screen, approves the requested scopes, and the client receives an access token — no manual token paste. Discovery happens via `/.well-known/oauth-protected-resource` per [RFC 9728](https://datatracker.ietf.org/doc/html/rfc9728): ``` GET https://mcp.vertexsms.com/.well-known/oauth-protected-resource ``` ```json { "resource": "https://mcp.vertexsms.com/mcp", "authorization_servers": ["https://tool.vertexsms.com"], "bearer_methods_supported": ["header"], "scopes_supported": [ "sms:send", "sms:rates", "sender:write", "hlr:lookup", "numbers:read" ] } ``` ### Scopes The MCP server defines five scopes. The consent screen shows the user a plain-language description of each before they approve. | Scope | Description | Tools it covers | |-------|-------------|-----------------| | sms:send | Send SMS on your behalf. | send_sms | | sms:rates | Read SMS rates. | get_sms_rates | | sender:write | Register and confirm Sender IDs on your account. | register_sender_id, register_msisdn_sender, confirm_msisdn_sender | | hlr:lookup | Run HLR lookups (billable per query). | lookup_hlr | | numbers:read | Read mobile network metadata and validate phone numbers. | get_operator, get_mcc_mnc_list, get_mobile_prefixes, correct_phone_number | Granted scopes map directly to the underlying VertexSMS API permissions on the issued token. A token issued with only `sms:rates` is rejected by the API for any non-rates request — no client-side enforcement, the API is the gatekeeper. ### Revocation OAuth tokens appear in your dashboard's **Settings → API** page alongside any manually-created bearer tokens, prefixed with `oauth:access:` and `oauth:refresh:`. Delete them to revoke access; the connected MCP client sees a 401 on its next call and either re-prompts the user or fails loudly. ## Authentication errors When auth fails the MCP server responds with HTTP `401` and a structured error envelope: ```json { "error": { "code": "AUTH_REQUIRED", "message": "A VertexSMS API token is required. ...", "retryable": false, "signup_url": "https://vertexsms.com/en/contact", "signin_url": "https://vertexsms.com/en/login", "token_url": "https://tool.vertexsms.com/settings/api" } } ``` The `WWW-Authenticate` header includes the resource-metadata URL so OAuth-aware clients can auto-recover. See the full error catalog in the Errors section. --- # MCP server — Tools reference Source: https://vertexsms.com/en/mcp/tools The MCP server exposes ten tools. Each section below documents one tool: required scope, parameters, an example natural-language prompt that triggers it, and the JSON response shape. ## send_sms **Billable.** Send an SMS message to one or more recipients. Charges your account at the per-operator rate for the destination. Required scope: `sms:send` | Field | Type | Description | |-------|------|-------------| | to | string | Recipient phone number in E.164 format. Required. | | from | string | Sender ID (max 11 alphanumeric chars) or registered phone number. Required. | | message | string | Message body. Long messages are split into multi-part SMS automatically. Required. | | priority | enum | `high`, `normal`, `low`. | | scheduled | string | ISO 8601 datetime to schedule delivery. | | correctBy | string | ISO 3166-1 alpha-2 country code; auto-correct the recipient number for that country. | | coding | int | `0` = GSM-7, `1` = 8-bit, `2` = UCS-2. | | expireIn | int | Message expiry in seconds (360 – 432000). | Example prompt: `"Send 'Your verification code is 4815' from VERTEXSMS to +37069555555."` Example response: ```json { "message_id": "abc-123-...", "status": "sent", "parts": 1, "destination": "+37069555555" } ``` Tool-specific errors: `VERTEX_SEND_FAILED` for rejected messages (bad sender, blacklisted number, etc.). The `vertex_error_code` field on the envelope often disambiguates — cross-reference with the REST API errors. ## get_sms_rates Look up per-operator SMS rate for a country. Read-only. Server-side cached for one hour. Required scope: `sms:rates` | Field | Type | Description | |-------|------|-------------| | country | string | ISO 3166-1 alpha-2 code, e.g. `LT`, `US`, `DE`. Required. | Example prompt: `"What does it cost to send an SMS to Lithuania?"` Example response: ```json { "country": "LT", "country_name": "Lithuania", "rates": [ { "operator": "BITE", "network": "Bite", "rate_eur": "0.045", "mcc": "246", "mnc": "020" }, { "operator": "Telia", "network": "Telia", "rate_eur": "0.045", "mcc": "246", "mnc": "010" } ], "cache_age_seconds": 412 } ``` ## correct_phone_number Validate and normalize phone numbers to E.164. Classifies each as mobile, landline, or unknown. Read-only. Up to 100 numbers per call. Required scope: `numbers:read` | Field | Type | Description | |-------|------|-------------| | numbers | array | Array of `{ number, country }` objects. `country` is ISO 3166-1 alpha-2. Required. | Example prompt: `"Validate these numbers as Lithuanian: 861860698, (370)-618-60698, 6186 0698."` Example response: ```json { "count": 3, "results": [ { "input_number": "861860698", "country": "LT", "number_type": "mobile", "mobile": true, "number_e164": "+37061860698", "error": null }, { "input_number": "(370)-618-60698", "country": "LT", "number_type": "mobile", "mobile": true, "number_e164": "+37061860698", "error": null } ] } ``` ## get_operator Look up an operator by its internal VertexSMS operator ID. Returns name, country, MCC, and the list of MNCs. Read-only. Required scope: `numbers:read` | Field | Type | Description | |-------|------|-------------| | operator_id | string \| int | Internal VertexSMS operator identifier (e.g. `493`). Required. | Example prompt: `"Which operator does VertexSMS ID 493 correspond to?"` Example response: ```json { "operator_id": 493, "name": "BITE", "country": "LT", "mcc": "246", "mnc": ["020", "028"] } ``` ## get_mcc_mnc_list List MCC/MNC entries for a country with their VertexSMS operator IDs. Read-only. Paginated. Required scope: `numbers:read` | Field | Type | Description | |-------|------|-------------| | country | string | ISO 3166-1 alpha-2 country code. Required. | | page | int | Optional 1-based page number. | Example prompt: `"List the mobile networks in Lithuania."` Example response: ```json { "country": "LT", "page": 1, "count": 2, "entries": [ { "country": "LT", "mcc": "246", "mnc": "01", "operator_id": "1891" }, { "country": "LT", "mcc": "246", "mnc": "02", "operator_id": "493" } ] } ``` ## get_mobile_prefixes List mobile number prefixes for a country, mapped to VertexSMS operator IDs. Read-only. Required scope: `numbers:read` | Field | Type | Description | |-------|------|-------------| | country | string | ISO 3166-1 alpha-2 country code. Required. | Example prompt: `"Which operator owns Lithuanian numbers starting with 3706000?"` Example response: ```json { "country": "LT", "count": 2, "prefixes": [ { "prefix": "3706000", "country": "LT", "operator_id": "2536" }, { "prefix": "3706001", "country": "LT", "operator_id": "2536" } ] } ``` ## lookup_hlr **Billable.** Synchronous Home Location Register lookup. Returns operator, country, MCC/MNC, IMSI, and ported information for a phone number. Charged per query whether the result is "found" or "unknown." Required scope: `hlr:lookup` | Field | Type | Description | |-------|------|-------------| | msisdn | string | International subscriber number, e.g. `37069912345`. Required. | Example prompt: `"Run an HLR lookup on +37069912345."` Example response: ```json { "msisdn": "37069912345", "id": "1203877133", "error_code": "0", "imsi": "246021005160001", "country": "LT", "mcc": "246", "mnc": "021", "operator_id": null, "ported": null } ``` ## register_sender_id Submit an alphanumeric Sender ID for VertexSMS approval. Goes through manual human review and may take several business days. Status updates can be received via the optional notification webhook. Required scope: `sender:write` | Field | Type | Description | |-------|------|-------------| | name | string | Sender name, 3–11 alphanumeric characters. Required. | | category | enum | One of `Company`, `Product`, `Brand`, `Shortcode`, `Landline`, `Other`. Required. | | category_description | string | Description / comments shown to the reviewer. Required. | | notification_url | string | Optional webhook URL for status-change notifications. | Example prompt: `"Register 'ACMECORP' as a brand sender for our outgoing notifications."` Example response: ```json { "sender_id": "1234", "status": "submitted" } ``` ## register_msisdn_sender Register a mobile number as a Sender ID. VertexSMS sends a 5-digit PIN via SMS to the number; you must follow up with `confirm_msisdn_sender` to complete registration. Required scope: `sender:write` | Field | Type | Description | |-------|------|-------------| | msisdn | string | Mobile number in E.164 format without leading `+`, e.g. `37069555555`. Required. | Example prompt: `"Register +37069555555 as a sender."` Example response: ```json { "sender_id": "5678", "status": "pending_confirmation", "next_step": "Call confirm_msisdn_sender with the 5-digit PIN delivered via SMS." } ``` ## confirm_msisdn_sender Confirm a pending MSISDN Sender ID by submitting the 5-digit PIN sent to the registered phone number. Required scope: `sender:write` | Field | Type | Description | |-------|------|-------------| | sender_id | string | Sender ID returned by `register_msisdn_sender`. Required. | | code | string | 5-digit PIN from the verification SMS. Required. | Example prompt: `"Confirm sender 5678 with PIN 12345."` Example response: ```json { "sender_id": "5678", "status": "confirmed" } ``` --- # MCP server — Errors Source: https://vertexsms.com/en/mcp/errors Every MCP tool that fails returns a uniform error envelope. The shape is identical regardless of which tool fired or whether the failure was local validation, an upstream API error, or a transient outage. ## Envelope ```json { "error": { "code": "AUTH_INVALID", "message": "VertexSMS rejected the provided token.", "retryable": false, "signup_url": "https://vertexsms.com/en/contact", "signin_url": "https://vertexsms.com/en/login", "token_url": "https://tool.vertexsms.com/settings/api", "vertex_error_code": null } } ``` | Field | Type | Description | |-------|------|-------------| | code | string | Stable machine-readable code (see catalog below). | | message | string | Human-readable description suitable for showing to the end user. | | retryable | bool | Whether the same call may succeed if retried later. Transient failures are retryable; auth or input errors are not. | | signup_url | string | Present on auth errors. Where a user without an account should request access. | | signin_url | string | Present on auth errors. Where an existing user should sign in to refresh their token. | | token_url | string | Present on auth errors. The dashboard page for managing API tokens. | | vertex_error_code | int \| null | The numeric error code surfaced by the underlying VertexSMS REST API, if any. | ## Error codes | Code | Retryable | When it fires & how to recover | |------|-----------|--------------------------------| | AUTH_REQUIRED | no | No `Authorization` header was present. The `WWW-Authenticate` response header includes a `resource_metadata=...` URL that OAuth-capable clients can use to start a fresh consent flow. Manual recovery: paste a token via your client's MCP config. | | AUTH_INVALID | no | Token rejected by VertexSMS — expired, revoked, IP-restricted, or scope-restricted. Recover by signing in to the dashboard, regenerating the token, and updating your client config. OAuth clients should re-trigger the consent flow. | | RATE_LIMITED | yes | Per-IP rate limit on unauthenticated requests was exceeded (typically 20 / minute). Authenticated requests are not rate-limited at the MCP layer. Recover by waiting; honor the `Retry-After` header. | | INVALID_INPUT | no | Tool arguments failed schema validation locally before any upstream call. Read `message` for the specific field; fix and resubmit. | | VERTEX_SEND_FAILED | no | VertexSMS rejected the request with a 4xx (other than 401/403). Common reasons: malformed phone number, sender not approved for the destination country, blacklisted destination. `vertex_error_code` often disambiguates — cross-reference with REST API errors. | | VERTEX_UNAVAILABLE | yes | Network failure or 5xx from VertexSMS. Wait a few seconds and retry. If it persists, contact support. | | RATES_UNAVAILABLE | yes | Specific to `get_sms_rates` when the rate cache cannot be refreshed. Treat as transient. | | NOT_FOUND | no | Returned when an entity referenced by the tool call (operator ID, sender ID) does not exist on the underlying account. | The error envelope is intentionally identical to the one used by the REST API, so existing client code that handles `error_uri` / `retryable` already works.