resend.emails.send por uma chamada ao SendGrid, Postmark, Amazon SES ou ao seu próprio relay SMTP.- Criar um entitlement de crédito personalizado para emails no dashboard.
- Associar créditos a um plano de assinatura e a um produto de recarga avulsa.
- Enviar emails pelo Resend e debitar um crédito por envio com uma entrada no ledger.
- Ler o saldo de créditos atualizado de um cliente no frontend.
- Verificar webhooks do Dodo Payments e tratar
credit.balance_lowpara avisar os clientes antes que o saldo chegue a zero.
O que vamos criar
O MailKit vende dois produtos:- Uma conta do Dodo Payments. Faça tudo no modo de teste.
- Uma conta gratuita do Resend e uma API key.
- Node.js 22 ou posterior e conhecimento prático de TypeScript.
Etapa 1: Crie seu entitlement de crédito para emails
O entitlement de crédito define a unidade vendida pelo MailKit: um envio de email.
The Credits tab under Products lists all your credit entitlements.
Open the Credits Section
- Acesse o dashboard do Dodo Payments.
- Clique em Products na barra lateral.
- Selecione a aba Credits.
- Clique em Create Credit.
Configure the Credit Unit
Email CreditsCredit Type: Custom UnitUnit Name: emailDefine Precision: 0. Um email é uma unidade inteira, portanto o saldo nunca precisa de casas decimais.Credit Expiry: 30 days. Os créditos não utilizados expiram 30 dias após serem emitidos.Leave the Other Defaults
Save and Copy the Credit ID
cde_. O backend o utiliza para consultar saldos e criar entradas no ledger.Email Credits está pronto. Agora, crie os produtos que o concedem aos clientes.Etapa 2: Crie o plano e o pacote de recarga
Crie dois produtos que associem o mesmo entitlementEmail Credits: um plano de Subscription que concede 5.000 emails a cada ciclo de cobrança e uma recarga One Time que adiciona mais 5.000 sob demanda.
Plano MailKit ($19/mês, 5.000 emails)
Create the Subscription
- Acesse Products e clique em Add Product.
- Insira os detalhes do produto:
MailKit PlanDescription: 5,000 transactional emails per month.- Em Pricing Type, selecione Subscription.
- Defina o preço recorrente:
19.00Repeat payment every: 1 mêsCurrency: USDAttach the Email Credit Entitlement
Email CreditsCredits issued per billing cycle: 5000Low Balance Threshold (%): 20. O Dodo Payments envia credit.balance_low quando o saldo fica abaixo de 20% dos créditos emitidos por ciclo, ou seja, 1.000 emails.Import Default Credit Settings: ativado, para que o produto use a expiração de 30 dias da Etapa 1.Adicione o crédito ao produto e salve-o. Copie o ID do produto, que começa com pdt_.Pacote de Recarga ($9 avulso, 5.000 emails)
Create a One-Time Product
- Acesse Products e clique em Add Product.
- Insira os detalhes do produto:
Email Top-Up PackDescription: Add 5,000 emails to your MailKit balance.- Em Pricing Type, selecione One Time.
- Defina o preço:
9.00Currency: USDAttach the Credit Grant
- Select credits:
Email Credits - No of credits issued:
5000
Etapa 3: Configure o backend
Crie o servidor Express que cria checkouts, envia emails, lê saldos e recebe webhooks.Initialize the Project
package.json:Configure Environment Variables
.env com uma API key do modo de teste em Developer → API Keys e os IDs das Etapas 1 e 2:DODO_PAYMENTS_WEBHOOK_KEY na Etapa 4, depois de criar o endpoint do webhook. Crie a API key do Resend em resend.com/api-keys.Build the Server
server.ts na raiz do projeto. O servidor expõe cinco rotas: checkout de assinatura, checkout de recarga, leitura de saldo, envio e recebimento de webhook.Add a Demo UI
public/index.html. Ele chama cada rota a partir de um formulário simples, para que você possa testar o fluxo no navegador:Etapa 4: Configure o endpoint do webhook
O eventocredit.balance_low permite avisar os clientes antes que fiquem sem créditos. Sem ele, o cliente só percebe o problema quando um email não consegue ser enviado.
Expose Your Local Server
https://1234abcd.ngrok-free.app.Register the Endpoint in Dodo Payments
- Acesse Developer → Webhooks e clique em Add endpoint.
- Insira a URL
https://1234abcd.ngrok-free.app/webhooks/dodo, usando o host do seu túnel. - Selecione os eventos
credit.added,credit.balance_lowecredit.rolled_over. - Clique em Create endpoint.
- Copie o signing secret da aba Overview do endpoint para
.envcomoDODO_PAYMENTS_WEBHOOK_KEY. - Reinicie o servidor.
Etapa 5: Teste o fluxo completo
Start the Server
MailKit running on http://localhost:3000. Abra essa URL no navegador.Subscribe a Test Customer
- Na seção 1, insira um endereço de email e um nome de teste e clique em Get checkout link.
- Abra o link e conclua o checkout com um cartão de teste.
- No dashboard, acesse Customers e copie o ID do novo cliente, que começa com
cus_.
Send an Email
- Cole o ID do cliente na seção 3.
- Deixe To definido como
delivered@resend.dev, um endereço de teste do Resend que aceita todas as mensagens. - Clique em Send.
Trigger the Low-Balance Webhook
- Abra o cliente em Customers, selecione a aba Credits e escolha Email Credits.
- Clique em Apply Credit/Debit, selecione Debit e insira
4000. O saldo agora é exatamente 1.000, portanto ainda não está abaixo do limite. - Envie mais um email pela demonstração. O saldo cai para 999.
Buy a Top-Up Pack
- Cole o ID do cliente na seção 4.
- Clique em Buy 5,000 emails e conclua o checkout de teste.
- Atualize o saldo. Ele aumenta em 5.000.
credit.added com transaction_type: "credit_added". O grant associado tem source_type: one_time, que você pode consultar pela API List Customer Grants. Os créditos de recarga são adicionados aos créditos da assinatura. Os débitos usam primeiro o grant que expira antes e, quando dois expiram ao mesmo tempo, o grant mais antigo.Test the Hard Stop
402:402 é a regra de controle da sua aplicação. Trate a API de saldo do Dodo Payments como fonte da verdade e não armazene o saldo em cache no cliente.Solução de problemas
Webhook signature verification fails (401)
Webhook signature verification fails (401)
express.json() substitui o corpo por um objeto analisado, portanto a verificação falha. Registre /webhooks/dodo com express.raw({ type: 'application/json' }) acima da linha app.use(express.json()). Depois, verifique se DODO_PAYMENTS_WEBHOOK_KEY corresponde ao signing secret na aba Overview do endpoint.Balance is 0, customer not found, or credits don't deduct
Balance is 0, customer not found, or credits don't deduct
- O cliente concluiu o checkout. Os créditos são emitidos quando o pagamento é aprovado, não quando a sessão de checkout é criada.
CREDIT_ENTITLEMENT_IDem.envcorresponde ao crédito associado ao produto. As chamadas de saldo e ledger usam esse ID, portanto uma divergência lê ou debita um crédito diferente.- O
customer_idinformado é o ID do cliente no Dodo Payments (começa comcus_), não um ID do seu próprio banco de dados.
Resend rejects the recipient
Resend rejects the recipient
onboarding@resend.dev entrega somente ao endereço de email da sua conta do Resend ou a delivered@resend.dev. Para enviar a qualquer outra pessoa, verifique um domínio e use um endereço from nesse domínio.O que você criou
One Reusable Credit Unit
Email Credits, definido uma vez e associado ao plano de assinatura e ao pacote de recarga.Subscription with Prepaid Allowance
Top-Up Pack
Direct Ledger Debits
createLedgerEntry após cada envio, sem medidor e sem atraso de agregação. O ID da mensagem do Resend como chave de idempotência impede um segundo débito para o mesmo envio.