API di verifica SMS

L'API di verifica SMS sono tre chiamate: compra un numero, aspetta il codice, rilascia il numero. Raggiunge 517 servizi in 225 paesi, i numeri partono da 0,07 € e un'attivazione che non riceve nulla viene rimborsata senza aprire un ticket. Le chiavi hanno scope, gli acquisti sono idempotenti e i client handler_api legacy funzionano senza modifiche.

L'API in un blocco solo

Aggiornato il 28 ago 2026
URL di base
https://virtualsmsnumbers.com/api/v1
Autenticazione
Chiave bearer, oppure X-Api-Key
Rate limit
120/min, picco 20/s
Finestra di idempotenza
24 ore
Rimborso automatico dopo
20 minuti
Attivazione più economica
0,07 €
Paesi coperti
225
Formato
JSON, centesimi, ISO 8601 UTC

Prezzi e disponibilità arrivano dal pool degli operatori così com'è adesso, non da un listino pubblicato.

Il flusso a tre chiamate

Tutto il resto nella documentazione è facoltativo. Questo è l'intero percorso di verifica, e non cambia dal 2019.

  1. 1

    POST /activations

    Chiedi un servizio, e un paese se ti interessa quale. La risposta porta il numero, il prezzo in centesimi e il timestamp di scadenza. Manda un Idempotency-Key perché una richiesta ripetuta non possa comprare un secondo numero, e un max_price_cents se il chiamante è automatico.

  2. 2

    GET /activations/{id}?wait=180

    Long poll. La connessione resta aperta finché il messaggio non arriva o non scade il timeout, così una sola richiesta sostituisce un ciclo che altrimenti ne farebbe novanta. Lo stato torna come code_received con il codice estratto accanto al testo grezzo, perché i mittenti lo formattano in modi diversi.

  3. 3

    POST /activations/{id}/complete

    Chiudi l'attivazione e rilascia la linea. Se non è arrivato nulla, non fare niente: la finestra scade da sola e il saldo viene riaccreditato. Annullare in anticipo è la stessa chiamata con un altro nome.

Un esempio funzionante

Imposta VSN_KEY ed esegui. Le risposte nei commenti sono le forme reali, compresi i campi che vorrai salvare.

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"

Rate limit

120 richieste al minuto per chiave, con picchi fino a 20 al secondo. Ogni risposta porta X-RateLimit-Limit, X-RateLimit-Remaining e X-RateLimit-Reset, e un 429 ti dice quanto aspettare invece di farti tirare a indovinare.

Il limite è raramente il vincolo se l'API è usata come previsto: un long poll invece di novanta interrogazioni, un webhook invece di un timer, e le liste di paesi e servizi messe in cache all'avvio. Se ti serve davvero più margine, chiedilo: alzare un limite è più semplice, per entrambi, che fare il debug di una flotta di chiavi.

Idempotenza

Manda un header Idempotency-Key su POST /activations. Ripetere la stessa chiave entro 24 ore restituisce l'attivazione originale nello stato attuale, con un header Idempotent-Replay, invece di comprare un secondo numero e addebitarti due volte.

La chiave non è un hash del corpo: un payload diverso con una chiave già usata restituisce comunque la prima attivazione. Genera una chiave per ogni acquisto logico — un UUID va benissimo — e riusala tra i tentativi, mai tra acquisti diversi.

Client handler_api legacy

Gli script scritti per il classico protocollo handler_api.php continuano a funzionare. Puntali all'endpoint di compatibilità, sostituisci l'api_key, e le stesse azioni restituiscono gli stessi token ACCESS_ e STATUS_ di sempre.

È uno strato di traduzione sopra lo stesso pool, quindi prezzi, scorte e rimborsi si comportano in modo identico nei due casi. Il codice nuovo dovrebbe comunque usare /api/v1: le risposte JSON portano timestamp, codici di errore e campi di prezzo per cui il formato a token non ha spazio.

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

Agenti, MCP e discovery

Ci sono un server MCP ospitato, un documento OpenAPI 3.1 e un indice llms.txt, così un agente può scoprire i tre strumenti che gli servono senza colla scritta a mano. Punta il tuo client all'endpoint qui sotto e troverà compra, attendi e rilascia.

Prima di lasciare che qualcosa di autonomo spenda dal saldo: limita la chiave a numbers:read e numbers:write, imposta un tetto max_price_cents su ogni acquisto e dagli una chiave sua, così revocarla non butta giù la tua integrazione di produzione.

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

Prima della produzione

  • Imposta max_price_cents su ogni acquisto. I prezzi si muovono con il pool, e un agente senza limiti comprerà volentieri dalla parte cara.
  • Tratta gli identificatori come stringhe opache. Gli id di attivazione oggi hanno dieci cifre; non è una promessa, e nemmeno la loro lunghezza lo è.
  • Ramifica sul codice di errore, mai sul messaggio. I codici sono stabili all'interno di una versione; i messaggi sono scritti per le persone e vengono riscritti.
  • Iscriviti a sms.received e verifica la firma — HMAC-SHA256 sul corpo grezzo, con una finestra di replay di cinque minuti — invece di interrogare uno stato che potresti farti comunicare.
  • Fai i calcoli sui campi interi in centesimi. Le stringhe formattate accanto servono alla visualizzazione e dipendono dalla lingua.

La documentazione completa

Sei endpoint, tabelle degli errori, payload dei webhook, scope e la mappa dei token legacy.

Domande frequenti

La consegna mediana è sotto i nove secondi dal momento in cui il servizio lo invia. Il long poll esiste perché la coda è lunga: l'attivazione resta aperta per 20 minuti e, se non arriva nulla, scade in un rimborso.

Niente che tu debba gestire. La finestra si chiude, il saldo viene riaccreditato in automatico e l'attivazione finisce in uno stato scaduto che puoi leggere dall'API.

Sì, e non costa nulla. Le chiavi hanno scope fissi, una allowlist IP facoltativa e una scadenza scelta alla creazione, così una chiave di staging che trapela non può comprare numeri in produzione.

Ci sono wrapper leggeri e senza dipendenze, ma l'API sono sei endpoint su JSON: fetch, requests o curl bastano davvero per il flusso a tre chiamate.

Su una singola attivazione sì: i messaggi extra arrivano sullo stesso numero finché è aperta. Tra sessioni diverse serve un noleggio, che tiene la linea da quattro ore a dodici mesi.

No. È lo stesso pool agli stessi prezzi; cambia solo la codifica della risposta.