API de verificación por SMS

La API de verificación por SMS son tres llamadas: compra un número, espera el código y libera el número. Llega a 517 servicios en 225 países, los números arrancan en 0,07 € y una activación que no recibe nada se reembolsa sin abrir ningún ticket. Las claves llevan scopes, las compras son idempotentes y los clientes antiguos de handler_api siguen funcionando sin tocar nada.

La API en un bloque

Actualizado el 28 ago 2026
URL base
https://virtualsmsnumbers.com/api/v1
Autenticación
Clave bearer o X-Api-Key
Límite de peticiones
120/min, picos de 20/s
Ventana de idempotencia
24 horas
Reembolso automático tras
20 minutos
Activación más barata
0,07 €
Países cubiertos
225
Formato
JSON, céntimos, ISO 8601 UTC

Los precios y el stock salen del pool de operadores tal y como está ahora mismo, no de una tarifa publicada.

El flujo de tres llamadas

Todo lo demás de la referencia es opcional. Esta es la ruta completa de una verificación, y no ha cambiado desde 2019.

  1. 1

    POST /activations

    Pide un servicio, y un país si te importa cuál. La respuesta trae el número, el precio en céntimos y la marca de caducidad. Manda una Idempotency-Key para que un reintento no pueda comprar un segundo número, y un max_price_cents si quien llama es un proceso automático.

  2. 2

    GET /activations/{id}?wait=180

    Long polling. La conexión se mantiene abierta hasta que entra el mensaje o vence el tiempo de espera, así que una petición sustituye a un bucle que si no haría noventa. El estado vuelve como code_received, con el código ya extraído junto al texto en bruto, porque cada remitente lo formatea a su manera.

  3. 3

    POST /activations/{id}/complete

    Cierra la activación y libera la línea. Si no llegó nada, no hagas nada: la ventana caduca sola y el saldo se abona de vuelta. Cancelar antes de tiempo es la misma llamada con otro nombre.

Un ejemplo que funciona

Define VSN_KEY y ejecútalo. Las respuestas comentadas son las formas reales, incluidos los campos que vas a querer guardar.

buy-and-wait.sh
# 1. Buy a Telegram number in Portugal
-kw">curl -X POST https://virtualsmsnumbers.com/api/v1/activations \
  -H "Authorization: Bearer $VSN_KEY" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{"service":"telegram","country":"PT"}'

# {"id":"1043872915","phone_number":"351926114508","status":"waiting",
#  "price_cents":11,"expires_at":"2026-08-26T12:41:07Z"}

# 2. Long-poll until the code lands (blocks up to 120 s)
-kw">curl "https://virtualsmsnumbers.com/api/v1/activations/1043872915?wait=120" \
  -H "Authorization: Bearer $VSN_KEY"

# {"id":"1043872915","status":"code_received",
#  "messages":[{"code":"48219","text":"Telegram code: 48219"}]}

# 3. Release the number
-kw">curl -X POST https://virtualsmsnumbers.com/api/v1/activations/1043872915/complete \
  -H "Authorization: Bearer $VSN_KEY"

Límites de peticiones

120 peticiones por minuto y clave, con picos de 20 por segundo. Cada respuesta lleva X-RateLimit-Limit, X-RateLimit-Remaining y X-RateLimit-Reset, y un 429 te dice cuánto esperar en lugar de dejarte adivinar.

El límite rara vez es la restricción si la API se usa como está pensada: un long poll en lugar de noventa consultas, un webhook en lugar de un temporizador y las listas de países y servicios cacheadas al arrancar. Si de verdad necesitas más margen, pídelo: subir un límite es más fácil para los dos que depurar una flota de claves.

Idempotencia

Manda una cabecera Idempotency-Key en POST /activations. Repetir la misma clave dentro de 24 horas devuelve la activación original tal y como está ahora, con una cabecera Idempotent-Replay, en lugar de comprar un segundo número y cobrarte dos veces.

La clave no es un hash del cuerpo: un contenido distinto bajo una clave ya usada sigue devolviendo la primera activación. Genera una clave por compra lógica —un UUID sirve— y reutilízala entre reintentos, nunca entre compras.

