Sign inGet Started

Templates de e-mail

Um template é um assunto e um corpo de e-mail que você salva uma vez e envia várias vezes. Você escreve as partes que mudam como placeholders {{ variable }}, publica o template e então envia pelo slug em vez de colar o mesmo HTML em cada chamada API. Um template pertence ao seu espaço de trabalho.
Crie e gerencie templates em Email > Templates, pelo /v1/email/templates, com a bird CLI, ou pelo MCP server. Métodos tipados estão disponíveis nos SDKs de TypeScript, Python, PHP e Go em email.templates. Os schemas completos de solicitação e resposta estão na referência do API. Envie um template publicado pelo endpoint de envio padrão.

O que tem em um template

Todo template tem dois nomes, e eles servem para coisas diferentes:
  • slug é o nome pelo qual você envia o template, por exemplo welcome-email. Você o escolhe ao criar o template e ele não pode ser alterado depois. Um slug pode conter letras minúsculas, números, hífens e underscores, precisa começar e terminar com uma letra ou número e pode ter até 63 caracteres. Dois prefixos são proibidos: bird_, que é reservado para nossos templates integrados, e emt_, que é o formato usado para IDs de template. O dashboard chama esse campo de Alias.
  • name é um rótulo de exibição em texto livre. O padrão é o slug, e você pode alterá-lo a qualquer momento. Nada é resolvido pelo name, então renomear um template para exibição nunca quebra um envio.
Além desses, um template tem um ID emt_ permanente, que é fixo por toda a sua vida. Ele também tem uma category, que pode ser marketing ou transactional, e uma source de autoria: html, markup finalizada que você fornece, opcionalmente personalizada com Liquid. A categoria e a source são ambas fixadas quando você cria o template.
Fornecemos um catálogo de templates integrados, e seus slugs sempre começam com bird_. Um template integrado não pertence a nenhum espaço de trabalho, não pode ser editado e está sempre pronto para envio. Copie um para o seu espaço de trabalho para torná-lo seu, e ele se torna um template comum que você pode editar. A cópia chega como um rascunho não publicado que herda a categoria, a source e as configurações de idioma do original, então publique-o antes de enviá-lo.

Rascunhos e versões publicadas

Todo template tem exatamente um rascunho, que é a cópia de trabalho que você edita. Ele também tem qualquer número de versões publicadas, cada uma numerada (1, 2, 3 e assim por diante) e nunca mais alterada depois de existir. Editar altera o rascunho diretamente. Publicar tira um snapshot do rascunho atual, transforma-o na próxima versão numerada e faz dessa versão a que os envios usam. O rascunho em si continua editável, então você pode seguir trabalhando no próximo.
A regra que importa para o envio é esta: um envio sempre usa a versão publicada do template, e um rascunho nunca é enviado sozinho. Você pode continuar editando o rascunho enquanto uma versão estável continua sendo enviada, e publicar quando a alteração estiver pronta. Publicar uma nova versão muda o que os envios seguintes renderizam. Um envio já aceito não é afetado por uma publicação que aconteça depois.
A aba Versions do template com uma linha Draft e linhas publicadas v3, v2 e v1 mostrando suas datas de criação e publicação
Versões suportam mais duas ações. Descartar as alterações do rascunho para redefinir o rascunho de volta ao que está publicado no momento. Ou reverter para fazer uma versão publicada anterior voltar a ser a que os envios usam. Você só pode reverter para uma versão que foi publicada, nunca para o rascunho em si. Reverter substitui o rascunho pelo conteúdo dessa versão, então qualquer coisa não salva no rascunho é perdida, e edições futuras começam a partir da versão para a qual você reverteu. Uma reversão não cria uma nova versão.
Para escolher uma imagem existente, você precisa de acesso de leitura à biblioteca de mídia do espaço de trabalho. Para enviar, colar ou arrastar e soltar uma nova imagem, você precisa de acesso de gravação. Se Inserir imagem estiver desativado ou você não conseguir pesquisar na biblioteca ou enviar imagens, peça a um administrador do espaço de trabalho a permissão correspondente para a biblioteca de mídia. A permissão para editar modelos, por si só, não concede acesso à biblioteca de mídia.
No painel, escolha Visual > Inserir imagem para pesquisar na biblioteca de mídia ou enviar uma imagem PNG, JPEG, GIF ou WebP de até 5 MB. Imagens WebP estáticas são convertidas para PNG ou JPEG. Selecione a imagem para definir sua Descrição da imagem, largura de exibição, alinhamento e link. Marque Imagem decorativa apenas quando ela não acrescentar informação; uma imagem com link precisa de uma descrição que explique o destino. Cada idioma mantém suas próprias descrições de imagens e seu layout.
Use Substituir imagem para trocar a imagem selecionada mantendo sua descrição, link, largura e alinhamento. Você também pode colar ou arrastar um arquivo de imagem por vez para o editor visual. Aguarde o fim do upload ou cancele-o antes de salvar ou enviar um teste. Confira a prévia e abra Mais ações > E-mail de teste para enviar o conteúdo atual para você. Código continua disponível para editar HTML.
Remover uma imagem da biblioteca de mídia não a remove dos e-mails já enviados. A substituição de uma imagem usa uma nova URL, então as mensagens anteriores continuam mostrando a original.
Salvar é protegido por um número de revisão. Envie o revision que você leu por último para o idioma que está salvando. Se outra pessoa alterou esse idioma nesse meio-tempo, o salvamento é recusado como conflito em vez de sobrescrever o trabalho dela. Omita revision para salvar incondicionalmente. Publicar e reverter usam o revision do próprio rascunho da mesma forma.

