Chaves de API e webhooks
Mail Merge possui uma API REST e webhooks de saída para desenvolvedores e construtores sem código. Com uma chave de API, seus scripts podem fazer o que o aplicativo web faz: ler sua conta, listar modelos e contatos, enviar campanhas e acompanhar seus destinatários. Com um webhook, Mail Merge chama seu endpoint no momento em que uma campanha termina ou um destinatário abre, clica, responde, retorna ou cancela a inscrição, para que um CRM, uma planilha ou um canal Slack permaneça sincronizado sem fazer polling.
Ambos estão em Configurações → Desenvolvedores no aplicativo web e fazem parte do plano Professional (veja Preços). Se preferir conversar com Mail Merge a partir de um assistente de IA em vez de escrever código, use o servidor MCP: ele expõe os mesmos recursos como ferramentas, em todos os planos.
Chaves de API
Seção intitulada “Chaves de API”Criar uma chave
Seção intitulada “Criar uma chave”- Abra Configurações → Desenvolvedores → Chaves de API e clique em Criar chave.
- Nomeie-a de acordo com o local onde será usada (
Zapier,Sincronização de CRM), para que você possa revogar a correta depois. - Copie a chave. Ela é mostrada uma única vez: Mail Merge mantém apenas um hash dela. Se você a perder, revogue-a e crie uma nova.
Você pode ter até 10 chaves por conta. Revogar uma chave faz com que todas as solicitações feitas com ela falhem imediatamente; a linha desaparece da lista.
Autenticar
Seção intitulada “Autenticar”Envie a chave como um token Bearer em cada solicitação, contra a URL base mostrada no cartão:
curl https://merge.email/api/v1/me \ -H "Authorization: Bearer mm_live_XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"Uma chave atua como a conta que a criou, exatamente como uma sessão conectada: a mesma concessão do Google, a mesma cota diária, os mesmos limites de plano. Não há um “usuário de API” separado.
Endpoints
Seção intitulada “Endpoints”A API é a mesma superfície /v1 que o aplicativo web usa, portanto qualquer coisa que você possa fazer em uma tela tem um endpoint por trás. Os que as integrações mais procuram:
| Chamada | O que faz |
|---|---|
GET /v1/me | A conta: plano, cota diária (máximo, usado, restante), fuso horário, metadados de modelo. |
GET /v1/templates · GET /v1/templates/{templateId} | Seus modelos salvos; o corpo carrega por modelo. |
GET /v1/contacts · POST /v1/contacts | O catálogo de contatos (paginado com limit / cursor → nextCursor). |
POST /v1/campaigns | Enviar, agendar ou autopiloto uma campanha a partir de uma Planilha Google. O corpo é o mesmo que o construtor de campanhas envia: a planilha, a coluna de destinatários, o assunto e corpo com {{merge tags}}, e as opções de envio. |
GET /v1/campaigns · GET /v1/campaigns/{campaignId}/recipients | Suas campanhas e o status de cada destinatário (enviado, lido, clicado, respondido, retornado, cancelado inscrição). |
POST /v1/campaigns/{campaignId}/status | Pausar, retomar ou parar uma campanha em execução. |
POST /v1/recipients/verify | O verificador de email. |
Os corpos de solicitação e resposta são JSON. A superfície digitada completa é gerada do servidor como um documento OpenAPI; entre em contato conosco se precisar do esquema para um gerador de cliente.
Erros e limite de taxa
Seção intitulada “Erros e limite de taxa”As falhas são status HTTP reais com um envelope:
{ "error": { "code": "professional_plan_required", "message": "API access is a Professional plan feature" } }| Status | code | Significado |
|---|---|---|
| 401 | Chave desconhecida ou revogada, ou o acesso do Google da conta precisa ser reconectado. | |
| 403 | professional_plan_required | A conta da chave não está mais no plano Professional. As chaves não são excluídas em um downgrade; funcionam novamente quando o plano funciona. |
| 429 | rate_limited | Mais de 600 solicitações por minuto em uma chave. Aguarde um minuto e tente novamente. |
| 400 / 404 / 409 | bad_request, not_found, conflict, … | A própria solicitação, com uma mensagem dizendo o que corrigir. |
O limite de taxa é contado por chave em cada instância do servidor de API, portanto o teto efetivo é “cerca de 600 por minuto”: não projete em torno de atingi-lo.
Webhooks
Seção intitulada “Webhooks”Adicionar um endpoint
Seção intitulada “Adicionar um endpoint”- Abra Configurações → Desenvolvedores → Webhooks e clique em Adicionar webhook.
- Digite uma URL HTTPS (http:// simples é recusado) e marque os eventos que deve receber.
- Clique em Enviar teste na nova linha: Mail Merge envia um
pinge o aviso informa como seu endpoint respondeu.
Cada endpoint recebe seu próprio segredo de assinatura (whsec_…), mostrado na linha com um botão de cópia. Você pode ter até 5 endpoints por conta.
Eventos
Seção intitulada “Eventos”| Evento | Quando | data |
|---|---|---|
campaign.completed | O último email de uma campanha foi processado. | campaignId, name, status: "completed", sentCount, campaignSize |
campaign.paused · campaign.resumed · campaign.stopped | Você pausou, retomou ou parou uma campanha. | campaignId, name, status (paused / active / stopped), sentCount |
email.opened | Um destinatário abriu um email, primeira vez apenas por campanha. | campaignId, recipient, at |
email.clicked | Um destinatário clicou em um link rastreado, cada clique. | campaignId, recipient, at, url |
email.replied | Uma resposta foi detectada em uma thread enviada. | campaignId, recipient, at |
email.bounced | Um retorno foi detectado. | campaignId, recipient, at |
recipient.unsubscribed | Um destinatário usou o link de cancelamento de inscrição, primeira vez apenas por campanha. | campaignId, recipient, at, method |
Aberturas e cliques precisam de rastreamento ativado para a campanha; respostas e retornos vêm da verificação de resposta que segue cada campanha enviada.
Entrega
Seção intitulada “Entrega”Mail Merge envia um POST por evento por endpoint inscrito, com um corpo JSON:
{ "id": "6f1c2d3e-…", "event": "email.opened", "createdAt": "2026-10-15T14:03:21.512Z", "data": { "campaignId": "…", "recipient": "ada@example.com", "at": "2026-10-15T14:03:21.498Z" }}e três cabeçalhos:
| Cabeçalho | Valor |
|---|---|
X-MailMerge-Event | O nome do evento, igual a event no corpo. |
X-MailMerge-Delivery | O id de entrega, igual a id. Use-o para ignorar uma duplicata. |
X-MailMerge-Signature | sha256= seguido pelo HMAC-SHA256 hexadecimal do corpo bruto, codificado com o segredo do endpoint. |
Responda com qualquer 2xx dentro de 5 segundos. Em um erro de rede ou um 5xx, Mail Merge tenta novamente uma vez, após 2 segundos; um 4xx é tomado como seu veredicto e não é tentado novamente. O mesmo id de entrega é enviado na tentativa. Após 20 entregas falhadas seguidas, o endpoint é desativado e a linha diz isso: corrija o endpoint, depois delete e adicione-o novamente. Qualquer entrega bem-sucedida redefine o contador.
Os eventos são entregues pelo menos uma vez e em nenhuma ordem garantida. As aberturas em particular chegam em rajadas (cada cliente de email que renderiza o pixel de rastreamento), portanto torne seu manipulador idempotente em X-MailMerge-Delivery ou em (event, campaignId, recipient).
Verificar a assinatura
Seção intitulada “Verificar a assinatura”Sempre verifique antes de confiar em um payload. Calcule o HMAC sobre o corpo bruto da solicitação (os bytes exatos, antes de qualquer análise JSON) e compare-o em tempo constante:
// Node.js (Express com `express.raw({ type: "application/json" })`)import { createHmac, timingSafeEqual } from "node:crypto"
export function verifyMailMergeSignature(rawBody, signatureHeader, secret) { const expected = "sha256=" + createHmac("sha256", secret).update(rawBody).digest("hex") const a = Buffer.from(expected) const b = Buffer.from(signatureHeader ?? "") return a.length === b.length && timingSafeEqual(a, b)}
app.post("/mailmerge", (req, res) => { if (!verifyMailMergeSignature(req.body, req.get("X-MailMerge-Signature"), process.env.MAILMERGE_WEBHOOK_SECRET)) { return res.status(401).end() } const payload = JSON.parse(req.body) // … handle payload.event / payload.data res.status(204).end()})# Pythonimport hashlib, hmac
def verify_mailmerge_signature(raw_body: bytes, signature_header: str, secret: str) -> bool: expected = "sha256=" + hmac.new(secret.encode(), raw_body, hashlib.sha256).hexdigest() return hmac.compare_digest(expected, signature_header or "")Zapier, Make e n8n
Seção intitulada “Zapier, Make e n8n”Sem código necessário: crie um Catch Hook (Zapier Webhooks by Zapier), um Custom webhook (Make) ou um nó de gatilho Webhook (n8n), cole a URL que ele fornece como o endpoint, marque os eventos e clique em Enviar teste para que a ferramenta possa amostrar o payload. Os campos data se tornam as variáveis que você mapeia para a próxima etapa (adicione uma linha a uma planilha, atualize um contato de CRM, poste no Slack). Essas ferramentas não verificam assinaturas por padrão; a URL que fornecem é inadivinhável, que é a proteção em que confiam.
Para onde ir a seguir
Seção intitulada “Para onde ir a seguir”- Agentes de IA (MCP), se um assistente deve conduzir Mail Merge para você em vez de um script.
- Campanhas, para o que os status no endpoint de destinatários significam.
- Preços, para o que o plano Professional inclui.