Integrações

Supabase

Usuários do Supabase Auth viram contatos, e os e-mails de autenticação saem pela Postal com o Send Email Hook.

A integração do Supabase tem duas partes, na mesma conexão: os usuários do Supabase Auth viram contatos (com eventos de cadastro, confirmação e exclusão), e os e-mails de autenticação do seu app saem pela Postal com o Send Email Hook.

#Crie a conexão

No painel, abra Integrações › Seu app e clique em Conectar no cartão do Supabase. A conexão tem a sua URL, que você cola no provedor, e mostra o passo a passo na própria tela.

URL da conexão (exemplo)
https://api.postal.so/integrations/crm/01a1c2d3-e4f5-7a6b-8c9d-0e1f2a3b4c5d/webhook

No Supabase, abra Integrations › Database Webhooks e crie um webhook na tabela auth.users com Insert, Update e Delete. Em HTTP Request, escolha POST e cole a URL da conexão. Em HTTP Headers, adicione:

Cabeçalho
X-Postal-Secret: whsec_… (o segredo mostrado na conexão)

O segredo é da conexão e pode ser trocado na tela dela (o antigo para de valer). Também vale Authorization: Bearer <segredo>.

As integrações de app contam no limite do plano (app_integrations). Fora do plano, os cartões aparecem bloqueados com o botão Fazer upgrade.

#Eventos

Mudança em auth.usersEvento na PostalPadrão
INSERTsupabase.user.createdligado
UPDATE que confirma o e-mailsupabase.user.confirmedligado
UPDATE que só muda o último loginsupabase.user.signed_indesligado
Outro UPDATE (e-mail, metadados)supabase.user.updatedligado
DELETEsupabase.user.deleted (exclusão)ligado

As propriedades são user_id, provider, email_confirmed, created_at e last_sign_in_at. Mudanças em outras tabelas são ignoradas.

#Qual contato

O usuário é casado pelo ID do Supabase, guardado no external_id do contato: se o e-mail mudar, o mesmo contato é atualizado. O nome vem dos metadados do usuário, de first_name e last_name (ou de full_name / name):

Cadastro com nome
await supabase.auth.signUp({
  email: '[email protected]',
  password,
  options: { data: { first_name: 'Fulano', last_name: 'Silva' } },
})

Para as exclusões, a conexão diz o que fazer com o contato: só registrar o evento (padrão), descadastrar o contato (ele continua na audiência, sem receber marketing) ou excluir o contato (sem evento, já que o contato some). Uma exclusão nunca cria um contato que a Postal não tinha.

#Configurações da conexão

  • Eventos: só os marcados viram contato e evento; os outros são ignorados (a resposta ainda é 202).
  • Sincronizar o nome: atualiza nome e sobrenome do contato com o que vier do provedor.
  • Adicionar ao segmento e Inscrever no tópico: um segmento estático e um tópico para cada contato que chega.
  • Quando o usuário for excluído no app: só registrar, descadastrar ou excluir o contato.

Tudo que a conexão muda no contato leva a origem crm:<id da conexão> (last_change_source), e cada entrega aparece no registro da conexão, com o resultado de cada pessoa. Uma entrega repetida pelo provedor (mesmo ID) não é processada duas vezes.

#E-mails de login (Send Email Hook)

Com o Send Email Hook, o Supabase entrega cada e-mail de autenticação à Postal em vez de enviar. Para ligar:

  1. Na conexão, em E-mails de login pelo Postal, ligue o envio, escolha o remetente (de um domínio verificado do seu time) e, se quiser, a URL do projeto (https://abcd.supabase.co).
  2. No Supabase, abra Authentication › Hooks, adicione um hook Send Email do tipo HTTPS com a URL do hook mostrada na conexão e gere o segredo.
  3. Copie o segredo (v1,whsec_…) e cole na conexão. Salve.
URL do hook (exemplo)
https://api.postal.so/integrations/supabase/01a1c2d3-e4f5-7a6b-8c9d-0e1f2a3b4c5d/send-email
email_action_typeModelo padrão (assunto)
signupConfirme seu cadastro
magiclinkSeu link de acesso
recoveryRedefina sua senha
inviteVocê recebeu um convite
email_changeConfirme a troca de e-mail (com a troca segura, um e-mail para o endereço atual e outro para o novo)
reauthenticationSeu código de confirmação

Cada tipo tem um modelo em português que você edita na conexão (assunto e HTML). Variáveis:

VariávelO que é
{{{CONFIRMATION_URL}}}O link de confirmação. Com a URL do projeto: https://abcd.supabase.co/auth/v1/verify?token=…&type=…&redirect_to=…. Sem ela: {site_url}/auth/confirm?token_hash=…&type=…&next=…, para quem confirma no próprio app (SSR).
{{{TOKEN}}}O código de 6 dígitos (OTP).
{{{TOKEN_HASH}}}O hash do token, para montar o seu próprio link.
{{{EMAIL}}}, {{{NEW_EMAIL}}}O e-mail do usuário e, na troca, o novo e-mail.
{{{SITE_URL}}}, {{{REDIRECT_TO}}}A Site URL do projeto e o destino depois da confirmação.

Os e-mails passam pelo mesmo caminho do POST /emails: domínio verificado, cotas diária e mensal e fila prioritária. Eles levam a tag supabase_auth com o tipo e aparecem em E-mails. Os tipos de aviso de segurança (password_changed_notification e outros) são aceitos sem envio.

A resposta segue o que o Supabase espera: {} com 200 quando o e-mail foi para a fila, e, nos erros, o status com o motivo, que aparece em Logs › Auth no Supabase:

403Erro
{
  "error": {
    "http_code": 403,
    "message": "The exemplo.com domain is not verified. Please, add and verify your domain."
  }
}
StatusQuando
401Assinatura ausente ou inválida: o segredo colado na conexão não é o do hook.
403O domínio do remetente não está verificado, o envio está pausado ou a conta está suspensa.
409Os e-mails de login estão desligados na conexão, ou a conexão está pausada.
422A conexão não tem remetente, ou o hook não trouxe e-mail.
429A cota diária ou mensal de envios acabou.

#Dispare automações

Cada evento fica no contato com o nome supabase.user.created e as propriedades da tabela acima. Na tela da conexão, o botão Criar automação ao lado de cada evento abre uma automação nova com o gatilho Evento recebido já preenchido. Pelos endpoints de automações, o gatilho é {"type": "event", "event": "supabase.user.created"}.

Exemplo: uma sequência de boas-vindas a partir do cadastro, e um lembrete para quem não confirmou o e-mail em 2 dias (com uma condição sobre supabase.user.confirmed). Nos e-mails, as propriedades do evento entram como {{event.amount}} nos passos ou como variáveis do template ({{{amount}}}).