Inviare SMS
Questa guida descrive l'endpoint per l'invio singolo, POST /v1/sms/messages. Crea un payload JSON con destinatario, mittente, corpo e categoria. Bird restituisce 202 Accepted con un ID del messaggio e consegna in modo asincrono. Ogni richiesta invia un messaggio a un destinatario. Per inviare molti messaggi insieme, usa l'invio in batch. Per inviare un template al posto del tuo testo, fornisci un oggetto template invece di text e category. I template predefiniti rifiutano from; i template dello spazio di lavoro lo richiedono.
Prima di inviare: abilita il paese di destinazione
Il tuo spazio di lavoro invia SMS solo ai paesi presenti nella sua lista di destinazioni consentite. Il paese di origine della tua organizzazione è il paese dell'indirizzo di registrazione nel suo profilo aziendale, oppure quello dell'indirizzo di fatturazione se l'indirizzo di registrazione non indica un paese. All'inizio la lista di destinazioni consentite del tuo spazio di lavoro è vuota. Ogni volta che il paese di origine viene impostato o modificato, Bird aggiunge quel paese alla lista. Bird rifiuta un invio verso un paese non presente nella lista con 422 SMSDestinationNotEnabled, prima di determinare il mittente. Abilita i paesi in cui operi in SMS > Destinations nella dashboard.
Nella stessa pagina puoi impostare un limite di spesa giornaliero per ogni paese, nella valuta del tuo wallet. Per impostarlo servono un wallet dell'organizzazione e l'accesso in lettura a quel wallet; per rimuoverlo no. Il limite si applica sia che il paese sia abilitato sia che non lo sia. Quando la spesa del giorno verso quel paese raggiunge il limite, Bird rifiuta i nuovi messaggi verso quel paese con 422 SMSDestinationDailySpendExceeded fino alla mezzanotte UTC. Vengono rifiutati anche i messaggi di verifica. La spesa viene conteggiata quando un messaggio viene addebitato, quindi i messaggi già accettati possono superare il limite per l'importo del loro costo. Una modifica a un limite impiega fino a un minuto per avere effetto sugli invii.
Un invio minimo
Il payload di testo libero valido più piccolo contiene un destinatario to, un mittente from, un corpo text e un category.
const msg = await bird.sms.send({
from: "+15557654321",
to: "+14155550100",
text: "Your verification code is 123456.",
category: "authentication",
});
console.log(msg.id, msg.status);msg = client.sms.send(
from_="+15557654321",
to="+15551234567",
text="Your verification code is 123456.",
category="authentication",
)
print(msg.id, msg.status)msg, err := client.Sms.Send(context.Background(), bird.SmsSendParams{
From: "+15557654321",
To: "+15551234567",
Text: "Your verification code is 123456.",
Category: bird.SMSCategoryAuthentication,
})
if err != nil {
log.Fatal(err)
}
fmt.Println(msg.Id, *msg.Status)$message = $bird->sms->send(
from: '+15557654321',
to: '+15551234567',
text: 'Your verification code is 123456.',
category: 'authentication',
);
echo $message->getId(), ' ', $message->getStatus();bird sms send --body-file - <<'JSON'
{
"to": "+14155550100",
"from": "+15557654321",
"text": "Your verification code is 123456.",
"category": "authentication",
"options": {
"smart_encoding": true
},
"tags": [
{
"name": "campaign",
"value": "signup"
}
],
"metadata": {
"user_id": "usr_12345"
}
}
JSONcurl -X POST https://eu1.platform.bird.com/v1/sms/messages \
-H "Authorization: Bearer bk_eu1_..." \
-H "Content-Type: application/json" \
-d '{
"to": "+31612345678",
"from": "Bird",
"text": "Your Bird verification code is 481920. It expires in 10 minutes.",
"category": "authentication"
}'Usa il tuo host regionale (https://us1.platform.bird.com o https://eu1.platform.bird.com) con una chiave bk_{region}_... corrispondente. La risposta è il messaggio accettato:
{
"id": "sms_01ky7qmwgpfkybj9ecrnwjx714",
"direction": "outbound",
"status": "accepted",
"to": "+31612345678",
"from": "Bird",
"text": "Your Bird verification code is 481920. It expires in 10 minutes.",
"category": "authentication",
"segments": { "count": 1, "encoding": "GSM_7BIT", "characters": 64 },
"cost": null,
"carrier": null,
"mcc_mnc": null,
"sent_at": null,
"delivered_at": null,
"created_at": "2026-07-23T14:56:34.326Z"
}status: accepted significa che Bird ha ricevuto il messaggio e lo sta elaborando; cost è null perché il prezzo viene calcolato durante l'elaborazione. Quello che succede dopo è descritto nel modello asincrono.
Costruire il payload
Destinatario
to è un singolo destinatario in formato E.164: un + iniziale, il prefisso internazionale e il numero dell'abbonato, ad esempio +31612345678. Ogni messaggio va a un solo destinatario, senza cc, bcc o array di destinatari. Per raggiungere più persone, invia un batch.
Mittente
from è il mittente che vede il destinatario. È obbligatorio in un invio di testo libero, a meno che messaging_profile_id indichi un profilo di messaggistica con un mittente per il paese di destinazione o un mittente predefinito. Può avere una di due forme, e quali funzionano dipende dal paese di destinazione:
- Un ID mittente alfanumerico: da 3 a 11 lettere, cifre, spazi, trattini, trattini bassi o punti, con almeno una lettera e nessun separatore all'inizio o alla fine, ad esempio
BirdoAcme-Co. Deve contenere una lettera, quindi una stringa di cifre con punteggiatura come555 555viene rifiutata. Alcuni paesi richiedono la registrazione, mentre altri, tra cui gli Stati Uniti, non supportano i mittenti alfanumerici. I destinatari non possono rispondere a questi mittenti. - Un numero di proprietà del tuo spazio di lavoro, in formato E.164 o come sole cifre. Qualsiasi
fromcomposto solo da cifre viene interpretato come numerico e cercato tra i tuoi mittenti, quindi un numero arbitrario che non possiedi viene rifiutato. Se funziona come long code, numero verde o short code dipende dal numero stesso, non da quante cifre hai scritto. Unfromdi 6 cifre non è uno short code perché ha 6 cifre: lo è se il numero che possiedi è uno short code.
Un mittente non valido per la destinazione viene rifiutato con un 422 che indica il motivo (ad esempio SMSAlphaNotSupported dove i mittenti alfanumerici non sono disponibili). In un invio con template integrato, from non è accettato: Bird sceglie un mittente in base alla destinazione e alla categoria. Un template dello spazio di lavoro richiede un tuo mittente from o un profilo di messaggistica che ne fornisca uno.
Come richiedere un ID mittente, quali requisiti impone ogni paese e come registrarlo paese per paese è spiegato in ID mittente SMS.
Per tenere in un unico posto i mittenti e le impostazioni predefinite di un programma, crea un profilo di messaggistica e indicalo in messaging_profile_id. Se ometti from, Bird invia dal mittente del profilo per il paese di destinazione o dal suo mittente predefinito. Se ometti category, viene usata la categoria predefinita del profilo, e options.smart_encoding, cost_center, validity_period e options.callback_url prendono le impostazioni del profilo. I valori impostati sul messaggio hanno la precedenza.
Corpo e categoria
text è il corpo del messaggio, di almeno un carattere. Viene fatturato e consegnato in segmenti; un invio è limitato a 12 segmenti (circa 1.836 caratteri GSM-7, o 804 se il corpo usa la codifica estesa UCS-2). Un corpo oltre il limite viene rifiutato con un 422 anziché troncato.
category è obbligatorio in un invio di testo libero, a meno che il profilo di messaggistica in messaging_profile_id imposti una categoria predefinita. Classifica il messaggio come transactional, marketing, authentication o service, e indica a Bird e agli operatori perché stai inviando. Un codice di verifica monouso usa authentication; una promozione usa marketing. Scegli la categoria che corrisponde allo scopo del messaggio.
Tag e metadati
Questi campi associano dati tuoi a un invio, ma servono a scopi diversi:
tagssono coppie strutturate{name, value}(massimo 20 per invio; nome da 1 a 32 caratteri, valore da 1 a 64, solo ASCII[A-Za-z0-9_-], con distinzione tra maiuscole e minuscole, nomi univoci all'interno di un invio). Sono dimensioni di filtro native: puoi filtrare l'elenco dei messaggi per tag. Usali per etichette con pochi valori distinti, comecampaignoexperiment_variant.metadataè un oggetto JSON arbitrario (massimo 2 KB serializzato). Viene memorizzato, restituito nelle letture API e riportato in ogni evento webhook, ma non è una dimensione di filtro. Usalo per il contesto che deve tornarti indietro: ID interni, chiavi esterne e qualsiasi dato che vuoi ricevere con ogni evento.referenceè una stringa da 1 a 255 caratteri con cui vuoi ritrovare il messaggio, come un numero d'ordine o di ticket.?reference=nell'elenco dei messaggi la confronta in modo esatto, distinguendo maiuscole e minuscole, e più messaggi possono condividere lo stesso valore. Viene restituita nelle letture e riportata in ogni evento webhook. Impostala solo se devi eseguire ricerche su di essa e inserisci gli altri dati inmetadata.
{
"tags": [{ "name": "campaign", "value": "spring-2026" }],
"metadata": { "user_id": "usr_12345", "order_id": "ord_98765" },
"reference": "ord_98765"
}Riferimento dei campi
| Campo | Tipo | Obbligatorio | Limiti / note |
|---|---|---|---|
to | stringa (E.164) | sì | Un destinatario per messaggio |
from | stringa | sì* | Numero E.164 di proprietà, ID mittente alfanumerico (3–11 caratteri, almeno una lettera) o short code (5–6 cifre) |
text | stringa | sì* | Almeno 1 carattere; massimo 12 segmenti |
category | stringa | sì* | transactional, marketing, authentication o service |
template | oggetto | sì* | {slug, parameters?, language?} per un template integrato o dello spazio di lavoro |
tags | {name, value}[] | no | Massimo 20; nome da 1 a 32 caratteri, valore da 1 a 64 caratteri; solo [A-Za-z0-9_-] |
metadata | oggetto | no | JSON arbitrario, massimo 2 KB serializzato |
reference | stringa | no | Da 1 a 255 caratteri; corrispondenza esatta per ?reference= nell'elenco dei messaggi |
messaging_profile_id | stringa | no | Un profilo di messaggistica che fornisce il mittente e i valori predefiniti; i valori impostati sul messaggio hanno la precedenza |
validity_period | intero | no | Da 60 a 172.800 secondi dall'accettazione; omettilo per usare il valore del profilo di messaggistica o le regole dell'operatore |
options | oggetto | no | Impostazioni di elaborazione per singolo messaggio, come smart_encoding (vedi segmenti e codifica) e callback_url (vedi URL di callback) |
* Gli invii di testo libero richiedono from, text e category, ma un profilo di messaggistica può fornire from e category. Gli invii con template richiedono template al posto di text e category (e rifiutano entrambi). I template predefiniti rifiutano from; i template dello spazio di lavoro lo richiedono.
Inviare con un template
Imposta template per inviare un template predefinito o un template pubblicato dello spazio di lavoro. La creazione di template dello spazio di lavoro è in anteprima su API. Il catalogo, le variabili e le regole sui mittenti sono descritti in Template SMS.
Segmenti e codifica
SMS viene fatturato per segmento. Un messaggio che rientra nella codifica GSM-7 dispone di 160 caratteri in un singolo segmento; con UCS-2 (attivata da emoji, caratteri CJK o altri caratteri non GSM) il limite scende a 70. I messaggi più lunghi vengono divisi in più segmenti, con limiti per segmento leggermente inferiori. Ogni risposta riporta il valore risolto di segments: il valore fatturabile di count, il valore di encoding e il numero di caratteri. I segmenti sono l'unità su cui vieni fatturato; vedi costi.
Quando l'unico motivo per cui un testo esce da GSM-7 sono i caratteri tipografici, lo smart encoding può ridurne il numero di segmenti. Imposta options.smart_encoding su true e Bird sostituirà virgolette curve, trattini, puntini di sospensione e caratteri simili con equivalenti GSM-7 prima dell'invio. È disattivato per impostazione predefinita perché modifica il testo che hai scritto.
Per il set di caratteri completo, i caratteri della tabella di estensione che occupano due posizioni, la dimensione delle emoji, le sostituzioni dello smart encoding e il calcolo dei segmenti, consulta Limiti di caratteri.
Invio in batch
POST /v1/sms/batches invia fino a 100 messaggi indipendenti in una sola richiesta, secondo lo schema di invio massivo SMS: una sola chiamata API per molti destinatari. Le richieste in batch usano la policy di limitazione delle richieste sms_batch, distinta dalla policy sms_send per gli invii singoli. Il corpo è un oggetto JSON il cui array messages contiene gli oggetti messaggio descritti in Costruire il payload:
const result = await bird.sms.sendBatch({
messages: [
{
from: "+15557654321",
to: "+15551111111",
text: "Hi Alice!",
category: "marketing",
},
{
from: "+15557654321",
to: "+15552222222",
text: "Hi Bob!",
category: "marketing",
},
],
});batch = client.sms.send_batch(
messages=[
{
"from_": "+15557654321",
"to": "+15551111111",
"text": "Hi Alice!",
"category": "marketing",
},
{
"from_": "+15557654321",
"to": "+15552222222",
"text": "Hi Bob!",
"category": "marketing",
},
]
)
for msg in batch.data:
print(msg.id, msg.status)batch, err := client.Sms.SendBatch(context.Background(), bird.SmsSendBatchParams{
Messages: []bird.SmsSendParams{
{
From: "+15557654321", To: "+15551111111",
Text: "Hi Alice!", Category: bird.SMSCategoryMarketing,
},
{
From: "+15557654321", To: "+15552222222",
Text: "Hi Bob!", Category: bird.SMSCategoryMarketing,
},
},
})
if err != nil {
log.Fatal(err)
}
for _, msg := range batch.Data {
fmt.Println(msg.Id, *msg.Status)
}$batch = $bird->sms->sendBatch(messages: [
(new SMSMessageSendRequest())
->setFrom('+15557654321')
->setTo('+15551111111')
->setText('Hi Alice!')
->setCategory('marketing'),
(new SMSMessageSendRequest())
->setFrom('+15557654321')
->setTo('+15552222222')
->setText('Hi Bob!')
->setCategory('marketing'),
]);
foreach ($batch->getData() ?? [] as $item) {
echo $item->getId(), ' ', $item->getStatus(), "\n";
}curl -X POST "https://{region}.platform.bird.com/v1/sms/batches" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"messages": [
{
"to": "+15551111111",
"from": "+15557654321",
"text": "Hi Alice!",
"category": "marketing"
},
{
"to": "+15552222222",
"from": "+15557654321",
"text": "Hi Bob!",
"category": "marketing"
}
]
}'La validazione è tutto o niente: se un qualsiasi messaggio del batch non è valido, l'intera richiesta viene rifiutata con un 422 e non viene inviato nulla, quindi un batch non viene mai applicato solo in parte. In caso di successo, la risposta 202 contiene ogni messaggio accettato nell'ordine di invio sotto data, più un summary con accepted_count. Da quel momento ogni messaggio è indipendente: il fallimento verso un destinatario non influisce mai sugli altri.
Il modello asincrono: cosa significa 202
Un invio riuscito restituisce 202 Accepted con un ID messaggio e status: accepted. Gli errori della richiesta vengono restituiti subito: un campo non valido, un corpo oltre il limite di segmenti, un paese di destinazione che non hai abilitato o un mittente non valido restituiscono un 422. Uno spazio di lavoro senza saldo nel wallet riceve un 402.
La consegna avviene in modo asincrono. Il messaggio passa a sent quando Bird lo consegna all'operatore. Una ricevuta di consegna imposta poi delivered, undelivered, failed o expired tramite eventi e webhook e gli endpoint di lettura. Questo modello ha tre conseguenze:
- Il costo viene calcolato dopo l'accettazione. Il campo
costdi un messaggio ènullal momento dell'accettazione e viene valorizzato quando Bird calcola il prezzo dell'invio durante l'elaborazione. Rileggi il messaggio, o attendi l'evento di consegna, per vedere l'addebito calcolato fino a quel momento; costi e fatturazione descrive le componenti e quando una resta senza prezzo. - Un messaggio può essere rifiutato dopo il 202. Se l'addebito non riesce durante l'elaborazione, il messaggio termina in
rejectedcon un webhooksms.rejectede non ti viene addebitato nulla; un wallet esaurito compare comelast_error.code: insufficient_balance. - Le letture possono essere brevemente in ritardo rispetto al 202. Il messaggio diventa visibile sugli endpoint di lettura poco dopo il
202, quindi un404subito dopo un invio si risolve da solo in pochi istanti.
Campi riservati
Bird rifiuta i seguenti campi della richiesta con 422 SMSUnsupportedFeature:
scheduled_at, media_urls, broadcast_id, campaign_id, audience_id, contact_id, topic_id, personalization, options.max_price_per_segment, options.track_clicks (quando true)
Non includere questi campi in un invio.
Riprovare in sicurezza
Invia l'header Idempotency-Key con un valore univoco per ogni invio logico. Se una richiesta va a buon fine senza restituire una risposta, ripeti la stessa richiesta con la stessa chiave. Bird restituisce il risultato originale invece di inviare un messaggio duplicato. Consulta idempotenza per il formato e la conservazione della chiave.
Costi e fatturazione
Gli SMS in uscita vengono fatturati per segmento. L'importo dipende dal paese di destinazione e dall'operatore; alcune rotte aggiungono un sovrapprezzo di terzi, come le tariffe degli operatori statunitensi per il 10DLC.
Il campo cost di un messaggio suddivide l'addebito in componenti con nome. transaction_amount è quanto Bird ha addebitato per trasportare il messaggio, passthrough_amount è l'eventuale tariffa di terzi riaddebitata e amount è la somma delle componenti già prezzate, espressa in currency_code. Una componente non ancora prezzata è null anziché "0.00000", quindi un messaggio il cui sovrapprezzo non è mai stato determinato riporta in amount solo il costo di trasporto. Il riferimento del messaggio documenta ogni campo.
Il sovrapprezzo viene determinato secondo il principio del best effort. Bird lo calcola mentre registra la ricevuta di consegna, entro un intervallo di tempo limitato. Se non viene determinato in quell'intervallo, passthrough_amount resta null in modo permanente: Bird non effettua un nuovo tentativo e amount resta pari al costo di trasporto.
Gli SMS in entrata vengono fatturati su due voci: la tariffa in entrata per segmento e, dove previsto, un sovrapprezzo dell'operatore in entrata. Entrambe compaiono nel campo cost del messaggio ricevuto: la tariffa come transaction_amount, il sovrapprezzo come passthrough_amount. A differenza del corrispettivo in uscita, il sovrapprezzo in entrata viene prezzato quando il messaggio viene accettato e non alla consegna, quindi non viene mai compilato in seguito.
Controlla costi e segmenti di ogni messaggio nel log di SMS.
Passaggi successivi
- Template SMS: invia un template integrato e lascia che Bird scelga il mittente.
- Log SMS: trova un messaggio ed esaminane il ciclo di vita, i segmenti e il costo.
- Eventi: ricevi gli eventi di consegna nei tuoi sistemi.
- URL di callback SMS: invia gli eventi di un singolo messaggio o di un singolo profilo a un endpoint HTTPS dedicato.
- Metriche SMS: monitora il tasso di consegna, il tasso di errore e il volume accettato.
- Idempotenza: riprova in sicurezza con l'header
Idempotency-Key. - Inviare il tuo primo SMS: un video che mostra la stessa configurazione nella dashboard
Risorse correlate
Continua con la documentazione, le guide e gli esempi per questo argomento.