Sign inGet Started

Invio di email

POST /v1/email/messages invia una singola email. Fornisci un mittente, i destinatari e il contenuto in un payload JSON. L'API restituisce 202 Accepted con un ID messaggio, poi consegna l'email in modo asincrono. Consulta il reference di API per gli schemi completi.

Un invio minimale

Il payload valido più piccolo è un from, almeno un destinatario to, un subject e un corpo (html, text o entrambi). L'indirizzo from deve trovarsi su un dominio che hai verificato in questo spazio di lavoro oppure sul dominio di onboarding.
const msg = await bird.email.send({
  from: { email: "onboarding@messagebird.dev", name: "Bird" },
  to: ["delivered@messagebird.dev"],
  subject: "Hello from Bird",
  html: "<p>My first Bird email.</p>",
});
console.log(msg.id, msg.status); // "em_…", "accepted"
Usa il tuo host regionale (https://us1.platform.bird.com o https://eu1.platform.bird.com) con una chiave bk_{region}_... corrispondente.
L'esempio di invio usa delivered@messagebird.dev, un indirizzo sandbox che accetta sempre la posta. L'API rifiuta i domini segnaposto con un 422: example.com, example.net, example.org, example.edu, test.com e qualsiasi dominio sotto i TLD riservati .test, .example, .invalid o .localhost. Un invio a questi domini può solo rimbalzare, il che danneggia la tua reputazione di mittente.

Invio prima della verifica di un dominio

Durante l'onboarding puoi inviare dal nostro dominio di onboarding condiviso, onboarding@messagebird.dev. Questi invii saltano il controllo del dominio, ma raggiungono solo i membri verificati del tuo spazio di lavoro e gli indirizzi sandbox, con un limite giornaliero di destinatari. Il quickstart contiene le regole e i limiti esatti.

Costruzione del payload

Destinatari

to, cc e bcc accettano ciascuno fino a 50 indirizzi, e to ne richiede almeno uno. Ogni voce è una stringa email semplice, una stringa mailbox RFC 5322 (Jane <jane@acme.com>) o un oggetto con un display name opzionale.
I destinatari presenti nella lista di soppressione dello spazio di lavoro non causano un errore della richiesta. Viene comunque restituito un 202, e ogni destinatario soppresso appare sugli endpoint di lettura come status: rejected con la motivazione recipient_suppressed, anche quando si tratta di tutti i destinatari dell'invio.

Contenuto

subject è obbligatorio per gli invii inline, fino a 998 caratteri. Fornisci html, text o entrambi, ciascuno fino a 524.288 caratteri. Invia entrambi quando possibile: un client che non riesce a renderizzare l'HTML usa la parte di testo come fallback.
Per personalizzare il contenuto inline, inserisci token {{ variable }} nell'oggetto o nel corpo e passa i relativi valori in parameters, fino a 16 KB serializzati. Un unico set di valori copre tutti i destinatari dell'invio, e un token senza chiave corrispondente viene renderizzato vuoto. Per contenuti da riutilizzare, invia un template.
Includi parameters, anche come oggetto vuoto ({}), per elaborare l'oggetto e il corpo come Liquid. Omettilo per inviare token come {{ animal }} esattamente come scritti. Ogni nome di parametro è una singola parola, ad esempio first_name; i nomi con punto e il nome riservato bird vengono rifiutati. Sintassi Liquid non valida e tag o filtri non supportati restituiscono 422.
I valori inseriti nell'HTML vengono sottoposti a escape, così non possono alterare il markup circostante. Per un link completo o l'URL di un'immagine, usa {{ link }} senza url_encode. Per un valore all'interno della query di un URL, codifica quel valore esplicitamente, ad esempio https://example.com/search?q={{ query | url_encode }}.

Reply-to e header personalizzati

reply_to accetta da 1 a 25 indirizzi, negli stessi formati dei destinatari. Ogni risposta del destinatario viene inviata a tutti, quindi uno o due è la prassi.
headers è un oggetto stringa-stringa per i tuoi header personalizzati, ad esempio {"X-Campaign": "spring-2026"}, con un massimo di 25 header e valori fino a 998 caratteri. Tre tipi di header vengono restituiti come 422:
  • Header di indirizzamento e di piattaforma. Imposta l'indirizzamento del messaggio tramite i campi dedicati (from, to, cc, bcc, reply_to, subject). Quei nomi, e gli header che generiamo per te (Content-Type, Content-Transfer-Encoding, DKIM-Signature, Received, Return-Path), non possono essere impostati qui.
  • List-Unsubscribe e List-Unsubscribe-Post su un invio marketing. Impostiamo noi un header di disiscrizione con un clic conforme. Su un invio transactional lasciamo i tuoi esattamente come li imposti.
  • Qualsiasi valore con un ritorno a capo o un avanzamento riga.

Tracciamento

track_opens e track_clicks hanno entrambi il valore predefinito true. Imposta uno dei due a false per saltare l'iniezione del pixel di apertura o la riscrittura dei link su questo invio. Tracciamento e metriche descrive cosa ciascuno modifica nel messaggio.

Categoria e pool di IP

category classifica il contenuto e imposta la policy di soppressione: marketing blocca la consegna per qualsiasi motivo di soppressione e per qualsiasi opt-out, mentre transactional consegna nonostante una soppressione per reclamo o un opt-out solo marketing (un opt-out registrato per tutti i messaggi lo blocca comunque). Il valore predefinito è la categoria del template su un invio con template e marketing altrimenti, quindi imposta transactional esplicitamente per ricevute, reset di password e altra posta operativa. Categorie tratta la scelta. La posta inviata tramite SMTP prende la categoria dalla configurazione SMTP della chiave.
ip_pool_id seleziona il pool di invio: un ID pool (ipp_...), oppure ipp_shared per instradare esplicitamente attraverso il pool condiviso. Omettilo per usare il pool predefinito della tua organizzazione. Un pool sconosciuto, o uno senza IP dedicati disponibili per l'invio, viene rifiutato con un 422.

Riferimento dei campi

CampoTipoObbligatorioLimiti e note
fromaddresssìDeve trovarsi su un dominio verificato o sul dominio di onboarding
toaddress[]sìDa 1 a 50
cc, bccaddress[]noFino a 50 ciascuno
subjectstringinvii inlineFino a 998 caratteri; omettere negli invii con template
html, textstringalmeno unoFino a 524.288 caratteri ciascuno; omettere negli invii con template
reply_toaddress[]noDa 1 a 25; le risposte raggiungono tutti gli indirizzi elencati
headersobject (string → string)noFino a 25; nomi riservati rifiutati (vedi header personalizzati)
parametersobjectnoValori per {{ tokens }} nel contenuto inline; fino a 16 KB serializzati; condivisi tra i destinatari
tags{name, value}[]noFino a 20; nome ≤ 32 caratteri, valore ≤ 64 caratteri; solo [A-Za-z0-9_-]; nomi univoci per invio
metadataobjectnoJSON arbitrari, fino a 2 KB serializzati
track_opensbooleannoPredefinito true
track_clicksbooleannoPredefinito true
categorystringnomarketing o transactional; predefinito quello del template su un invio con template, altrimenti marketing
ip_pool_idstringnoipp_... o ipp_shared; omettere per il pool predefinito della tua organizzazione
templateobjectnoInvia un template pubblicato per id o slug, con parameters per le sue variabili e un language opzionale
attachmentsobject[]noFino a 20; vedi allegati
scheduled_atRFC 3339 timestampnoProgramma l'invio di contenuto inline o di un template; vedi invio programmato

Invio con un template

Anziché contenuto inline, invia un template pubblicato: imposta template su un oggetto che lo identifica per id (emt_...) o per slug, esattamente uno dei due, con i valori delle variabili in template.parameters. Ometti subject, html e text, perché il template li contiene già.
const msg = await bird.email.send({
  from: { email: "onboarding@messagebird.dev", name: "Bird" },
  to: ["delivered@messagebird.dev"],
  category: "transactional",
  template: {
    slug: "welcome-email",
    parameters: { first_name: "Jane" },
  },
});
console.log(msg.id, msg.status);
Il contenuto di un template è Liquid, quindi oltre alla semplice sostituzione {{ variable }} può usare filtri, condizionali {% if %} e cicli {% for %}. Personalizzazione con variabili elenca i pochi costrutti rifiutati alla pubblicazione. template.parameters è dove inserisci i valori per i parametri del template, indicizzati per nome. Omettine uno e l'invio viene rifiutato con un 422 che lo indica. Tutto il resto dell'invio si comporta come nell'invio inline, inclusi destinatari, tags, metadata, tracciamento e allegati. Cosa è specifico di un invio con template:
  • Inline o con template, mai entrambi. Inviare template insieme a subject, html o text viene rifiutato con un 422. L'API rifiuta anche i valori delle variabili nel campo di primo livello parameters; in un invio con template vanno in template.parameters.
  • bird è l'unico nome riservato. Un percorso placeholder che inizia con bird. identifica dati nostri, come il link di disiscrizione o il record del contatto del destinatario, quindi una chiave template.parameters non può chiamarsi bird. Tutte le altre chiavi sono definibili da te, e ognuna è una singola parola: {"order_number": "A-1043"} riempie {{ order_number }}.
  • Un template può essere inviato subito o in un secondo momento. Aggiungi scheduled_at per programmare l'invio. Al momento dell'accettazione fissiamo la versione pubblicata, la lingua selezionata e i valori dei parametri. Se elimini il template prima dell'orario di invio, il messaggio viene rifiutato con generation_failure.
  • Un invio usa la versione pubblicata del template. Le bozze non vengono mai inviate. Un template sconosciuto viene rifiutato con un 404, e un template senza versione pubblicata con un 422.
  • language seleziona una delle lingue del template. Omettilo per inviare la lingua predefinita del template. Chiedi una lingua che il template non ha, e la sua impostazione on_missing_language decide se viene inviata la corrispondenza più vicina o se l'invio viene rifiutato. Un template che imposta language_source_required rifiuta un invio che non specifica alcuna lingua.
  • La categoria del template è un valore predefinito, e la tua lo sovrascrive. Ometti category e l'invio eredita quella del template, quindi un template transazionale non ha bisogno di ripeterla a ogni chiamata.
Template email tratta la creazione, la pubblicazione e i costrutti che un template può contenere.

Tag e metadati a confronto

Entrambi associano dati tuoi a un invio, e differiscono nel modo in cui li interroghi successivamente:
  • I tags sono coppie {name, value} strutturate: fino a 20 per invio, nome fino a 32 caratteri, valore fino a 64, solo lettere ASCII, cifre, underscore e trattino, e nomi univoci all'interno dell'invio. I tag sono dimensioni di filtro, quindi puoi filtrare l'elenco messaggi per tag e segmentare analytics e aggregazioni dashboard per tag. Usali per etichette a bassa cardinalità come campaign, experiment_variant o source.
  • I metadata sono un oggetto JSON arbitrario, fino a 2 KB serializzati. Li conserviamo, li restituiamo nelle letture API e li includiamo in ogni evento webhook, quindi sono adatti a contesti che vuoi ricevere indietro: ID interni, chiavi esterne, payload strutturati.
Ogni evento webhook include entrambi insieme agli ID di correlazione (email_id, recipient_id), così puoi riconciliare con i tuoi record senza una seconda lookup. I nomi dei tag e le chiavi di metadati di primo livello che iniziano con __bird vengono rifiutati. Non è necessario codificare dispositivo, area geografica, provider di casella, tipo di bounce o dominio del destinatario in nessuno dei due campi, perché ciascuno di questi viene già catturato come dimensione di analytics.
Esempio di codice
{
  "tags": [{ "name": "campaign", "value": "onboarding" }],
  "metadata": { "user_id": "usr_12345", "order_id": "ord_98765" }
}

Allegati

attachments accetta fino a 20 file per messaggio, come byte codificati in base64 inline. Rifiutiamo un invio la cui dimensione stimata del messaggio generato supera 20 MB, misurata dopo la codifica base64, quindi mantieni il contenuto grezzo degli allegati a 15 MB o meno per avere margine. Allegati contiene il contratto dei campi, le immagini inline, i tipi di file bloccati e come scaricare un allegato.

Cosa significa un 202

Un invio riuscito restituisce 202 Accepted con un ID messaggio prefissato da em_ e status: accepted:
Esempio di codice
{
  "id": "em_01ky7ma8y2es1s2akzk53tmjn0",
  "status": "accepted",
  "category": "marketing",
  "from": { "email": "hello@yourdomain.com" },
  "to": [{ "email": "delivered@messagebird.dev" }],
  "subject": "Hello from Bird",
  "accepted_count": 1,
  "processed_count": 0,
  "delivered_count": 0,
  "deferred_count": 0,
  "bounced_count": 0,
  "complained_count": 0,
  "rejected_count": 0,
  "open_count": 0,
  "click_count": 0,
  "track_opens": true,
  "track_clicks": true,
  "created_at": "2026-07-23T13:58:20.866Z"
}
Il 202 significa che l'invio è stato accettato in modo durevole. Gli errori che puoi correggere tornano sulla richiesta stessa come 422: un dominio mittente non verificato o un campo non valido. Gli esiti per destinatario (consegnato, respinto, differito, segnalato) arrivano successivamente tramite i webhook e gli endpoint di lettura del messaggio.
Da questo derivano due conseguenze:
  • Le letture restituiscono lo stato senza il corpo. GET /v1/email/messages/{message_id} restituisce lo stato del messaggio e dei destinatari, mai il corpo html o text. Quando l'archiviazione dei contenuti è abilitata per lo spazio di lavoro, i corpi archiviati restano disponibili fino a 30 giorni da GET /v1/email/messages/{message_id}/content.
  • Una lettura può seguire brevemente l'invio. Un 404 sugli endpoint di lettura subito dopo un 202 significa che il messaggio non è ancora visibile: riprova dopo un momento.

Riprovare in sicurezza

Invia un header Idempotency-Key con un valore univoco per ogni invio logico. Se una richiesta è riuscita ma non hai mai visto la risposta, ripetila con la stessa chiave. L'API restituisce il risultato originale invece di inviare una seconda email e include un header Idempotency-Replay. Idempotenza contiene il formato della chiave e la durata di conservazione.

Invio in batch

Per ridurre le richieste API, POST /v1/email/batches accetta fino a 100 messaggi indipendenti e li valida come un'unica unità. Anche chiamare l'endpoint di invio singolo in un ciclo è supportato. Ogni elemento del batch usa il payload descritto in questa pagina, scheduled_at incluso, quindi un singolo batch può combinare messaggi immediati e programmati.

Fatturazione

Gli invii email vengono conteggiati per destinatario a fronte della quota mensile del tuo piano, quindi un messaggio a tre destinatari consuma tre invii. Fatturazione e utilizzo descrive il modello di conteggio e la lettura dell'utilizzo in tempo reale.

Prossimi passi