Clientes antiguos de handler_api

Los scripts escritos para el protocolo clásico handler_api.php siguen funcionando. Apúntalos al endpoint de compatibilidad, cambia la api_key y las mismas acciones devuelven los mismos tokens ACCESS_ y STATUS_ de siempre.

Es una capa de traducción sobre el mismo pool, así que los precios, el stock y los reembolsos se comportan igual por las dos vías. El código nuevo debería usar igualmente /api/v1: las respuestas JSON llevan marcas de tiempo, códigos de error y campos de precio para los que el formato de tokens no tiene sitio.

legacy-compat.sh
# Existing scripts keep working: same actions, same response tokens.
BASE="https://virtualsmsnumbers.com/stubs/handler_api.php"

-kw">curl "$BASE?api_key=$KEY&action=getNumber&service=tg&country=117"
# ACCESS_NUMBER:1043872915:351926114508

-kw">curl "$BASE?api_key=$KEY&action=getStatus&id=1043872915"
# STATUS_WAIT_CODE
# STATUS_OK:48219

-kw">curl "$BASE?api_key=$KEY&action=setStatus&id=1043872915&status=6"
# ACCESS_ACTIVATION

-kw">curl "$BASE?api_key=$KEY&action=getBalance"
# ACCESS_BALANCE:41.87

Agentes, MCP y descubrimiento

Hay un servidor MCP alojado, un documento OpenAPI 3.1 y un índice llms.txt, así que un agente puede descubrir las tres herramientas que necesita sin pegamento escrito a mano. Apunta tu cliente al endpoint de abajo y encontrará comprar, esperar y liberar.

Antes de dejar que algo autónomo gaste del saldo: limita la clave a numbers:read y numbers:write, pon un techo max_price_cents en cada compra y dale su propia clave, para que revocarla no tumbe tu integración de producción.

mcp.json
{
  "mcpServers": {
    "virtualsmsnumbers": {
      "type": "http",
      "url": "https://virtualsmsnumbers.com/api/mcp",
      "headers": { "Authorization": "Bearer vsn_live_xxxxxxxxxxxx" }
    }
  }
}

Antes de pasar a producción

  • Pon max_price_cents en cada compra. Los precios se mueven con el pool, y un agente sin límite comprará tan contento por el extremo caro.
  • Trata los identificadores como cadenas opacas. Los id de activación hoy tienen diez dígitos; eso no es una promesa, y su longitud tampoco.
  • Ramifica por el código de error, nunca por el mensaje. Los códigos son estables dentro de una versión; los mensajes están escritos para personas y se reescriben.
  • Suscríbete a sms.received y verifica la firma —HMAC-SHA256 sobre el cuerpo bruto, con una ventana de repetición de cinco minutos— en lugar de consultar un estado que te pueden contar.
  • Haz las cuentas con los campos enteros en céntimos. Las cadenas formateadas que tienen al lado son para mostrar y dependen del idioma.

La referencia completa

Seis endpoints, tablas de errores, cargas de webhook, scopes y el mapa de tokens antiguos.

Preguntas frecuentes

La entrega mediana es de menos de nueve segundos desde que el servicio lo manda. El long polling existe porque la cola es larga: la activación sigue abierta 20 minutos y caduca en un reembolso si no llega nada.

Nada que tengas que gestionar. La ventana se cierra, el saldo se abona de vuelta solo y la activación termina en un estado caducado que puedes leer desde la API.

Sí, y no cuesta nada. Las claves llevan scopes fijos, una lista de IP opcional y una caducidad elegida al crearlas, así que una clave de pruebas filtrada no puede comprar números en producción.

Hay envoltorios ligeros y sin dependencias, pero la API son seis endpoints sobre JSON: fetch, requests o curl bastan de sobra para el flujo de tres llamadas.

En una misma activación, sí: los mensajes extra llegan al mismo número mientras siga abierta. Entre sesiones necesitas un alquiler, que retiene la línea de cuatro horas a doce meses.

No. Es el mismo pool a los mismos precios; lo único que cambia es la codificación de la respuesta.