Automações
Sequências de e-mails e ações disparadas por eventos, contatos novos, segmentos e formulários, com versões e o registro de cada execução.
Automações enviam e-mails e cuidam dos contatos sozinhas, a partir de um gatilho: um evento do seu produto, um contato novo, a entrada num segmento ou uma inscrição por formulário. Cada contato que dispara o gatilho ganha uma execução, que percorre os passos (esperar, enviar e-mail, verificar uma condição, mudar o contato, chamar um webhook) e registra o que aconteceu em cada um. Todos os endpoints exigem uma chave de acesso total.
#Rascunho, ativa e pausada
| Status | Como funciona |
|---|---|
draft | Criada assim. Pode ser salva incompleta (um e-mail sem template, uma condição sem caminhos); o que falta aparece em issues. Não inicia execuções. |
active | Depois de ativar: a definição precisa estar completa e vira uma versão (version). Cada gatilho inicia uma execução. |
paused | Depois de pausar: não inicia execuções, e as que estão esperando ficam paradas até a automação ser ativada de novo. |
Versões. Editar uma automação ativa publica uma nova versão na hora (se o gatilho, os passos ou reentry mudaram). Só as novas execuções seguem a versão nova: as que já estão em andamento terminam na versão em que começaram (version da execução). Mudar só o nome não cria versão.
Reentrada. Com reentry: "once" (padrão), cada contato passa pela automação uma vez só. Com "every_time", cada gatilho inicia uma nova execução, mesmo que outra esteja em andamento.
Limite do plano. As execuções iniciadas no mês (em UTC), somando todas as automações, têm limite por plano (veja Limites e automation_runs em GET /usage). Passou do limite, a execução fica registrada como skipped, com o motivo, e não conta no limite.
#Gatilho e passos
Uma automação é um trigger e uma lista de steps. Os passos rodam em ordem; uma condition fecha a lista e continua num dos caminhos (branches.yes ou branches.no), cada um com a própria lista. O fim de uma lista termina a execução. Uma automação pode ter até 100 passos no total.
Gatilhos
type | Campos | Quando inicia | Exemplo |
|---|---|---|---|
event | event: nome do evento. filters: até 10 comparações com as propriedades do evento, todas precisam bater. | Um evento com esse nome chega com um contato. | {"type": "event", "event": "order.paid", "filters": [{"key": "total", "operator": "gte", "value": 500}]} |
contact.created | — | Um contato é criado pela API, por um formulário ou por um evento com e-mail novo. Contatos de importação de CSV não disparam. | {"type": "contact.created"} |
segment.added | segment_id | Um contato entra no segmento: pela API, por um formulário ou por um passo update_contact. Importações não disparam. | {"type": "segment.added", "segment_id": "019a1d90-3b4c-7d5e-9f6a-7b8c9d0e1f2a"} |
form.submitted | form_id | Alguém se inscreve pelo formulário (com double opt-in, depois de confirmar). | {"type": "form.submitted", "form_id": "019a1da0-7f80-7b91-8c0d-2e3f4a5b6c7d"} |
Passos
Cada passo é {"id", "type", "config"}. O id (letras, números, _ e -, até 64 caracteres, único na automação) identifica o passo nas condições e no registro das execuções; sem ele, a Postal gera um como step_k3x9p2qa7m. Chaves desconhecidas são descartadas.
type | O que faz | config |
|---|---|---|
wait | Espera um tempo ou até um horário. | {"mode": "duration", "amount": 2, "unit": "days"} (unidades: minutes, hours, days, weeks; até 365 dias) ou {"mode": "until", "time": "09:00", "weekdays": [1, 2, 3, 4, 5], "timezone": "America/Sao_Paulo"}: o próximo 09:00, só nos dias da semana listados (1 = segunda, 7 = domingo; vazio = qualquer dia). Fuso padrão: America/Sao_Paulo. |
send_email | Envia um template publicado para o contato. | template_id (ID ou alias, obrigatório), from (padrão: o do template), subject (no lugar do assunto do template), reply_to e variables. Veja Variáveis. |
condition | Segue pelo caminho yes ou no. | Fica sempre no fim da sua lista; os passos seguintes vão em branches.yes e branches.no. Veja Condições. |
update_contact | Muda o contato. | actions, até 20: {"type": "set_property", "key": "plan", "value": "pro"} (first_name, last_name ou uma propriedade; o valor aceita {{event.*}}), add_to_segment e remove_from_segment (com segment_id), subscribe_topic e unsubscribe_topic (com topic_id), unsubscribe e resubscribe. |
webhook | Envia o contato e o evento para uma URL sua. | {"url": "https://…"}. Veja Passo de webhook. |
exit | Termina a execução. | Sem configuração; fica no fim da sua lista. O fim de uma lista já termina a execução, então use exit só para deixar claro. |
Condições
kind | Campos | Exemplo |
|---|---|---|
contact_property | key (email, first_name, last_name ou uma propriedade), operator, value | {"kind": "contact_property", "key": "plan", "operator": "equals", "value": "pro"} |
event_property | key (caminho na propriedade do evento que iniciou a execução, como items.0.name), operator, value | {"kind": "event_property", "key": "total", "operator": "gt", "value": 200} |
segment | segment_id, operator: in ou not_in | {"kind": "segment", "segment_id": "019a1d90-3b4c-7d5e-9f6a-7b8c9d0e1f2a", "operator": "in"} |
topic | topic_id, operator: subscribed ou not_subscribed | {"kind": "topic", "topic_id": "019a1d95-4c5d-7e6f-8a7b-8c9d0e1f2a3b", "operator": "subscribed"} |
email_activity | step_id de um send_email anterior no mesmo caminho, activity: opened ou clicked. Um clique conta como abertura. | {"kind": "email_activity", "step_id": "welcome", "activity": "opened"} |
Operadores de comparação (nas condições de propriedade e nos filtros do gatilho): equals, not_equals, contains, not_contains, starts_with, ends_with, gt, gte, lt, lte, is_set e is_not_set (esses dois sem value). Textos são comparados sem diferenciar maiúsculas; números, como números; datas no formato AAAA-MM-DD, em ordem de calendário.
Variáveis nos e-mails
O send_email usa a versão publicada do template, como um POST /emails com template: mesmas validações, cota de envio e lista de supressão. As variáveis do template ({{{NAME}}}) são preenchidas sozinhas com:
EMAIL,FIRST_NAME,LAST_NAMEeCONTACT_IDdo contato;- cada propriedade do contato e cada propriedade de primeiro nível do evento, pela chave e em maiúsculas (
planePLAN); POSTAL_UNSUBSCRIBE_URL, o link da página de preferências do contato;- e as
variablesdo passo, que aceitam referências como{{contact.first_name}},{{contact.plan}}e{{event.items.0.name}}(valores ausentes ficam vazios).
O subject do passo e os valores de set_property aceitam as mesmas referências {{contact.*}} e {{event.*}}. Os e-mails levam os cabeçalhos List-Unsubscribe com clique único; inclua {{{POSTAL_UNSUBSCRIBE_URL}}} no template para mostrar o link no corpo. Contatos descadastrados (unsubscribed) não recebem: o passo fica skipped e a execução continua. Se o envio falhar (cota esgotada, domínio sem verificação, variável sem valor), o passo e a execução ficam failed.
#Listar automações
GET/automations
Cada automação com a definição, a versão em vigor (null num rascunho nunca ativado), runs_this_month (execuções iniciadas no mês) e runs_in_progress.
Parâmetros de consulta
limitintegerDe 1 a 100. Padrão: 20.afterstringCursor da próxima página.beforestringCursor da página anterior.searchstringBusca no nome.statusstringdraft,activeoupaused.
cURL
curl 'https://api.postal.so/automations?status=active' \
-H "Authorization: Bearer $POSTAL_API_KEY"
Node.js
const response = await fetch('https://api.postal.so/automations?status=active', {
headers: {
Authorization: `Bearer ${process.env.POSTAL_API_KEY}`,
},
});
const data = await response.json();
Python
import os
import requests
response = requests.get(
"https://api.postal.so/automations",
headers={"Authorization": f"Bearer {os.environ['POSTAL_API_KEY']}"},
params={
"status": "active",
},
timeout=10,
)
data = response.json()
PHP
$client = new \GuzzleHttp\Client(['base_uri' => 'https://api.postal.so']);
$response = $client->get('automations', [
'headers' => ['Authorization' => 'Bearer '.getenv('POSTAL_API_KEY')],
'query' => [
'status' => 'active',
],
]);
$data = json_decode($response->getBody(), true);
{
"object": "list",
"has_more": false,
"data": [
{
"object": "automation",
"id": "019a1f60-6071-7c83-8e9f-0a1b2c3d4e5f",
"name": "Boas-vindas do teste grátis",
"status": "active",
"trigger": {
"type": "event",
"event": "trial.started",
"filters": [
{
"key": "plan",
"operator": "equals",
"value": "pro"
}
]
},
"reentry": "once",
"steps": [
{
"id": "welcome",
"type": "send_email",
"config": {
"template_id": "trial-welcome",
"from": "Ana da Loja Exemplo <[email protected]>",
"subject": null,
"reply_to": null,
"variables": {
"DAYS": "{{event.trial_days}}"
}
}
},
{
"id": "wait_2_days",
"type": "wait",
"config": {
"mode": "duration",
"amount": 2,
"unit": "days"
}
},
{
"id": "check_opened",
"type": "condition",
"config": {
"kind": "email_activity",
"step_id": "welcome",
"activity": "opened"
},
"branches": {
"yes": [
{
"id": "tag_engaged",
"type": "update_contact",
"config": {
"actions": [
{
"type": "add_to_segment",
"segment_id": "019a1d91-4c5d-7e6f-8a7b-8c9d0e1f2a3c"
}
]
}
}
],
"no": [
{
"id": "wait_morning",
"type": "wait",
"config": {
"mode": "until",
"time": "09:00",
"weekdays": [1, 2, 3, 4, 5],
"timezone": "America/Sao_Paulo"
}
},
{
"id": "reminder",
"type": "send_email",
"config": {
"template_id": "trial-help",
"from": null,
"subject": "{{contact.first_name}}, posso ajudar com o seu teste?",
"reply_to": null,
"variables": {}
}
},
{
"id": "notify_crm",
"type": "webhook",
"config": {
"url": "https://crm.lojaexemplo.com.br/hooks/postal"
}
}
]
}
}
],
"version": 2,
"runs_this_month": 318,
"runs_in_progress": 41,
"activated_at": "2026-10-15T13:00:00.000000Z",
"created_at": "2026-10-14T19:22:00.000000Z",
"updated_at": "2026-10-20T10:31:00.000000Z"
}
]
}
#Criar uma automação
POST/automations
Cria um rascunho. Erros de estrutura recusam o salvamento (um tipo de passo desconhecido, um passo depois de uma condição, um segmento de outro time, um ID repetido); o que está só faltando entra em issues e impede apenas a ativação. Devolve a automação completa, com issues e o webhook_signing_secret usado nos passos de webhook.
Corpo da requisição
Erros
- 422
validation_errorCampo inválido ou definição com erro. O campo extraerrorslista cada problema, com ostep_id(ounull, para o gatilho) e a mensagem.
cURL
curl -X POST https://api.postal.so/automations \
-H "Authorization: Bearer $POSTAL_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "Boas-vindas do teste grátis",
"trigger": {
"type": "event",
"event": "trial.started",
"filters": [
{
"key": "plan",
"operator": "equals",
"value": "pro"
}
]
},
"steps": [
{
"id": "welcome",
"type": "send_email",
"config": {
"template_id": "trial-welcome",
"from": "Ana da Loja Exemplo <[email protected]>",
"variables": {
"DAYS": "{{event.trial_days}}"
}
}
},
{
"id": "wait_2_days",
"type": "wait",
"config": {
"mode": "duration",
"amount": 2,
"unit": "days"
}
},
{
"id": "check_opened",
"type": "condition",
"config": {
"kind": "email_activity",
"step_id": "welcome",
"activity": "opened"
},
"branches": {
"yes": [
{
"id": "tag_engaged",
"type": "update_contact",
"config": {
"actions": [
{
"type": "add_to_segment",
"segment_id": "019a1d91-4c5d-7e6f-8a7b-8c9d0e1f2a3c"
}
]
}
}
],
"no": [
{
"id": "wait_morning",
"type": "wait",
"config": {
"mode": "until",
"time": "09:00",
"weekdays": [1, 2, 3, 4, 5],
"timezone": "America/Sao_Paulo"
}
},
{
"id": "reminder",
"type": "send_email",
"config": {
"template_id": "trial-help",
"subject": "{{contact.first_name}}, posso ajudar com o seu teste?"
}
},
{
"id": "notify_crm",
"type": "webhook",
"config": {
"url": "https://crm.lojaexemplo.com.br/hooks/postal"
}
}
]
}
}
]
}'
Node.js
const response = await fetch('https://api.postal.so/automations', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.POSTAL_API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
name: 'Boas-vindas do teste grátis',
trigger: {
type: 'event',
event: 'trial.started',
filters: [
{
key: 'plan',
operator: 'equals',
value: 'pro',
},
],
},
steps: [
{
id: 'welcome',
type: 'send_email',
config: {
template_id: 'trial-welcome',
from: 'Ana da Loja Exemplo <[email protected]>',
variables: {
DAYS: '{{event.trial_days}}',
},
},
},
{
id: 'wait_2_days',
type: 'wait',
config: {
mode: 'duration',
amount: 2,
unit: 'days',
},
},
{
id: 'check_opened',
type: 'condition',
config: {
kind: 'email_activity',
step_id: 'welcome',
activity: 'opened',
},
branches: {
yes: [
{
id: 'tag_engaged',
type: 'update_contact',
config: {
actions: [
{
type: 'add_to_segment',
segment_id: '019a1d91-4c5d-7e6f-8a7b-8c9d0e1f2a3c',
},
],
},
},
],
no: [
{
id: 'wait_morning',
type: 'wait',
config: {
mode: 'until',
time: '09:00',
weekdays: [1, 2, 3, 4, 5],
timezone: 'America/Sao_Paulo',
},
},
{
id: 'reminder',
type: 'send_email',
config: {
template_id: 'trial-help',
subject: '{{contact.first_name}}, posso ajudar com o seu teste?',
},
},
{
id: 'notify_crm',
type: 'webhook',
config: {
url: 'https://crm.lojaexemplo.com.br/hooks/postal',
},
},
],
},
},
],
}),
});
const data = await response.json();
Python
import os
import requests
response = requests.post(
"https://api.postal.so/automations",
headers={"Authorization": f"Bearer {os.environ['POSTAL_API_KEY']}"},
json={
"name": "Boas-vindas do teste grátis",
"trigger": {
"type": "event",
"event": "trial.started",
"filters": [
{
"key": "plan",
"operator": "equals",
"value": "pro",
},
],
},
"steps": [
{
"id": "welcome",
"type": "send_email",
"config": {
"template_id": "trial-welcome",
"from": "Ana da Loja Exemplo <[email protected]>",
"variables": {
"DAYS": "{{event.trial_days}}",
},
},
},
{
"id": "wait_2_days",
"type": "wait",
"config": {
"mode": "duration",
"amount": 2,
"unit": "days",
},
},
{
"id": "check_opened",
"type": "condition",
"config": {
"kind": "email_activity",
"step_id": "welcome",
"activity": "opened",
},
"branches": {
"yes": [
{
"id": "tag_engaged",
"type": "update_contact",
"config": {
"actions": [
{
"type": "add_to_segment",
"segment_id": "019a1d91-4c5d-7e6f-8a7b-8c9d0e1f2a3c",
},
],
},
},
],
"no": [
{
"id": "wait_morning",
"type": "wait",
"config": {
"mode": "until",
"time": "09:00",
"weekdays": [1, 2, 3, 4, 5],
"timezone": "America/Sao_Paulo",
},
},
{
"id": "reminder",
"type": "send_email",
"config": {
"template_id": "trial-help",
"subject": "{{contact.first_name}}, posso ajudar com o seu teste?",
},
},
{
"id": "notify_crm",
"type": "webhook",
"config": {
"url": "https://crm.lojaexemplo.com.br/hooks/postal",
},
},
],
},
},
],
},
timeout=10,
)
data = response.json()
PHP
$client = new \GuzzleHttp\Client(['base_uri' => 'https://api.postal.so']);
$response = $client->post('automations', [
'headers' => ['Authorization' => 'Bearer '.getenv('POSTAL_API_KEY')],
'json' => [
'name' => 'Boas-vindas do teste grátis',
'trigger' => [
'type' => 'event',
'event' => 'trial.started',
'filters' => [
[
'key' => 'plan',
'operator' => 'equals',
'value' => 'pro',
],
],
],
'steps' => [
[
'id' => 'welcome',
'type' => 'send_email',
'config' => [
'template_id' => 'trial-welcome',
'from' => 'Ana da Loja Exemplo <[email protected]>',
'variables' => [
'DAYS' => '{{event.trial_days}}',
],
],
],
[
'id' => 'wait_2_days',
'type' => 'wait',
'config' => [
'mode' => 'duration',
'amount' => 2,
'unit' => 'days',
],
],
[
'id' => 'check_opened',
'type' => 'condition',
'config' => [
'kind' => 'email_activity',
'step_id' => 'welcome',
'activity' => 'opened',
],
'branches' => [
'yes' => [
[
'id' => 'tag_engaged',
'type' => 'update_contact',
'config' => [
'actions' => [
[
'type' => 'add_to_segment',
'segment_id' => '019a1d91-4c5d-7e6f-8a7b-8c9d0e1f2a3c',
],
],
],
],
],
'no' => [
[
'id' => 'wait_morning',
'type' => 'wait',
'config' => [
'mode' => 'until',
'time' => '09:00',
'weekdays' => [1, 2, 3, 4, 5],
'timezone' => 'America/Sao_Paulo',
],
],
[
'id' => 'reminder',
'type' => 'send_email',
'config' => [
'template_id' => 'trial-help',
'subject' => '{{contact.first_name}}, posso ajudar com o seu teste?',
],
],
[
'id' => 'notify_crm',
'type' => 'webhook',
'config' => [
'url' => 'https://crm.lojaexemplo.com.br/hooks/postal',
],
],
],
],
],
],
],
]);
$data = json_decode($response->getBody(), true);
{
"object": "automation",
"id": "019a1f60-6071-7c83-8e9f-0a1b2c3d4e5f",
"name": "Boas-vindas do teste grátis",
"status": "draft",
"trigger": {
"type": "event",
"event": "trial.started",
"filters": [
{
"key": "plan",
"operator": "equals",
"value": "pro"
}
]
},
"reentry": "once",
"steps": [
{
"id": "welcome",
"type": "send_email",
"config": {
"template_id": "trial-welcome",
"from": "Ana da Loja Exemplo <[email protected]>",
"subject": null,
"reply_to": null,
"variables": {
"DAYS": "{{event.trial_days}}"
}
}
},
{
"id": "wait_2_days",
"type": "wait",
"config": {
"mode": "duration",
"amount": 2,
"unit": "days"
}
},
{
"id": "check_opened",
"type": "condition",
"config": {
"kind": "email_activity",
"step_id": "welcome",
"activity": "opened"
},
"branches": {
"yes": [
{
"id": "tag_engaged",
"type": "update_contact",
"config": {
"actions": [
{
"type": "add_to_segment",
"segment_id": "019a1d91-4c5d-7e6f-8a7b-8c9d0e1f2a3c"
}
]
}
}
],
"no": [
{
"id": "wait_morning",
"type": "wait",
"config": {
"mode": "until",
"time": "09:00",
"weekdays": [1, 2, 3, 4, 5],
"timezone": "America/Sao_Paulo"
}
},
{
"id": "reminder",
"type": "send_email",
"config": {
"template_id": "trial-help",
"from": null,
"subject": "{{contact.first_name}}, posso ajudar com o seu teste?",
"reply_to": null,
"variables": {}
}
},
{
"id": "notify_crm",
"type": "webhook",
"config": {
"url": "https://crm.lojaexemplo.com.br/hooks/postal"
}
}
]
}
}
],
"version": null,
"runs_this_month": 0,
"runs_in_progress": 0,
"activated_at": null,
"created_at": "2026-10-14T19:22:00.000000Z",
"updated_at": "2026-10-14T19:22:00.000000Z",
"issues": [],
"webhook_signing_secret": "whsec_YXV0b21hY2FvLWV4ZW1wbG8tYWJjZGVmMTIzNA=="
}
{
"statusCode": 422,
"name": "validation_error",
"message": "A condition must be the last step of its path: continue in its branches.",
"errors": [
{
"step_id": "check_opened",
"message": "A condition must be the last step of its path: continue in its branches."
}
]
}
#Obter uma automação
GET/automations/{id}
Devolve a automação com issues (o que impede a ativação, cada um com step_id e message) e o webhook_signing_secret.
Parâmetros de caminho
idstringobrigatórioID da automação.
Erros
- 404
not_foundO recurso não existe ou é de outro time.
cURL
curl https://api.postal.so/automations/019a1f60-6071-7c83-8e9f-0a1b2c3d4e5f \
-H "Authorization: Bearer $POSTAL_API_KEY"
Node.js
const response = await fetch('https://api.postal.so/automations/019a1f60-6071-7c83-8e9f-0a1b2c3d4e5f', {
headers: {
Authorization: `Bearer ${process.env.POSTAL_API_KEY}`,
},
});
const data = await response.json();
Python
import os
import requests
response = requests.get(
"https://api.postal.so/automations/019a1f60-6071-7c83-8e9f-0a1b2c3d4e5f",
headers={"Authorization": f"Bearer {os.environ['POSTAL_API_KEY']}"},
timeout=10,
)
data = response.json()
PHP
$client = new \GuzzleHttp\Client(['base_uri' => 'https://api.postal.so']);
$response = $client->get('automations/019a1f60-6071-7c83-8e9f-0a1b2c3d4e5f', [
'headers' => ['Authorization' => 'Bearer '.getenv('POSTAL_API_KEY')],
]);
$data = json_decode($response->getBody(), true);
{
"object": "automation",
"id": "019a1f60-6071-7c83-8e9f-0a1b2c3d4e5f",
"name": "Boas-vindas do teste grátis",
"status": "active",
"trigger": {
"type": "event",
"event": "trial.started",
"filters": [
{
"key": "plan",
"operator": "equals",
"value": "pro"
}
]
},
"reentry": "once",
"steps": [
{
"id": "welcome",
"type": "send_email",
"config": {
"template_id": "trial-welcome",
"from": "Ana da Loja Exemplo <[email protected]>",
"subject": null,
"reply_to": null,
"variables": {
"DAYS": "{{event.trial_days}}"
}
}
},
{
"id": "wait_2_days",
"type": "wait",
"config": {
"mode": "duration",
"amount": 2,
"unit": "days"
}
},
{
"id": "check_opened",
"type": "condition",
"config": {
"kind": "email_activity",
"step_id": "welcome",
"activity": "opened"
},
"branches": {
"yes": [
{
"id": "tag_engaged",
"type": "update_contact",
"config": {
"actions": [
{
"type": "add_to_segment",
"segment_id": "019a1d91-4c5d-7e6f-8a7b-8c9d0e1f2a3c"
}
]
}
}
],
"no": [
{
"id": "wait_morning",
"type": "wait",
"config": {
"mode": "until",
"time": "09:00",
"weekdays": [1, 2, 3, 4, 5],
"timezone": "America/Sao_Paulo"
}
},
{
"id": "reminder",
"type": "send_email",
"config": {
"template_id": "trial-help",
"from": null,
"subject": "{{contact.first_name}}, posso ajudar com o seu teste?",
"reply_to": null,
"variables": {}
}
},
{
"id": "notify_crm",
"type": "webhook",
"config": {
"url": "https://crm.lojaexemplo.com.br/hooks/postal"
}
}
]
}
}
],
"version": 2,
"runs_this_month": 318,
"runs_in_progress": 41,
"activated_at": "2026-10-15T13:00:00.000000Z",
"created_at": "2026-10-14T19:22:00.000000Z",
"updated_at": "2026-10-20T10:31:00.000000Z",
"issues": [],
"webhook_signing_secret": "whsec_YXV0b21hY2FvLWV4ZW1wbG8tYWJjZGVmMTIzNA=="
}
#Atualizar uma automação
PATCH/automations/{id}
Só os campos enviados mudam; trigger e steps substituem os anteriores por inteiro. Num rascunho ou numa automação pausada, a definição pode ficar incompleta. Numa automação ativa, ela precisa estar completa, e a mudança vira uma nova versão, que vale só para as novas execuções. Devolve a automação completa.
Parâmetros de caminho
idstringobrigatórioID da automação.
Corpo da requisição (todos opcionais)
namestringNovo nome.triggerobjectNovo gatilho.stepsobject[]Nova lista de passos.reentrystringonceouevery_time.
Erros
- 422
validation_errorDefinição com erro ou, numa automação ativa, incompleta. Vejaerrors. - 404
not_foundO recurso não existe ou é de outro time.
cURL
curl -X PATCH https://api.postal.so/automations/019a1f60-6071-7c83-8e9f-0a1b2c3d4e5f \
-H "Authorization: Bearer $POSTAL_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"reentry": "every_time"
}'
Node.js
const response = await fetch('https://api.postal.so/automations/019a1f60-6071-7c83-8e9f-0a1b2c3d4e5f', {
method: 'PATCH',
headers: {
Authorization: `Bearer ${process.env.POSTAL_API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
reentry: 'every_time',
}),
});
const data = await response.json();
Python
import os
import requests
response = requests.patch(
"https://api.postal.so/automations/019a1f60-6071-7c83-8e9f-0a1b2c3d4e5f",
headers={"Authorization": f"Bearer {os.environ['POSTAL_API_KEY']}"},
json={
"reentry": "every_time",
},
timeout=10,
)
data = response.json()
PHP
$client = new \GuzzleHttp\Client(['base_uri' => 'https://api.postal.so']);
$response = $client->patch('automations/019a1f60-6071-7c83-8e9f-0a1b2c3d4e5f', [
'headers' => ['Authorization' => 'Bearer '.getenv('POSTAL_API_KEY')],
'json' => [
'reentry' => 'every_time',
],
]);
$data = json_decode($response->getBody(), true);
{
"object": "automation",
"id": "019a1f60-6071-7c83-8e9f-0a1b2c3d4e5f",
"name": "Boas-vindas do teste grátis",
"status": "active",
"trigger": {
"type": "event",
"event": "trial.started",
"filters": [
{
"key": "plan",
"operator": "equals",
"value": "pro"
}
]
},
"reentry": "every_time",
"steps": [
{
"id": "welcome",
"type": "send_email",
"config": {
"template_id": "trial-welcome",
"from": "Ana da Loja Exemplo <[email protected]>",
"subject": null,
"reply_to": null,
"variables": {
"DAYS": "{{event.trial_days}}"
}
}
},
{
"id": "wait_2_days",
"type": "wait",
"config": {
"mode": "duration",
"amount": 2,
"unit": "days"
}
},
{
"id": "check_opened",
"type": "condition",
"config": {
"kind": "email_activity",
"step_id": "welcome",
"activity": "opened"
},
"branches": {
"yes": [
{
"id": "tag_engaged",
"type": "update_contact",
"config": {
"actions": [
{
"type": "add_to_segment",
"segment_id": "019a1d91-4c5d-7e6f-8a7b-8c9d0e1f2a3c"
}
]
}
}
],
"no": [
{
"id": "wait_morning",
"type": "wait",
"config": {
"mode": "until",
"time": "09:00",
"weekdays": [1, 2, 3, 4, 5],
"timezone": "America/Sao_Paulo"
}
},
{
"id": "reminder",
"type": "send_email",
"config": {
"template_id": "trial-help",
"from": null,
"subject": "{{contact.first_name}}, posso ajudar com o seu teste?",
"reply_to": null,
"variables": {}
}
},
{
"id": "notify_crm",
"type": "webhook",
"config": {
"url": "https://crm.lojaexemplo.com.br/hooks/postal"
}
}
]
}
}
],
"version": 3,
"runs_this_month": 318,
"runs_in_progress": 41,
"activated_at": "2026-10-15T13:00:00.000000Z",
"created_at": "2026-10-14T19:22:00.000000Z",
"updated_at": "2026-10-24T16:30:00.000000Z",
"issues": [],
"webhook_signing_secret": "whsec_YXV0b21hY2FvLWV4ZW1wbG8tYWJjZGVmMTIzNA=="
}
#Excluir uma automação
DELETE/automations/{id}
Apaga a automação com as versões e as execuções; as que estavam em andamento param. Para só interromper, prefira pausar.
Parâmetros de caminho
idstringobrigatórioID da automação.
Erros
- 404
not_foundO recurso não existe ou é de outro time.
cURL
curl -X DELETE https://api.postal.so/automations/019a1f60-6071-7c83-8e9f-0a1b2c3d4e5f \
-H "Authorization: Bearer $POSTAL_API_KEY"
Node.js
const response = await fetch('https://api.postal.so/automations/019a1f60-6071-7c83-8e9f-0a1b2c3d4e5f', {
method: 'DELETE',
headers: {
Authorization: `Bearer ${process.env.POSTAL_API_KEY}`,
},
});
const data = await response.json();
Python
import os
import requests
response = requests.delete(
"https://api.postal.so/automations/019a1f60-6071-7c83-8e9f-0a1b2c3d4e5f",
headers={"Authorization": f"Bearer {os.environ['POSTAL_API_KEY']}"},
timeout=10,
)
data = response.json()
PHP
$client = new \GuzzleHttp\Client(['base_uri' => 'https://api.postal.so']);
$response = $client->delete('automations/019a1f60-6071-7c83-8e9f-0a1b2c3d4e5f', [
'headers' => ['Authorization' => 'Bearer '.getenv('POSTAL_API_KEY')],
]);
$data = json_decode($response->getBody(), true);
{
"object": "automation",
"id": "019a1f60-6071-7c83-8e9f-0a1b2c3d4e5f",
"deleted": true
}
#Ativar
POST/automations/{id}/activate
Ativa um rascunho ou retoma uma automação pausada. A definição precisa estar completa: templates escolhidos e publicados, remetente de domínio verificado, caminhos das condições com ao menos um passo, URLs dos webhooks… Publica a definição como versão (se mudou desde a última) e devolve a automação.
Parâmetros de caminho
idstringobrigatórioID da automação.
Erros
- 422
validation_errorA definição tem erros ou ainda está incompleta.errorslista tudo o que falta. - 404
not_foundO recurso não existe ou é de outro time.
cURL
curl -X POST https://api.postal.so/automations/019a1f60-6071-7c83-8e9f-0a1b2c3d4e5f/activate \
-H "Authorization: Bearer $POSTAL_API_KEY"
Node.js
const response = await fetch('https://api.postal.so/automations/019a1f60-6071-7c83-8e9f-0a1b2c3d4e5f/activate', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.POSTAL_API_KEY}`,
},
});
const data = await response.json();
Python
import os
import requests
response = requests.post(
"https://api.postal.so/automations/019a1f60-6071-7c83-8e9f-0a1b2c3d4e5f/activate",
headers={"Authorization": f"Bearer {os.environ['POSTAL_API_KEY']}"},
timeout=10,
)
data = response.json()
PHP
$client = new \GuzzleHttp\Client(['base_uri' => 'https://api.postal.so']);
$response = $client->post('automations/019a1f60-6071-7c83-8e9f-0a1b2c3d4e5f/activate', [
'headers' => ['Authorization' => 'Bearer '.getenv('POSTAL_API_KEY')],
]);
$data = json_decode($response->getBody(), true);
{
"object": "automation",
"id": "019a1f60-6071-7c83-8e9f-0a1b2c3d4e5f",
"name": "Boas-vindas do teste grátis",
"status": "active",
"trigger": {
"type": "event",
"event": "trial.started",
"filters": [
{
"key": "plan",
"operator": "equals",
"value": "pro"
}
]
},
"reentry": "once",
"steps": [
{
"id": "welcome",
"type": "send_email",
"config": {
"template_id": "trial-welcome",
"from": "Ana da Loja Exemplo <[email protected]>",
"subject": null,
"reply_to": null,
"variables": {
"DAYS": "{{event.trial_days}}"
}
}
},
{
"id": "wait_2_days",
"type": "wait",
"config": {
"mode": "duration",
"amount": 2,
"unit": "days"
}
},
{
"id": "check_opened",
"type": "condition",
"config": {
"kind": "email_activity",
"step_id": "welcome",
"activity": "opened"
},
"branches": {
"yes": [
{
"id": "tag_engaged",
"type": "update_contact",
"config": {
"actions": [
{
"type": "add_to_segment",
"segment_id": "019a1d91-4c5d-7e6f-8a7b-8c9d0e1f2a3c"
}
]
}
}
],
"no": [
{
"id": "wait_morning",
"type": "wait",
"config": {
"mode": "until",
"time": "09:00",
"weekdays": [1, 2, 3, 4, 5],
"timezone": "America/Sao_Paulo"
}
},
{
"id": "reminder",
"type": "send_email",
"config": {
"template_id": "trial-help",
"from": null,
"subject": "{{contact.first_name}}, posso ajudar com o seu teste?",
"reply_to": null,
"variables": {}
}
},
{
"id": "notify_crm",
"type": "webhook",
"config": {
"url": "https://crm.lojaexemplo.com.br/hooks/postal"
}
}
]
}
}
],
"version": 2,
"runs_this_month": 318,
"runs_in_progress": 41,
"activated_at": "2026-10-15T13:00:00.000000Z",
"created_at": "2026-10-14T19:22:00.000000Z",
"updated_at": "2026-10-20T10:31:00.000000Z",
"issues": [],
"webhook_signing_secret": "whsec_YXV0b21hY2FvLWV4ZW1wbG8tYWJjZGVmMTIzNA=="
}
{
"statusCode": 422,
"name": "validation_error",
"message": "The automation is not complete yet. Choose the template to send.",
"errors": [
{
"step_id": "welcome",
"message": "Choose the template to send."
},
{
"step_id": null,
"message": "Choose the event that starts the automation."
}
]
}
#Pausar
POST/automations/{id}/pause
Para de iniciar execuções. As que estão esperando ficam paradas e continuam de onde estavam quando a automação for ativada de novo; uma espera que venceu nesse meio-tempo segue logo depois.
Parâmetros de caminho
idstringobrigatórioID da automação.
Erros
- 422
validation_errorA automação não está ativa. - 404
not_foundO recurso não existe ou é de outro time.
cURL
curl -X POST https://api.postal.so/automations/019a1f60-6071-7c83-8e9f-0a1b2c3d4e5f/pause \
-H "Authorization: Bearer $POSTAL_API_KEY"
Node.js
const response = await fetch('https://api.postal.so/automations/019a1f60-6071-7c83-8e9f-0a1b2c3d4e5f/pause', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.POSTAL_API_KEY}`,
},
});
const data = await response.json();
Python
import os
import requests
response = requests.post(
"https://api.postal.so/automations/019a1f60-6071-7c83-8e9f-0a1b2c3d4e5f/pause",
headers={"Authorization": f"Bearer {os.environ['POSTAL_API_KEY']}"},
timeout=10,
)
data = response.json()
PHP
$client = new \GuzzleHttp\Client(['base_uri' => 'https://api.postal.so']);
$response = $client->post('automations/019a1f60-6071-7c83-8e9f-0a1b2c3d4e5f/pause', [
'headers' => ['Authorization' => 'Bearer '.getenv('POSTAL_API_KEY')],
]);
$data = json_decode($response->getBody(), true);
{
"object": "automation",
"id": "019a1f60-6071-7c83-8e9f-0a1b2c3d4e5f",
"name": "Boas-vindas do teste grátis",
"status": "paused",
"trigger": {
"type": "event",
"event": "trial.started",
"filters": [
{
"key": "plan",
"operator": "equals",
"value": "pro"
}
]
},
"reentry": "once",
"steps": [
{
"id": "welcome",
"type": "send_email",
"config": {
"template_id": "trial-welcome",
"from": "Ana da Loja Exemplo <[email protected]>",
"subject": null,
"reply_to": null,
"variables": {
"DAYS": "{{event.trial_days}}"
}
}
},
{
"id": "wait_2_days",
"type": "wait",
"config": {
"mode": "duration",
"amount": 2,
"unit": "days"
}
},
{
"id": "check_opened",
"type": "condition",
"config": {
"kind": "email_activity",
"step_id": "welcome",
"activity": "opened"
},
"branches": {
"yes": [
{
"id": "tag_engaged",
"type": "update_contact",
"config": {
"actions": [
{
"type": "add_to_segment",
"segment_id": "019a1d91-4c5d-7e6f-8a7b-8c9d0e1f2a3c"
}
]
}
}
],
"no": [
{
"id": "wait_morning",
"type": "wait",
"config": {
"mode": "until",
"time": "09:00",
"weekdays": [1, 2, 3, 4, 5],
"timezone": "America/Sao_Paulo"
}
},
{
"id": "reminder",
"type": "send_email",
"config": {
"template_id": "trial-help",
"from": null,
"subject": "{{contact.first_name}}, posso ajudar com o seu teste?",
"reply_to": null,
"variables": {}
}
},
{
"id": "notify_crm",
"type": "webhook",
"config": {
"url": "https://crm.lojaexemplo.com.br/hooks/postal"
}
}
]
}
}
],
"version": 2,
"runs_this_month": 318,
"runs_in_progress": 41,
"activated_at": "2026-10-15T13:00:00.000000Z",
"created_at": "2026-10-14T19:22:00.000000Z",
"updated_at": "2026-10-24T16:35:00.000000Z",
"issues": [],
"webhook_signing_secret": "whsec_YXV0b21hY2FvLWV4ZW1wbG8tYWJjZGVmMTIzNA=="
}
#Execuções
| Status | O que significa |
|---|---|
running | Executando passos agora. |
waiting | Esperando até next_run_at: um passo wait ou uma nova tentativa de webhook. current_step_id é o próximo passo. |
completed | Chegou ao fim de um caminho ou a um exit. |
failed | Um passo falhou; o motivo está em error e no registro do passo. |
canceled | Cancelada pelo painel ou pela API. |
skipped | Não começou: o limite mensal de execuções do plano tinha acabado. |
Cada passo executado fica registrado em steps, com status (running, waiting, completed, failed ou skipped), tentativas, erro e uma saída (output): {"until"} numa espera, {"email_id", "to", "subject"} num envio, {"result": "yes"} numa condição, {"changes": […]} numa mudança de contato e {"status_code"} num webhook.
#Listar execuções
GET/automations/{id}/runs
As execuções da automação, da mais recente para a mais antiga, com a definição da versão que cada uma segue (definition). O registro dos passos só vem em obter uma execução.
Parâmetros de caminho
idstringobrigatórioID da automação.
Parâmetros de consulta
limitintegerDe 1 a 100. Padrão: 20.afterstringCursor da próxima página.beforestringCursor da página anterior.statusstringUm ou mais status separados por vírgula, comorunning,waiting.contactstringID ou e-mail do contato.
Erros
- 422
validation_errorAlgum campo é inválido. A mensagem diz qual. - 404
not_foundO recurso não existe ou é de outro time.
cURL
curl 'https://api.postal.so/automations/019a1f60-6071-7c83-8e9f-0a1b2c3d4e5f/runs?status=waiting,failed' \
-H "Authorization: Bearer $POSTAL_API_KEY"
Node.js
const response = await fetch('https://api.postal.so/automations/019a1f60-6071-7c83-8e9f-0a1b2c3d4e5f/runs?status=waiting,failed', {
headers: {
Authorization: `Bearer ${process.env.POSTAL_API_KEY}`,
},
});
const data = await response.json();
Python
import os
import requests
response = requests.get(
"https://api.postal.so/automations/019a1f60-6071-7c83-8e9f-0a1b2c3d4e5f/runs",
headers={"Authorization": f"Bearer {os.environ['POSTAL_API_KEY']}"},
params={
"status": "waiting,failed",
},
timeout=10,
)
data = response.json()
PHP
$client = new \GuzzleHttp\Client(['base_uri' => 'https://api.postal.so']);
$response = $client->get('automations/019a1f60-6071-7c83-8e9f-0a1b2c3d4e5f/runs', [
'headers' => ['Authorization' => 'Bearer '.getenv('POSTAL_API_KEY')],
'query' => [
'status' => 'waiting,failed',
],
]);
$data = json_decode($response->getBody(), true);
{
"object": "list",
"has_more": true,
"data": [
{
"object": "automation_run",
"id": "019a1f70-7182-7d94-9fa0-1b2c3d4e5f60",
"automation_id": "019a1f60-6071-7c83-8e9f-0a1b2c3d4e5f",
"version": 2,
"contact_id": "019a1e00-1a2b-7c3d-8e4f-5a6b7c8d9e0f",
"contact_email": "[email protected]",
"status": "waiting",
"trigger": {
"type": "event",
"event_id": "019a1f40-5f60-7b72-9d8e-9f0a1b2c3d4e",
"event": "trial.started",
"properties": {
"plan": "pro",
"source": "website",
"trial_days": 14
}
},
"current_step_id": "check_opened",
"next_run_at": "2026-10-26T14:20:02.000000Z",
"error": null,
"started_at": "2026-10-24T14:20:01.000000Z",
"finished_at": null,
"created_at": "2026-10-24T14:20:01.000000Z",
"definition": [
{
"id": "welcome",
"…": "…"
}
]
}
]
}
#Obter uma execução
GET/automation-runs/{id}
A execução com o que a iniciou (trigger: o tipo e, conforme o gatilho, o evento com as propriedades, o segmento ou o formulário), a definição da versão e o registro de cada passo.
Parâmetros de caminho
idstringobrigatórioID da execução.
Erros
- 404
not_foundO recurso não existe ou é de outro time.
cURL
curl https://api.postal.so/automation-runs/019a1f70-7182-7d94-9fa0-1b2c3d4e5f60 \
-H "Authorization: Bearer $POSTAL_API_KEY"
Node.js
const response = await fetch('https://api.postal.so/automation-runs/019a1f70-7182-7d94-9fa0-1b2c3d4e5f60', {
headers: {
Authorization: `Bearer ${process.env.POSTAL_API_KEY}`,
},
});
const data = await response.json();
Python
import os
import requests
response = requests.get(
"https://api.postal.so/automation-runs/019a1f70-7182-7d94-9fa0-1b2c3d4e5f60",
headers={"Authorization": f"Bearer {os.environ['POSTAL_API_KEY']}"},
timeout=10,
)
data = response.json()
PHP
$client = new \GuzzleHttp\Client(['base_uri' => 'https://api.postal.so']);
$response = $client->get('automation-runs/019a1f70-7182-7d94-9fa0-1b2c3d4e5f60', [
'headers' => ['Authorization' => 'Bearer '.getenv('POSTAL_API_KEY')],
]);
$data = json_decode($response->getBody(), true);
{
"object": "automation_run",
"id": "019a1f70-7182-7d94-9fa0-1b2c3d4e5f60",
"automation_id": "019a1f60-6071-7c83-8e9f-0a1b2c3d4e5f",
"automation_name": "Boas-vindas do teste grátis",
"version": 2,
"contact_id": "019a1e00-1a2b-7c3d-8e4f-5a6b7c8d9e0f",
"contact_email": "[email protected]",
"status": "waiting",
"trigger": {
"type": "event",
"event_id": "019a1f40-5f60-7b72-9d8e-9f0a1b2c3d4e",
"event": "trial.started",
"properties": {
"plan": "pro",
"source": "website",
"trial_days": 14
}
},
"current_step_id": "check_opened",
"next_run_at": "2026-10-26T14:20:02.000000Z",
"error": null,
"started_at": "2026-10-24T14:20:01.000000Z",
"finished_at": null,
"created_at": "2026-10-24T14:20:01.000000Z",
"definition": [
{
"id": "welcome",
"type": "send_email",
"config": {
"template_id": "trial-welcome",
"from": "Ana da Loja Exemplo <[email protected]>",
"subject": null,
"reply_to": null,
"variables": {
"DAYS": "{{event.trial_days}}"
}
}
},
{
"id": "wait_2_days",
"type": "wait",
"config": {
"mode": "duration",
"amount": 2,
"unit": "days"
}
},
{
"id": "check_opened",
"type": "condition",
"config": {
"kind": "email_activity",
"step_id": "welcome",
"activity": "opened"
},
"branches": {
"yes": [
{
"id": "tag_engaged",
"type": "update_contact",
"config": {
"actions": [
{
"type": "add_to_segment",
"segment_id": "019a1d91-4c5d-7e6f-8a7b-8c9d0e1f2a3c"
}
]
}
}
],
"no": [
{
"id": "wait_morning",
"type": "wait",
"config": {
"mode": "until",
"time": "09:00",
"weekdays": [1, 2, 3, 4, 5],
"timezone": "America/Sao_Paulo"
}
},
{
"id": "reminder",
"type": "send_email",
"config": {
"template_id": "trial-help",
"from": null,
"subject": "{{contact.first_name}}, posso ajudar com o seu teste?",
"reply_to": null,
"variables": {}
}
},
{
"id": "notify_crm",
"type": "webhook",
"config": {
"url": "https://crm.lojaexemplo.com.br/hooks/postal"
}
}
]
}
}
],
"steps": [
{
"object": "automation_run_step",
"id": "019a1f70-7183-7ea5-8ab1-2c3d4e5f6071",
"step_id": "welcome",
"type": "send_email",
"status": "completed",
"attempts": 1,
"output": {
"email_id": "019a1b2c-4d5e-7f60-8a9b-0c1d2e3f4a5b",
"to": "[email protected]",
"subject": "Ana, seu teste do plano Pro começou"
},
"error": null,
"started_at": "2026-10-24T14:20:01.000000Z",
"finished_at": "2026-10-24T14:20:02.000000Z"
},
{
"object": "automation_run_step",
"id": "019a1f70-7184-7fb6-9bc2-3d4e5f607182",
"step_id": "wait_2_days",
"type": "wait",
"status": "waiting",
"attempts": 1,
"output": {
"until": "2026-10-26T14:20:02Z"
},
"error": null,
"started_at": "2026-10-24T14:20:02.000000Z",
"finished_at": null
}
]
}
#Cancelar uma execução
POST/automation-runs/{id}/cancel
Para uma execução em andamento ou esperando; a espera pendente fica skipped. Devolve a execução.
Parâmetros de caminho
idstringobrigatórioID da execução.
Erros
- 422
validation_errorA execução já terminou. - 404
not_foundO recurso não existe ou é de outro time.
cURL
curl -X POST https://api.postal.so/automation-runs/019a1f70-7182-7d94-9fa0-1b2c3d4e5f60/cancel \
-H "Authorization: Bearer $POSTAL_API_KEY"
Node.js
const response = await fetch('https://api.postal.so/automation-runs/019a1f70-7182-7d94-9fa0-1b2c3d4e5f60/cancel', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.POSTAL_API_KEY}`,
},
});
const data = await response.json();
Python
import os
import requests
response = requests.post(
"https://api.postal.so/automation-runs/019a1f70-7182-7d94-9fa0-1b2c3d4e5f60/cancel",
headers={"Authorization": f"Bearer {os.environ['POSTAL_API_KEY']}"},
timeout=10,
)
data = response.json()
PHP
$client = new \GuzzleHttp\Client(['base_uri' => 'https://api.postal.so']);
$response = $client->post('automation-runs/019a1f70-7182-7d94-9fa0-1b2c3d4e5f60/cancel', [
'headers' => ['Authorization' => 'Bearer '.getenv('POSTAL_API_KEY')],
]);
$data = json_decode($response->getBody(), true);
{
"object": "automation_run",
"id": "019a1f70-7182-7d94-9fa0-1b2c3d4e5f60",
"automation_id": "019a1f60-6071-7c83-8e9f-0a1b2c3d4e5f",
"automation_name": "Boas-vindas do teste grátis",
"version": 2,
"contact_id": "019a1e00-1a2b-7c3d-8e4f-5a6b7c8d9e0f",
"contact_email": "[email protected]",
"status": "canceled",
"trigger": {
"type": "event",
"event_id": "019a1f40-5f60-7b72-9d8e-9f0a1b2c3d4e",
"event": "trial.started",
"properties": {
"plan": "pro",
"source": "website",
"trial_days": 14
}
},
"current_step_id": "check_opened",
"next_run_at": null,
"error": "Canceled from the dashboard or API.",
"started_at": "2026-10-24T14:20:01.000000Z",
"finished_at": "2026-10-25T09:12:00.000000Z",
"created_at": "2026-10-24T14:20:01.000000Z",
"definition": [
{
"id": "welcome",
"type": "send_email",
"config": {
"template_id": "trial-welcome",
"from": "Ana da Loja Exemplo <[email protected]>",
"subject": null,
"reply_to": null,
"variables": {
"DAYS": "{{event.trial_days}}"
}
}
},
{
"id": "wait_2_days",
"type": "wait",
"config": {
"mode": "duration",
"amount": 2,
"unit": "days"
}
},
{
"id": "check_opened",
"type": "condition",
"config": {
"kind": "email_activity",
"step_id": "welcome",
"activity": "opened"
},
"branches": {
"yes": [
{
"id": "tag_engaged",
"type": "update_contact",
"config": {
"actions": [
{
"type": "add_to_segment",
"segment_id": "019a1d91-4c5d-7e6f-8a7b-8c9d0e1f2a3c"
}
]
}
}
],
"no": [
{
"id": "wait_morning",
"type": "wait",
"config": {
"mode": "until",
"time": "09:00",
"weekdays": [1, 2, 3, 4, 5],
"timezone": "America/Sao_Paulo"
}
},
{
"id": "reminder",
"type": "send_email",
"config": {
"template_id": "trial-help",
"from": null,
"subject": "{{contact.first_name}}, posso ajudar com o seu teste?",
"reply_to": null,
"variables": {}
}
},
{
"id": "notify_crm",
"type": "webhook",
"config": {
"url": "https://crm.lojaexemplo.com.br/hooks/postal"
}
}
]
}
}
],
"steps": [
{
"object": "automation_run_step",
"id": "019a1f70-7183-7ea5-8ab1-2c3d4e5f6071",
"step_id": "welcome",
"type": "send_email",
"status": "completed",
"attempts": 1,
"output": {
"email_id": "019a1b2c-4d5e-7f60-8a9b-0c1d2e3f4a5b",
"to": "[email protected]",
"subject": "Ana, seu teste do plano Pro começou"
},
"error": null,
"started_at": "2026-10-24T14:20:01.000000Z",
"finished_at": "2026-10-24T14:20:02.000000Z"
},
{
"object": "automation_run_step",
"id": "019a1f70-7184-7fb6-9bc2-3d4e5f607182",
"step_id": "wait_2_days",
"type": "wait",
"status": "skipped",
"attempts": 1,
"output": {
"until": "2026-10-26T14:20:02Z"
},
"error": null,
"started_at": "2026-10-24T14:20:02.000000Z",
"finished_at": "2026-10-25T09:12:00.000000Z"
}
]
}
#Passo de webhook
O passo webhook faz um POST com JSON para a sua URL (HTTPS e pública), com o contato e o evento que iniciou a execução:
{
"type": "automation.webhook",
"created_at": "2026-10-28T12:00:03.410Z",
"data": {
"automation_id": "019a1f60-6071-7c83-8e9f-0a1b2c3d4e5f",
"automation_name": "Boas-vindas do teste grátis",
"run_id": "019a1f70-7182-7d94-9fa0-1b2c3d4e5f60",
"step_id": "notify_crm",
"trigger": "event",
"contact": {
"id": "019a1e00-1a2b-7c3d-8e4f-5a6b7c8d9e0f",
"email": "[email protected]",
"first_name": "Ana",
"last_name": "Souza",
"unsubscribed": false,
"properties": {
"plan": "pro",
"city": "Recife"
},
"created_at": "2026-10-24T14:00:00.000Z",
"updated_at": "2026-10-24T14:00:00.000Z"
},
"event": {
"id": "019a1f40-5f60-7b72-9d8e-9f0a1b2c3d4e",
"name": "trial.started",
"properties": {
"plan": "pro",
"source": "website",
"trial_days": 14
}
}
}
}
A requisição é assinada como os webhooks da Postal, com os cabeçalhos webhook-id, webhook-timestamp e webhook-signature (e os equivalentes svix-*), mas usando o webhook_signing_secret da automação, que aparece em GET /automations/{id}. O mesmo código de verificação serve. O webhook-id é o ID do registro do passo e se repete nas novas tentativas, para você descartar duplicatas.
- Responda com
2xxem até 15 segundos. Redirecionamentos não são seguidos e endereços de rede privada são recusados. - Qualquer outra resposta conta como falha. São 3 tentativas: a segunda 1 minuto depois, a terceira 10 minutos depois. Depois disso, o passo e a execução ficam
failed. - As entregas usam o User-Agent
Postal-Webhooks/1.0.