Conteúdo em mais de um idioma

Um template contém conteúdo em até 25 idiomas, cada um com seu próprio assunto e corpo, marcado com um código BCP-47 como en ou pt-BR. Um idioma é o padrão do template. Publicar um template publica todos os idiomas que ele contém ao mesmo tempo. Você não pode publicar um idioma isoladamente, então todos precisam estar finalizados antes. Todo idioma precisa de um assunto e um corpo, e o idioma padrão do template precisa ser um dos idiomas que você preencheu. Se algo estiver faltando, nada é publicado, e o erro informa o que está faltando em cada idioma para que você possa corrigir tudo de uma vez. Você não precisa finalizar todos os idiomas de antemão: publique os que estão prontos e adicione o restante depois.
Um idioma precisa de um corpo HTML. Você pode omitir o text: a publicação então cria uma alternativa em texto puro a partir do HTML automaticamente, assim você obtém as duas partes sem precisar escrever a segunda.
Cada idioma também pode ter um texto de pré-visualização, às vezes chamado de preheader: a linha que a caixa de entrada mostra após o assunto na lista de mensagens. É opcional, tem até 255 caracteres e aceita os mesmos placeholders {{ variable }} que o assunto. Omita-o e a caixa de entrada recorre à primeira linha do corpo, que raramente é a linha que você escolheria. A publicação recusa texto de pré-visualização em um idioma cujo corpo não tem parte HTML, já que um cliente de e-mail só lê a linha de pré-visualização a partir de markup HTML oculta, e recusa {{ bird.unsubscribe_url }} dentro dele pela mesma razão que o assunto não pode carregá-lo: nenhum dos dois é um lugar onde um link pode ir.
Duas configurações cobrem um envio que não nomeia um idioma para o qual o template tem conteúdo, e elas protegem contra erros diferentes:
ConfiguraçãoO que ela controla
on_missing_languageO que acontece quando um envio solicita um idioma que o template não tem. fallback, o padrão, serve a correspondência mais próxima. Ele tenta uma forma mais ampla do mesmo idioma primeiro, então um pt armazenado pode atender uma solicitação de pt-BR. Em seguida, recorre ao idioma padrão do template. fail rejeita o envio, para conteúdo em que enviar o idioma errado é pior do que não enviar nada.
language_source_requiredSe um envio precisa informar um idioma. Está desativado por padrão, então um envio que não informa nenhum recebe o idioma padrão. Ative-o, e esse envio é rejeitado. Um broadcast informa um único idioma para toda a audiência, então um template com essa configuração ativada precisa que o idioma seja escolhido antes de o broadcast poder enviar.
Você pode definir essas duas configurações de forma independente. Sozinho, fail só se aplica quando um envio nomeia um idioma que não temos, então um envio que não nomeia nenhum ainda passa. Ative ambas as configurações juntas quando quiser que todo envio nomeie um idioma de propósito.

Personalizando com variáveis

