Template email
Un template è un oggetto e un corpo email che salvi una volta e invii molte volte. Scrivi le parti variabili come segnaposto {{ variable }}, pubblichi il template e poi lo invii per slug invece di incollare lo stesso HTML in ogni chiamata API. Un template appartiene al tuo spazio di lavoro.
Crea e gestisci i template in Email > Templates, tramite /v1/email/templates, con il bird CLI, o tramite il server MCP. I metodi tipizzati sono disponibili negli SDK TypeScript, Python, PHP e Go sotto email.templates. Gli schemi completi di richiesta e risposta sono nel reference API. Invia un template pubblicato tramite il normale endpoint di invio.
Cosa contiene un template
Ogni template ha due nomi, e svolgono funzioni diverse:
slugè il nome con cui invii il template, ad esempiowelcome-email. Lo scegli quando crei il template e non può essere modificato in seguito. Uno slug può contenere lettere minuscole, numeri, trattini e underscore, deve iniziare e finire con una lettera o un numero e può essere lungo fino a 63 caratteri. Due prefissi sono riservati:bird_, riservato ai nostri template predefiniti, eemt_, che è il formato usato per gli ID dei template. La dashboard chiama questo campo Alias.nameè un'etichetta di visualizzazione a testo libero. Per impostazione predefinita corrisponde allo slug, e puoi modificarla in qualsiasi momento. Nessuna risoluzione avviene tramite il nome, quindi rinominare un template a scopo di visualizzazione non interrompe mai un invio.
Oltre a questi, un template ha un ID emt_ permanente, fisso per tutta la sua vita. Ha anche una category, che può essere marketing o transactional, e un source di authoring: html, markup finito che fornisci tu, opzionalmente personalizzato con Liquid. La categoria e la sorgente sono entrambe fissate quando crei il template.
Forniamo un catalogo di template predefiniti, i cui slug iniziano tutti con bird_. Un template predefinito non appartiene ad alcuno spazio di lavoro, non può essere modificato ed è sempre inviabile così com'è. Copialo nel tuo spazio di lavoro per farlo tuo: diventa un template ordinario che puoi modificare. La copia arriva come bozza non pubblicata che eredita la categoria, la sorgente e le impostazioni di lingua dell'originale, quindi pubblicala prima di inviarla.
Bozze e versioni pubblicate
Ogni template ha esattamente una bozza, che è la copia di lavoro su cui apporti le modifiche. Ha anche un numero qualsiasi di versioni pubblicate, ciascuna numerata (1, 2, 3 e così via) e mai più modificata una volta creata. Le modifiche cambiano la bozza sul posto. La pubblicazione scatta un'istantanea della bozza corrente, la trasforma nella versione numerata successiva e rende quella versione quella usata dagli invii. La bozza stessa resta modificabile, così puoi continuare a lavorare sulla prossima.
La regola che conta per l'invio è questa: un invio usa sempre la versione pubblicata del template, e una bozza non viene mai inviata da sola. Puoi continuare a modificare la bozza mentre una versione stabile continua a essere inviata, e poi pubblicare quando la modifica è pronta. Pubblicare una nuova versione cambia ciò che gli invii successivi renderizzano. Un invio già accettato non è influenzato da una pubblicazione avvenuta dopo.

