resend.emails.send par un appel à SendGrid, Postmark, Amazon SES ou votre propre relais SMTP.- Créer un droit de crédit personnalisé pour les e-mails dans le dashboard.
- Associer des crédits à un plan d’abonnement et à un produit de recharge ponctuel.
- Envoyer des e-mails via Resend et débiter un crédit par envoi avec une entrée de ledger.
- Lire le solde de crédits en temps réel d’un client depuis votre frontend.
- Vérifier les webhooks de Dodo Payments et gérer
credit.balance_lowpour avertir les clients avant que leur solde n’atteigne zéro.
What We’re Building
MailKit vend deux produits :- Un compte Dodo Payments. Effectuez tout le développement en mode test.
- Un compte Resend gratuit et une clé API.
- Node.js 22 ou version ultérieure, ainsi qu’une bonne connaissance de TypeScript.
Étape 1 : créer votre droit de crédit pour les e-mails
Le droit de crédit définit l’unité vendue par MailKit : un envoi d’e-mail.
The Credits tab under Products lists all your credit entitlements.
Open the Credits Section
- Connectez-vous au dashboard de Dodo Payments.
- Cliquez sur Products dans la barre latérale.
- Sélectionnez l’onglet Credits.
- Cliquez sur Create Credit.
Configure the Credit Unit
Email CreditsCredit Type : Custom UnitUnit Name : emailDefine Precision : 0. Un e-mail est une unité entière, le solde n’a donc jamais besoin de décimales.Credit Expiry : 30 days. Les crédits inutilisés expirent 30 jours après leur émission.Leave the Other Defaults
Save and Copy the Credit ID
cde_. Le backend l’utilise pour lire les soldes et créer les entrées de ledger.Email Credits est prêt. Créez maintenant les produits qui l’accordent aux clients.Étape 2 : créer le forfait et le pack de recharge
Créez deux produits qui associent le même droitEmail Credits : un forfait Subscription qui accorde 5 000 e-mails à chaque cycle de facturation, et une recharge One Time qui en ajoute 5 000 à la demande.
Forfait MailKit ($19/mois, 5 000 e-mails)
Create the Subscription
- Accédez à Products et cliquez sur Add Product.
- Saisissez les informations du produit :
MailKit PlanDescription : 5,000 transactional emails per month.- Sous Pricing Type, sélectionnez Subscription.
- Définissez le prix récurrent :
19.00Repeat payment every : 1 moisCurrency : USDAttach the Email Credit Entitlement
Email CreditsCredits issued per billing cycle : 5000Low Balance Threshold (%) : 20. Dodo Payments envoie credit.balance_low lorsque le solde passe sous 20 % des crédits émis par cycle, soit 1 000 e-mails.Import Default Credit Settings : activé, afin que le produit utilise l’expiration de 30 jours définie à l’étape 1.Ajoutez le crédit au produit, puis enregistrez le produit. Copiez l’ID du produit, qui commence par pdt_.Pack de recharge ($9 en paiement unique, 5 000 e-mails)
Create a One-Time Product
- Accédez à Products et cliquez sur Add Product.
- Saisissez les informations du produit :
Email Top-Up PackDescription : Add 5,000 emails to your MailKit balance.- Sous Pricing Type, sélectionnez One Time.
- Définissez le prix :
9.00Currency : USDAttach the Credit Grant
- Select credits :
Email Credits - No of credits issued :
5000
Étape 3 : configurer le backend
Créez le serveur Express qui crée les checkouts, envoie les e-mails, lit les soldes et reçoit les webhooks.Initialize the Project
package.json :Configure Environment Variables
.env avec une clé API de mode test obtenue dans Developer → API Keys, ainsi qu’avec les ID des étapes 1 et 2 :DODO_PAYMENTS_WEBHOOK_KEY à l’étape 4, après avoir créé le endpoint webhook. Créez la clé API Resend sur resend.com/api-keys.Build the Server
server.ts à la racine du projet. Le serveur expose cinq routes : checkout d’abonnement, checkout de recharge, lecture du solde, envoi et réception du webhook.Add a Demo UI
public/index.html. Il appelle chaque route depuis un formulaire simple afin que vous puissiez tester le flux dans un navigateur :Étape 4 : connecter le endpoint webhook
L’événementcredit.balance_low vous permet d’avertir les clients avant qu’ils ne soient à court de crédits. Sans lui, un client ne remarque le problème qu’au moment où un e-mail ne peut plus être envoyé.
Expose Your Local Server
https://1234abcd.ngrok-free.app.Register the Endpoint in Dodo Payments
- Accédez à Developer → Webhooks et cliquez sur Add endpoint.
- Saisissez l’URL
https://1234abcd.ngrok-free.app/webhooks/dodoen utilisant l’hôte de votre propre tunnel. - Sélectionnez les événements
credit.added,credit.balance_lowetcredit.rolled_over. - Cliquez sur Create endpoint.
- Copiez le secret de signature depuis l’onglet Overview du endpoint dans
.enven tant queDODO_PAYMENTS_WEBHOOK_KEY. - Redémarrez le serveur.
Étape 5 : tester le flux complet
Start the Server
MailKit running on http://localhost:3000. Ouvrez cette URL dans votre navigateur.Subscribe a Test Customer
- Dans la section 1, saisissez une adresse e-mail et un nom de test, puis cliquez sur Get checkout link.
- Ouvrez le lien et terminez le checkout avec une carte de test.
- Dans le dashboard, accédez à Customers et copiez l’ID du nouveau client, qui commence par
cus_.
Send an Email
- Collez l’ID du client dans la section 3.
- Laissez To défini sur
delivered@resend.dev, une adresse de test Resend qui accepte tous les messages. - Cliquez sur Send.
Trigger the Low-Balance Webhook
- Ouvrez le client dans Customers, sélectionnez l’onglet Credits, puis choisissez Email Credits.
- Cliquez sur Apply Credit/Debit, sélectionnez Debit et saisissez
4000. Le solde est désormais exactement de 1 000, ce qui n’est pas encore inférieur au seuil. - Envoyez un e-mail supplémentaire depuis la démo. Le solde passe à 999.
Buy a Top-Up Pack
- Collez l’ID du client dans la section 4.
- Cliquez sur Buy 5,000 emails et terminez le checkout de test.
- Actualisez le solde. Il augmente de 5 000.
credit.added avec transaction_type: "credit_added". Le grant associé possède source_type: one_time, que vous pouvez relire avec l’API List Customer Grants. Les crédits de recharge s’ajoutent aux crédits de l’abonnement. Les débits utilisent d’abord le grant qui expire en premier, puis le grant le plus ancien lorsque deux grants expirent au même moment.Test the Hard Stop
402 :402 constitue le mécanisme de contrôle de votre application. Considérez l’API de solde de Dodo Payments comme la source de vérité et ne mettez pas le solde en cache côté client.Résolution des problèmes
Webhook signature verification fails (401)
Webhook signature verification fails (401)
express.json() remplace le corps par un objet analysé, ce qui fait échouer la vérification. Enregistrez /webhooks/dodo avec express.raw({ type: 'application/json' }) au-dessus de la ligne app.use(express.json()). Vérifiez ensuite que DODO_PAYMENTS_WEBHOOK_KEY correspond au secret de signature affiché dans l’onglet Overview du endpoint.Balance is 0, customer not found, or credits don't deduct
Balance is 0, customer not found, or credits don't deduct
- Le client a terminé le checkout. Les crédits sont émis lorsque le paiement réussit, et non lors de la création de la session de checkout.
CREDIT_ENTITLEMENT_IDdans.envcorrespond au crédit associé au produit. Les appels de solde et de ledger utilisent cet ID ; une incohérence permet donc de lire ou de débiter un autre crédit.- Le
customer_idtransmis est l’ID client Dodo Payments (il commence parcus_), et non un ID provenant de votre propre base de données.
Resend rejects the recipient
Resend rejects the recipient
onboarding@resend.dev n’envoie des e-mails qu’à l’adresse associée à votre compte Resend ou à delivered@resend.dev. Pour envoyer des e-mails à d’autres destinataires, vérifiez un domaine et utilisez une adresse from sur ce domaine.Ce que vous avez créé
One Reusable Credit Unit
Email Credits, défini une seule fois et associé à la fois au forfait d’abonnement et au pack de recharge.Subscription with Prepaid Allowance
Top-Up Pack
Direct Ledger Debits
createLedgerEntry après chaque envoi, sans compteur ni délai d’agrégation. L’ID du message Resend utilisé comme clé d’idempotence empêche un second débit pour le même envoi.