Escreva placeholders {{ variable }} no assunto, texto de pré-visualização e corpo. Nós os identificamos automaticamente, combinados em todos os idiomas, então você nunca precisa declará-los separadamente. O prefixo do placeholder distingue os dois tipos. Um caminho que começa com bird. lê dos nossos dados, seja um registro de contato ou o link de descadastro. Todo o restante é um parâmetro para o qual você fornece um valor ao enviar.
O nome de um parâmetro é uma palavra única, como {{ animal }}. Um nome com pontos tenta acessar uma estrutura que um parâmetro não tem, então publicar um assim é rejeitado: escreva o valor como seu próprio parâmetro ou leia dados do contato com bird.contact.<attribute>.
Em um envio individual ou em lote, o valor de um parâmetro vem do objeto template.parameters do envio, indexado pelo nome. Um conjunto de valores cobre todos os destinatários desse envio. bird é o único nome que você não pode usar ali: uma chave template.parameters chamada bird é rejeitada com um 422.
Um broadcast não tem objeto parameters, então seu conteúdo só pode usar placeholders bird.. bird.contact.<attribute> é preenchido a partir das propriedades de contato de cada destinatário, que é o que personaliza o conteúdo por destinatário. Toda propriedade de contato está disponível pela sua própria chave, assim como os três campos integrados: first_name, last_name e email.
Exemplo de código
Hi {{ bird.contact.first_name }},
Todo parâmetro no template precisa de um valor quando você envia. Caso contrário, o API retorna um 422 que nomeia o parâmetro ausente. Forneça valores para parâmetros em todos os idiomas, porque o idioma selecionado pode depender das configurações de fallback. Uma propriedade de contato ausente é renderizada como valor vazio, então adicione um fallback para conteúdo visível ao cliente: {{ bird.contact.first_name | default: "there" }}.
Um broadcast é mais restrito quanto aos nomes que aceita, porque propriedades de contato são tudo o que ele tem para preencher placeholders. Seus placeholders bird.contact.* só podem nomear um campo integrado ou uma propriedade de contato que o espaço de trabalho tenha registrado. Qualquer outro placeholder, incluindo um parâmetro, é um que o broadcast não tem como preencher. O envio é recusado, e o erro nomeia o placeholder.
O que arquivar uma propriedade muda para um template é apenas conteúdo novo: a propriedade desaparece do seletor no editor, e publicar uma versão cujo conteúdo a utiliza é recusado, nomeando a propriedade. Versões publicadas antes do arquivamento não são afetadas.
Placeholders usam Liquid, então filtros e controle de fluxo funcionam junto com substituição simples. Um condicional {% if %} e um loop {% for %} sobre um valor de array funcionam normalmente. Alguns construtos são rejeitados quando você publica, e o erro nomeia exatamente o que mudar:
  • Inclusões parciais, usando {% include %} ou {% render %}.
  • As tags increment, decrement e ifchanged.
  • Os filtros money, format_date, format_time, json, inspect e type.
  • Comparações com empty ou blank. Use .size == 0 em vez disso.
  • Blocos aninhados muito mais fundo do que a marcação real de e-mail precisa.
O template de um broadcast não pode usar um loop {% for %} de forma alguma, porque um broadcast preenche um valor por propriedade de contato e não tem nada para iterar. Se o seu conteúdo precisa de um loop, envie-o pela API de mensagens.
Todo template usa Liquid, inclusive um que contém apenas placeholders {{ variable }}. Antes de publicar, validamos o assunto, o texto de pré-visualização, o HTML e o conteúdo em texto simples como Liquid. Também adicionamos o filtro escape a cada saída HTML que ainda não termina com escape ou escape_once, para que um valor contendo & ou < não consiga alterar a marcação ao redor. A saída reservada de cancelamento de inscrição permanece inalterada para que o envio possa substituí-la. O assunto e o corpo em texto simples são mantidos como escritos. Como a publicação adiciona esses filtros, o HTML que você lê de uma versão publicada pode não ser idêntico byte a byte ao que você enviou.
Coloque uma URL completa diretamente em um href, como <a href="{{ sign_in_url }}">Sign in</a>. Não adicione url_encode ao valor inteiro. Ele codifica em porcentagem https://, /, ? e &, o que impede o resultado de funcionar como um link absoluto. Nós adicionamos escape de HTML preservando a estrutura da URL. Quando um parâmetro fornece um componente da URL, codifique esse componente explicitamente: <a href="https://example.com/search?q={{ query | url_encode }}">Search</a>.

Pré-visualizando antes de publicar