Le versioni supportano altre due azioni. Scarta le modifiche della bozza per ripristinare la bozza allo stato della versione attualmente pubblicata. Oppure esegui un rollback per rendere una versione pubblicata precedente quella usata dagli invii. Puoi eseguire il rollback solo a una versione pubblicata, mai alla bozza stessa. Il rollback sostituisce la bozza con il contenuto di quella versione, quindi qualsiasi modifica non salvata nella bozza va persa, e le modifiche successive partono dalla versione a cui hai fatto rollback. Un rollback non crea una nuova versione.
Per scegliere un'immagine esistente, hai bisogno dell'accesso in lettura alla libreria multimediale dello spazio di lavoro. Per caricare, incollare o trascinare una nuova immagine, hai bisogno dell'accesso in scrittura. Se Insert image è disabilitato o non riesci a sfogliare o caricare, chiedi a un amministratore dello spazio di lavoro il permesso corrispondente per la libreria multimediale. Il solo permesso di modifica dei template non concede l'accesso alla libreria multimediale.
Nella dashboard, scegli Visual > Insert image per cercare nella libreria multimediale o caricare un'immagine PNG, JPEG, GIF o WebP statica entro i limiti di caricamento della libreria multimediale. I caricamenti di WebP statici vengono convertiti in PNG o JPEG. Seleziona l'immagine per impostarne Image description, larghezza di visualizzazione, allineamento e link. Contrassegna un'immagine come Decorative image solo quando non aggiunge informazioni; un'immagine con link ha bisogno di una descrizione che ne spieghi la destinazione. Ogni lingua mantiene le proprie descrizioni delle immagini e il proprio layout.
Usa Replace image per cambiare un'immagine selezionata mantenendone descrizione, link, larghezza e allineamento. Puoi anche incollare o trascinare un file immagine nell'editor visuale. Attendi che il caricamento finisca, o annullalo, prima di salvare o inviare un test. Controlla l'anteprima, poi apri More actions > Test email per inviare il contenuto corrente a te stesso. Code resta disponibile per modificare l'HTML.
Rimuovere un'immagine dalla libreria multimediale non la rimuove dalle email già inviate. La sostituzione di un'immagine usa un nuovo URL, quindi i messaggi precedenti continuano a mostrare l'originale.
Il salvataggio è protetto da un numero di revisione. Invia la revision che hai letto per ultima per la lingua che stai salvando. Se qualcun altro ha modificato quella lingua nel frattempo, il salvataggio viene rifiutato come conflitto anziché sovrascrivere il suo lavoro. Ometti revision per salvare incondizionatamente. La pubblicazione e il rollback usano la revision della bozza allo stesso modo.
Contenuto in più di una lingua
Un template contiene contenuto in un massimo di 25 lingue, ciascuna con il proprio oggetto e corpo, contrassegnata con un codice BCP-47 come en o pt-BR. Una lingua è quella predefinita del template. Pubblicare un template pubblica tutte le lingue che contiene contemporaneamente. Non puoi pubblicare una sola lingua, quindi devono essere tutte completate prima. Ogni lingua ha bisogno di un oggetto e di un corpo, e la lingua predefinita del template deve essere una di quelle che hai compilato. Se manca qualcosa, non viene pubblicato nulla, e l'errore ti indica cosa manca in ogni lingua così puoi correggere tutto in un solo passaggio. Non devi completare ogni lingua in anticipo: pubblica quelle pronte, e aggiungi le altre in seguito.
Una lingua ha bisogno di un corpo HTML. Puoi omettere il suo text: la pubblicazione crea automaticamente un'alternativa in testo semplice dall'HTML, così ottieni entrambe le parti senza scrivere la seconda tu stesso.
Ogni lingua può anche avere un testo di anteprima, a volte chiamato preheader: la riga che la casella di posta mostra dopo l'oggetto nell'elenco dei messaggi. È facoltativo, lungo fino a 255 caratteri, e accetta gli stessi segnaposto {{ variable }} dell'oggetto. Se lo ometti, la casella di posta ripiegherà sulla prima riga del corpo, che raramente è quella che sceglieresti. La pubblicazione rifiuta il testo di anteprima su una lingua il cui corpo non ha una parte HTML, perché un client di posta legge la riga di anteprima solo dal markup HTML nascosto, e rifiuta {{ bird.unsubscribe_url }} al suo interno per lo stesso motivo per cui l'oggetto non può contenerlo: nessuno dei due è un posto dove può andare un link.
Due impostazioni coprono un invio che non specifica una lingua per cui il template ha contenuto, e proteggono da errori diversi:
| Impostazione | Cosa controlla |
|---|---|
on_missing_language | Cosa succede quando un invio richiede una lingua che il template non ha. fallback, il valore predefinito, serve la corrispondenza più vicina. Prima prova una forma più generica della stessa lingua, così un pt memorizzato può servire una richiesta per pt-BR. Poi ripiega sulla lingua predefinita del template. fail rifiuta l'invio, per contenuti in cui inviare nella lingua sbagliata è peggio che non inviare affatto. |
language_source_required | Se un invio deve specificare una lingua. Questa impostazione è disattivata per impostazione predefinita, quindi un invio che non ne specifica nessuna riceve la lingua predefinita. Attivala e l'invio viene rifiutato. Un broadcast specifica una lingua per tutto il suo pubblico, quindi un template con questa impostazione attiva richiede che la lingua sia scelta prima che il broadcast possa partire. |
Puoi impostare le due opzioni in modo indipendente. Da solo, fail si applica solo quando un invio specifica una lingua che non abbiamo, quindi un invio senza lingua passa comunque. Attiva entrambe le impostazioni insieme quando vuoi che ogni invio specifichi una lingua intenzionalmente.
Personalizzazione con le variabili
Gli invii di template singoli, in batch e programmati possono usare i valori dei contatti. Ogni indirizzo To deve corrispondere a un contatto quando il template legge bird.contact.*.
Scrivi segnaposto {{ variable }} nell'oggetto, nel testo di anteprima e nel corpo. Li rileviamo automaticamente, combinati tra tutte le lingue, quindi non devi mai dichiararli separatamente. Il prefisso del segnaposto distingue i due tipi. Un percorso che inizia con bird. legge dai nostri dati, un record di contatto o il link di disiscrizione. Tutto il resto è un parametro a cui dai un valore quando invii.
Il nome di un parametro è una singola parola, come {{ animal }}. Un nome con punti cerca una struttura che un parametro non ha, quindi la pubblicazione lo rifiuta: scrivi il valore come parametro a sé, oppure leggi i dati del contatto con bird.contact.<attribute>.
In un invio singolo o in batch, il valore di un parametro proviene dall'oggetto template.parameters dell'invio, indicizzato per nome. Un unico set di valori copre tutti i destinatari di quell'invio. bird è l'unico nome che non puoi usare lì: una chiave template.parameters chiamata bird viene rifiutata con un 422.
Usa bird.contact.<attribute> per leggere le proprietà del contatto del destinatario, inclusi i campi predefiniti first_name, last_name e email. Gli invii singoli e in batch abbinano ogni indirizzo To a un contatto dello stesso spazio di lavoro. I destinatari in Cc e Bcc ricevono una copia dell'email personalizzata di ciascun destinatario To; non serve che abbiano contatti corrispondenti. Un broadcast legge i contatti del suo pubblico e accetta anche valori del chiamante nei parametri del template.
Hi {{ bird.contact.first_name }},Fornisci i parametri obbligatori del chiamante usati dalla lingua risolta. Un parametro obbligatorio mancante restituisce 422. Anche un valore obbligatorio null restituisce 422; una stringa vuota intenzionale resta valida. L'elenco variables della versione copre le sue lingue, quindi un parametro usato solo da un'altra lingua non ha bisogno di un valore per questo invio.
La pubblicazione registra gli attributi del contatto usati da ciascuna lingua. L'invio recupera solo gli attributi usati dalla lingua selezionata e dai campi dell'invio. Un invio senza riferimenti ai contatti salta la ricerca del contatto.
Un template che legge bird.contact.* richiede un contatto corrispondente nello spazio di lavoro per ogni destinatario To. Se un destinatario To non ha un contatto, la richiesta restituisce 422 con E04099 prima di accettare qualsiasi messaggio, anche in un batch o in un invio programmato. Crea o aggiorna prima il contatto, oppure usa parametri del chiamante. Un filtro default o un condizionale Liquid non elimina questo requisito. I template che usano parametri del chiamante o bird.unsubscribe_url senza attributi del contatto non richiedono un contatto corrispondente.
Ad esempio, invia Hello {{ bird.contact.first_name }} ad Alice e Bob, con Charlie in Cc:
| Consegna | Saluto | To visibile |
|---|---|---|
| Alice | Hello Alice | Alice |
| Charlie, in copia sull'email di Alice | Hello Alice | Alice |
| Bob | Hello Bob | Bob |
| Charlie, in copia sull'email di Bob | Hello Bob | Bob |
Charlie riceve due copie, quindi questa richiesta produce quattro consegne. Bcc funziona allo stesso modo, con l'indirizzo Bcc nascosto. Queste email personalizzate separate si applicano quando il template usa attributi del contatto; gli invii ordinari mantengono il loro comportamento di indirizzamento esistente. La stessa regola si applica a ogni messaggio del batch API.
Un contatto esistente può avere il nome o il cognome vuoto. I nomi mancanti vengono visualizzati come valori vuoti e scegli tu il saluto nel modello. Per un saluto con il nome, usa Hello {{ bird.contact.first_name | default: "there" }}!. Per il nome completo, combina entrambe le parti, rimuovi gli spazi alle estremità e scegli un valore predefinito:
{% assign full_name = bird.contact.first_name | append: " " | append: bird.contact.last_name | strip %}
Hello {{ full_name | default: "there" }}!Questo produce Hello Jane Doe!, Hello Jane! o Hello Doe! quando i nomi corrispondenti sono presenti, e Hello there! quando mancano entrambi. Non servono nomi sostitutivi per l'intero workspace.
Le proprietà del contatto che crei mantengono i valori di fallback configurati. Un null memorizzato è considerato assente; una stringa esplicitamente vuota, false o zero rimane un valore. Una proprietà assente senza fallback viene visualizzata vuota. Proprietà sconosciute e valori memorizzati non validi impediscono l'accettazione. Una ricerca non riuscita si può riprovare e non comporta la sostituzione con valori di fallback.
Un segnaposto bird.contact.* deve indicare un attributo predefinito o una proprietà personalizzata registrata. I nomi dei parametri del chiamante restano separati da quei percorsi della piattaforma. Gli invii di template singoli e in batch, inclusi quelli programmati, salvano i valori del destinatario al momento dell'accettazione e li riutilizzano per i nuovi tentativi di consegna e per le letture dei messaggi. I broadcast mantengono le proprie tempistiche di preparazione. Gli invii singoli e in batch rifiutano gli input sensibili prima dell'accettazione.
Archiviare una proprietà la rimuove dal selettore delle proprietà nell'editor. Le nuove versioni del template che la leggono non possono essere pubblicate, e l'errore indica la proprietà. I template già pubblicati continuano a inviare. Annulla l'archiviazione della proprietà per usarla di nuovo nelle nuove versioni.
I segnaposto usano Liquid, quindi filtri e flussi di controllo funzionano insieme alla semplice sostituzione. Un condizionale {% if %} e un ciclo {% for %} su un valore array vanno entrambi bene. Alcuni costrutti vengono rifiutati alla pubblicazione, e l'errore indica esattamente cosa modificare:
- Inclusioni parziali, con
{% include %}o{% render %}. - I tag
increment,decrementeifchanged. - I filtri
money,format_date,format_time,json,inspectetype. - Confronti con
emptyoblank. Usa.size == 0al loro posto. - Blocchi annidati molto più in profondità di quanto il markup email richieda realmente.
I parametri di template dei broadcast accettano valori scalari; array e oggetti non sono supportati. Senza parametri del chiamante, sia {% for %} sia {% tablerow %} supportano intervalli letterali come (1..3) ed elenchi creati in Liquid con split. Un broadcast che usa parametri del chiamante supporta {% for %} su un elenco creato con split, ma rifiuta gli intervalli e {% tablerow %}. In entrambi i casi, un tag di ciclo che legge direttamente un parametro del chiamante o una proprietà del contatto viene rifiutato, inclusi gli intervalli il cui estremo legge uno di questi valori.
Ogni template usa Liquid, anche uno che contiene solo segnaposto {{ variable }}. Prima della pubblicazione, validiamo l'oggetto, il testo di anteprima, l'HTML e il contenuto in testo semplice come Liquid. Aggiungiamo inoltre il filtro escape a ogni output HTML che non termina già con escape o escape_once, in modo che un valore contenente & o < non possa alterare il markup circostante. L'output riservato per la disiscrizione resta invariato, così l'invio può sostituirlo. L'oggetto e il corpo in testo semplice restano come scritti. Poiché la pubblicazione aggiunge questi filtri, l'HTML che leggi da una versione pubblicata potrebbe non essere identico byte per byte a quello che hai inviato.
Inserisci un URL completo direttamente in un href, ad esempio <a href="{{ sign_in_url }}">Sign in</a>. Non aggiungere url_encode all'intero valore. Codifica in percentuale https://, /, ? e &, il che impedisce al risultato di funzionare come link assoluto. Aggiungiamo l'escaping HTML preservando la struttura dell'URL. Quando un parametro fornisce un singolo componente dell'URL, codifica quel componente esplicitamente: <a href="https://example.com/search?q={{ query | url_encode }}">Search</a>.
Anteprima prima della pubblicazione
Renderizza un template con valori di esempio e ottieni l'oggetto e i corpi HTML e in testo semplice che un invio consegnerebbe. L'anteprima usa il nostro renderer Liquid locale e renderizza la bozza per impostazione predefinita: così verifichi una modifica prima che diventi attiva. Può renderizzare anche una versione pubblicata. Funziona sia con i tuoi template sia con quelli predefiniti, e non viene inviato nulla.
Puoi anche fornire tu il contenuto anziché farlo leggere dalla bozza. Passa un oggetto e i corpi, e questi vengono renderizzati esattamente come una bozza: questo permette a un editor di mostrare una modifica mentre viene digitata, senza prima salvare nulla.
La personalizzazione viene compilata per te, così il risultato si legge come testo finito anziché come segnaposto {{ }}. Specifica un contact e ogni bird.contact.<attribute> viene risolto in base alle proprietà di quel contatto: così verifichi il testo su un record reale prima che qualcuno lo riceva. I valori provengono dalla stessa proiezione che un broadcast usa per compilare i propri segnaposto, quindi l'anteprima restituisce ciò che restituirebbe un invio.
Se ometti contact, vengono sostituiti valori fittizi: Bird e Test per nome e cognome, bird.test@example.com per l'email e il fallback registrato di ogni altra proprietà. Una proprietà referenziata senza fallback viene renderizzata come la propria chiave tra parentesi quadre, ad esempio [loyalty_tier]: questo indica sia che il valore è fittizio sia quale proprietà necessita ancora di un fallback.
Un contatto viene letto nel suo stato attuale. Per questo l'anteprima è lo strumento giusto per verificare i contenuti che stai per inviare, e quello sbagliato per sapere cosa conteneva un invio precedente. Per leggere cosa ha effettivamente consegnato un invio, apri quel messaggio nel registro email, che lo renderizza dai valori che quell'invio conteneva.
Aggiungi language per renderizzare una lingua specifica, oppure omettilo per usare quella predefinita del template. La risposta indica quale lingua è stata renderizzata; questo conta quando quella richiesta non è disponibile e il on_missing_language del template ha servito una corrispondenza vicina.
Se la bozza ha una personalizzazione che verrebbe rifiutata al momento della pubblicazione, l'anteprima restituisce lo stesso errore, fungendo anche da strumento per individuare i problemi in anticipo.
Nel template builder della dashboard, Preview with contact data in fondo alla barra laterale sinistra mostra l'email renderizzata accanto a ciò che stai modificando, sia nell'editor visuale sia in quello del codice. Il selettore sottostante sceglie i dati di quale contatto compilano i segnaposto, e Sample data corrisponde ai valori fittizi descritti sopra.
Invio con un template
Imposta il campo template dell'invio su un oggetto che indica il template, tramite id (emt_...) oppure tramite slug, usando esattamente uno dei due. Inserisci i valori delle variabili in template.parameters. Aggiungi language per scegliere una lingua specifica, oppure omettilo per inviare nella lingua predefinita del template, a meno che il template non richieda che ogni invio ne specifichi una. Ometti del tutto subject, html e text, perché il template li fornisce già.
{
"from": "hello@yourdomain.com",
"to": ["delivered@messagebird.dev"],
"category": "transactional",
"template": {
"slug": "welcome-email",
"parameters": { "first_name": "Jane" }
}
}Un comportamento da tenere presente: la categoria del template è un valore predefinito, e il category dell'invio la sovrascrive. Se ometti category, l'invio eredita la categoria del template, quindi un template operativo viene inviato come transazionale senza doverlo ripetere a ogni chiamata. Se imposti category, il tuo valore prevale. Il resto del contratto lato invio è in invio con un template.
Creazione al di fuori della dashboard
L'intero ciclo di vita è disponibile al di fuori della dashboard: tramite API, gli SDK sotto email.templates, il bird CLI e gli strumenti email_templates_* MCP. Negli SDK, le operazioni su versioni e lingue si trovano sotto email.templates.versions e email.templates.versions.languages. Il passaggio di pubblicazione si chiama submit, e trasforma la bozza nella versione pubblicata successiva.
Puoi conservare i template nel tuo repository e sincronizzarli da uno step di build. Una bozza e una versione pubblicata restituiscono HTML diverso, quindi scegli la lettura adatta a ciò che serve al tuo strumento:
- Una bozza restituisce esattamente ciò che hai salvato. L'HTML che salvi in una lingua della bozza viene restituito byte per byte dalla lettura di quella lingua (
GET /v1/email/templates/{id}/versions/{draft_version_id}/languages/{language}) e dalla lettura della versione, inclusi il doctype, i blocchi<style>, i commenti, gli spazi, le terminazioni di riga e il testo non ASCII. Un salvataggio non restituisce contenuto, quindi rileggi la lingua quando devi confermare cosa è stato memorizzato. - Una versione pubblicata restituisce contenuto pronto per l'invio. La pubblicazione riscrive l'HTML in tre modi: ogni output
{{ }}che non termina già conescapeoescape_oncericeve il filtroescape, tranne{{ bird.unsubscribe_url }}, che resta invariato; il testo di anteprima viene inserito in un blocco nascosto subito dopo il tag di apertura<body>, oppure all'inizio se l'HTML non ne ha uno; e untextvuoto viene riempito con un'alternativa in testo semplice derivata dall'HTML. La lettura di quella versione restituisce il contenuto riscritto, che quindi differisce dal tuo file sorgente.
Per esportare il sorgente che hai scritto, leggi la bozza. La lettura di un template o l'elenco dei template restituisce metadati e stato per lingua, ma non l'HTML.
Gli esempi qui sotto usano {{ first_name }}, un parametro del chiamante fornito in template.parameters, come in "parameters": {"first_name": "Jane"}. Usa {{ bird.contact.first_name }} quando il template deve invece leggere il contatto del destinatario nello spazio di lavoro. Indica i destinatari tramite indirizzo email sia negli invii singoli sia in quelli in batch. Lo stile salvato nel template pubblicato resta parte di quella versione. Non esiste un namespace bird.brandkit.* a runtime.
Crea il template con la sua prima lingua. La risposta contiene l'id del template e il draft_version_id, usati dalle operazioni su versioni e lingue. L'esempio imposta anche preview_text, il testo di anteprima che un client di posta mostra dopo l'oggetto nell'elenco dei messaggi. La pubblicazione lo inserisce nell'HTML come blocco nascosto, ed è uno dei motivi per cui una versione pubblicata restituisce HTML diverso dalla bozza:
const template = await bird.email.templates.create({
slug: "welcome-email",
category: "transactional",
source: "html",
languages: {
en: {
subject: "Welcome, {{ first_name }}",
preview_text: "Your account is ready",
html: "<!DOCTYPE html>\n<html>\n<body>\n<p>Hi {{ first_name }}, thanks for signing up.</p>\n</body>\n</html>\n",
},
},
});
console.log(template.id, template.draft_version_id);template = client.email.templates.create(
slug="welcome-email",
category="transactional",
source="html",
languages={
"en": {
"subject": "Welcome, {{ first_name }}",
"preview_text": "Your account is ready",
"html": "<!DOCTYPE html>\n<html>\n<body>\n<p>Hi {{ first_name }}, thanks for signing up.</p>\n</body>\n</html>\n",
},
},
)
print(template.id, template.draft_version_id)template, err := client.Email.Templates.Create(context.Background(), bird.EmailTemplatesCreateParams{
Slug: "welcome-email",
Category: "transactional",
Source: "html",
Languages: map[string]bird.EmailTemplateLanguageContent{
"en": {
Subject: bird.String("Welcome, {{ first_name }}"),
PreviewText: bird.String("Your account is ready"),
Html: bird.String("<!DOCTYPE html>\n<html>\n<body>\n<p>Hi {{ first_name }}, thanks for signing up.</p>\n</body>\n</html>\n"),
},
},
})
if err != nil {
log.Fatal(err)
}
fmt.Println(template.Id, *template.DraftVersionId)$template = $bird->email->templates->create(
slug: 'welcome-email',
category: 'transactional',
source: 'html',
languages: [
'en' => [
'subject' => 'Welcome, {{ first_name }}',
'preview_text' => 'Your account is ready',
'html' => "<!DOCTYPE html>\n<html>\n<body>\n<p>Hi {{ first_name }}, thanks for signing up.</p>\n</body>\n</html>\n",
],
],
);
echo $template->getId(), ' ', $template->getDraftVersionId();bird email templates create --body-file - <<'EOF'
{
"slug": "welcome-email",
"category": "transactional",
"source": "html",
"languages": {
"en": {
"subject": "Welcome, {{ first_name }}",
"preview_text": "Your account is ready",
"html": "<!DOCTYPE html>\n<html>\n<body>\n<p>Hi {{ first_name }}, thanks for signing up.</p>\n</body>\n</html>\n"
}
}
}
EOFcurl -X POST https://us1.platform.bird.com/v1/email/templates \
-H "Authorization: Bearer bk_us1_..." \
-H "Content-Type: application/json" \
-d '{
"slug": "welcome-email",
"category": "transactional",
"source": "html",
"languages": {
"en": {
"subject": "Welcome, {{ first_name }}",
"preview_text": "Your account is ready",
"html": "<!DOCTYPE html>\n<html>\n<body>\n<p>Hi {{ first_name }}, thanks for signing up.</p>\n</body>\n</html>\n"
}
}
}'Per modificare una lingua in seguito, salvala di nuovo con bird email templates versions languages set o un PUT sullo stesso percorso della lingua. Il corpo è piatto: subject, che è obbligatorio, più preview_text, html e text. Un campo che ometti viene cancellato. Aggiungi il revision che hai letto per ultimo per rifiutare il salvataggio se qualcun altro ha modificato quella lingua nel frattempo.
Il layout dell'editor visuale della dashboard è uno dei campi cancellati in questo modo, perché API, gli SDK e CLI non possono inviarlo. Salvare una lingua creata nell'editor visuale ne conserva l'HTML ma rimuove il layout, quindi la dashboard riapre quella lingua nell'editor di codice.
I passaggi seguenti usano TEMPLATE_ID e DRAFT_VERSION_ID per id e draft_version_id restituiti dalla chiamata di creazione. Rileggi la lingua della bozza per ottenere l'HTML esattamente com'è memorizzato:
const language = await bird.email.templates.versions.languages.get(
"TEMPLATE_ID",
"DRAFT_VERSION_ID",
"en",
);
console.log(language.content?.html);language = client.email.templates.versions.languages.get(
"TEMPLATE_ID",
"DRAFT_VERSION_ID",
"en",
)
if language.content is not None:
print(language.content.html)language, err := client.Email.Templates.Versions.Languages.Get(context.Background(),
"TEMPLATE_ID", "DRAFT_VERSION_ID", "en")
if err != nil {
log.Fatal(err)
}
if language.Content != nil && language.Content.Html != nil {
fmt.Println(*language.Content.Html)
}$language = $bird->email->templates->versions->languages->get(
'TEMPLATE_ID',
'DRAFT_VERSION_ID',
'en',
);
echo $language->getContent()?->getHtml();bird email templates versions languages get "$TEMPLATE_ID" "$DRAFT_VERSION_ID" en \
| jq -j .content.html > welcome-email.htmlcurl "https://us1.platform.bird.com/v1/email/templates/$TEMPLATE_ID/versions/$DRAFT_VERSION_ID/languages/en" \
-H "Authorization: Bearer bk_us1_..." \
| jq -j .content.html > welcome-email.htmljq -j scrive la stringa senza aggiungere un a capo finale, quindi il file contiene gli stessi byte memorizzati da API.
Esegui prima il submit della bozza con validate_only. Esegue gli stessi controlli di un submit reale su tutte le lingue e riporta i problemi trovati in un'unica risposta, senza pubblicare nulla. Poi esegui il submit senza validate_only per pubblicare la versione successiva, che gli invii useranno da quel momento:
const templateId = "TEMPLATE_ID";
const draftVersionId = "DRAFT_VERSION_ID";
const check = await bird.email.templates.versions.submit(templateId, draftVersionId, {
validate_only: true,
});
for (const problem of check.errors) {
console.log(problem.language, problem.field, problem.message);
}
if (check.valid) {
const result = await bird.email.templates.versions.submit(templateId, draftVersionId);
console.log(result.version?.version_number);
}template_id = "TEMPLATE_ID"
draft_version_id = "DRAFT_VERSION_ID"
check = client.email.templates.versions.submit(template_id, draft_version_id, validate_only=True)
for problem in check.errors:
print(problem.language, problem.field, problem.message)
if check.valid:
result = client.email.templates.versions.submit(template_id, draft_version_id)
if result.version is not None:
print(result.version.version_number)ctx := context.Background()
templateID := "TEMPLATE_ID"
draftVersionID := "DRAFT_VERSION_ID"
check, err := client.Email.Templates.Versions.Submit(ctx, templateID, draftVersionID,
bird.EmailTemplatesVersionsSubmitParams{ValidateOnly: bird.Bool(true)})
if err != nil {
log.Fatal(err)
}
if check.Errors != nil {
for _, problem := range *check.Errors {
fmt.Println(*problem.Message)
}
}
if check.Valid != nil && *check.Valid {
result, err := client.Email.Templates.Versions.Submit(ctx, templateID, draftVersionID,
bird.EmailTemplatesVersionsSubmitParams{})
if err != nil {
log.Fatal(err)
}
fmt.Println(*result.Version.VersionNumber)
}$templateId = 'TEMPLATE_ID';
$draftVersionId = 'DRAFT_VERSION_ID';
$check = $bird->email->templates->versions->submit(
$templateId,
$draftVersionId,
(new EmailTemplateSubmit())->setValidateOnly(true),
);
foreach ($check->getErrors() ?? [] as $problem) {
echo $problem->getLanguage(), ' ', $problem->getField(), ' ', $problem->getMessage(), "\n";
}
if ($check->getValid() === true) {
$result = $bird->email->templates->versions->submit($templateId, $draftVersionId, new EmailTemplateSubmit());
echo $result->getVersion()?->getVersionNumber();
}bird email templates versions submit "$TEMPLATE_ID" "$DRAFT_VERSION_ID" --validate-only
bird email templates versions submit "$TEMPLATE_ID" "$DRAFT_VERSION_ID"curl -X POST "https://us1.platform.bird.com/v1/email/templates/$TEMPLATE_ID/versions/$DRAFT_VERSION_ID/submit" \
-H "Authorization: Bearer bk_us1_..." \
-H "Content-Type: application/json" \
-d '{"validate_only": true}'
curl -X POST "https://us1.platform.bird.com/v1/email/templates/$TEMPLATE_ID/versions/$DRAFT_VERSION_ID/submit" \
-H "Authorization: Bearer bk_us1_..." \
-H "Content-Type: application/json" \
-d '{}'Il corpo della richiesta di submit accetta validate_only e expected_revision. Passa la revision del template come expected_revision per rifiutare la pubblicazione se la bozza è cambiata dall'ultima lettura.
Elenca i template del tuo spazio di lavoro per trovare lo slug da indicare in un invio:
for await (const tpl of bird.email.templates.list({ scope: "workspace" })) {
console.log(tpl.slug, tpl.name);
}for template in client.email.templates.list(scope="workspace"):
print(template.slug, template.name)for tpl, err := range client.Email.Templates.List(context.Background(), bird.EmailTemplatesListParams{Scope: "workspace"}) {
if err != nil {
log.Fatal(err)
}
fmt.Println(*tpl.Slug, tpl.Name)
}foreach ($bird->email->templates->list(['scope' => 'workspace']) as $template) {
echo $template->getSlug(), ' ', $template->getName(), "\n";
}bird email templates list --scope workspacecurl "https://us1.platform.bird.com/v1/email/templates?scope=workspace" \
-H "Authorization: Bearer bk_us1_..."Invia il template pubblicato tramite slug, con un valore in template.parameters per ogni parametro che utilizza, qui first_name:
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);msg = client.email.send(
from_={"email": "onboarding@messagebird.dev", "name": "Bird"},
to=["delivered@messagebird.dev"],
category="transactional",
template="welcome-email",
parameters={"first_name": "Jane"},
)
print(msg.id, msg.status)msg, err := client.Email.Send(context.Background(), bird.EmailSendParams{
From: "onboarding@messagebird.dev",
To: []string{"delivered@messagebird.dev"},
Category: "transactional",
Template: "welcome-email",
Parameters: map[string]any{"first_name": "Jane"},
})
if err != nil {
log.Fatal(err)
}
fmt.Println(msg.Id, *msg.Status)$message = $bird->email->send(
from: 'Bird <onboarding@messagebird.dev>',
to: ['delivered@messagebird.dev'],
category: 'transactional',
template: (new EmailMessageSendRequestTemplate())
->setSlug('welcome-email')
->setParameters(['first_name' => 'Jane']),
);
echo $message->getId(), ' ', $message->getStatus();bird email send \
--category transactional \
--from hello@yourdomain.com \
--parameters '{"first_name":"Jane"}' \
--template welcome-email \
--to delivered@messagebird.devcurl -X POST https://us1.platform.bird.com/v1/email/messages \
-H "Authorization: Bearer bk_us1_..." \
-H "Content-Type: application/json" \
-d '{
"from": "hello@yourdomain.com",
"to": ["delivered@messagebird.dev"],
"category": "transactional",
"template": {
"slug": "welcome-email",
"parameters": { "first_name": "Jane" }
}
}'Passaggi successivi
- Invio di email: il payload completo di invio e come vi si inseriscono gli invii con template
- Categorie: scegliere
marketingotransactionalper ogni invio bird email templates: gestire i template dal terminale- Reference API: schemi completi di richiesta e risposta per tutte le diciotto operazioni sui template
- SDK: i metodi tipizzati
email.templatesin TypeScript, Python, PHP e Go - Server MCP: consentire a un agente di creare e pubblicare template
- Come creare un template email: un video che ne costruisce uno nella dashboard e poi ne fa costruire un altro a un agente
Risorse correlate
Continua con la documentazione, le guide e gli esempi per questo argomento.