Renderize um template com valores de exemplo e receba de volta o assunto e os corpos em HTML e texto simples que um envio entregaria. A pré-visualização usa nosso renderizador Liquid local e renderiza o rascunho por padrão, que é como você confere uma mudança antes de ela ir ao ar. Ela também pode renderizar uma versão publicada. Funciona para seus próprios templates e para os nossos integrados, e nada é enviado.
Você também pode fornecer o conteúdo diretamente em vez de deixar que ele leia o rascunho. Passe um assunto e corpos e eles serão renderizados, tratados exatamente como um rascunho seria, que é o que permite a um editor mostrar uma mudança enquanto ela é digitada sem salvar nada antes.
A personalização é preenchida para você, então o que volta se lê como texto final em vez de placeholders {{ }}. Nomeie um contact e cada bird.contact.<attribute> é resolvido com base nas propriedades daquele contato, que é como você confere sua redação contra um registro real antes de qualquer pessoa recebê-lo. Os valores vêm da mesma projeção que um broadcast usa para preencher seus placeholders, então a pré-visualização responde com o que um envio responderia.
Omita contact e valores substitutos são usados: Bird e Test para o primeiro e o último nome, bird.test@example.com para o e-mail, e o fallback registrado de cada outra propriedade. Uma propriedade referenciada sem fallback é renderizada como sua chave entre colchetes, como [loyalty_tier], o que indica tanto que o valor é um placeholder quanto qual propriedade ainda precisa de um fallback.
Um contato é lido como está neste momento. Isso faz da pré-visualização a ferramenta certa para conferir conteúdo que você está prestes a enviar, e a errada para perguntar o que um envio anterior continha. Para ler o que um envio de fato entregou, abra aquela mensagem no log de e-mail, que a renderiza a partir dos valores que aquele envio carregou.
Adicione language para renderizar um idioma específico, ou omita para usar o padrão do template. A resposta informa qual idioma foi renderizado, o que importa quando o que você pediu não está disponível e o on_missing_language do template serviu a correspondência mais próxima.
Se o rascunho tiver personalização que seria rejeitada ao publicar, a pré-visualização retorna o mesmo erro, então ela também serve para encontrar problemas cedo.
No construtor de templates do dashboard, Preview with contact data na parte inferior do painel esquerdo mostra o e-mail renderizado ao lado do que você está editando, tanto no editor visual quanto no editor de código. O seletor abaixo dele escolhe de quem são os dados que preenchem os placeholders, e Sample data são os valores substitutos acima.

Enviando com um template

Defina o campo template do envio como um objeto que nomeia o template, seja por id (emt_...) ou por slug, usando exatamente um dos dois. Coloque os valores das variáveis em template.parameters. Adicione language para escolher um idioma específico, ou omita para enviar o idioma padrão do template, a menos que o template exija que cada envio nomeie um. Omita subject, html e text inteiramente, porque o template já os fornece.
Exemplo de código
{
  "from": "hello@yourdomain.com",
  "to": ["delivered@messagebird.dev"],
  "category": "transactional",
  "template": {
    "slug": "welcome-email",
    "parameters": { "first_name": "Jane" }
  }
}
Um comportamento que vale planejar: a categoria do template é um padrão, e o category do próprio envio a sobrescreve. Omita category, e o envio herda a categoria do template, então um template operacional envia como transacional sem você repetir isso em cada chamada. Defina category, e o seu valor prevalece. O restante do contrato do lado do envio está em enviando com um template.

Criando fora do dashboard

Todo o ciclo de vida está disponível fora do dashboard. A etapa de publicação se chama submit lá, e é a operação que transforma o rascunho na próxima versão publicada:
Exemplo de código
bird email templates create welcome-email --category marketing --source html
bird email templates versions languages set <emt_...> <emv_...> en --subject "Hi {{ bird.contact.first_name }}" --html "<p>Hello</p>"
bird email templates versions submit <emt_...> <emv_...> --validate-only   # report problems, freeze nothing
bird email templates versions submit <emt_...> <emv_...>                   # freeze, go live
create retorna o template junto com seu draft_version_id, que todo comando de versão e idioma recebe. --validate-only executa as mesmas verificações de completude de um submit real, sem congelar nada, então é o jeito barato de encontrar todos os problemas em todos os idiomas de uma vez. Ler um template de volta devolve seus metadados e o estado por idioma, mas sem conteúdo. O conteúdo fica nos idiomas de uma versão, um idioma por vez.
Os SDKs trazem o mesmo ciclo de vida como métodos tipados em email.templates, com as operações de versão e idioma aninhadas abaixo como email.templates.versions e email.templates.versions.languages. Um agente acessa as mesmas operações por meio das ferramentas email_templates_* MCP.

Próximos passos

  • Enviando e-mail: o payload completo de envio e como envios com template se encaixam nele
  • Categorias: escolhendo marketing vs transactional em cada envio
  • bird email templates: gerenciando templates pelo terminal
  • Referência do API: schemas completos de solicitação e resposta para todas as dezoito operações de template
  • SDKs: os métodos tipados email.templates em TypeScript, Python, PHP e Go
  • Servidor MCP: permitindo que um agente crie e publique templates
  • Como criar um template de email: um vídeo que cria um no dashboard e depois faz um agente criar outro

Recursos relacionados

Continue com a documentação, guias e exemplos sobre este tópico. Os recursos estão em inglês.

Experimente na prática e obtenha um resumo de implementação