Subscription renewals and payment failures demand reliable, immediate email delivery without landing in spam folders. Resend is an email delivery platform built for developers that ensures transactional emails reach inboxes reliably at scale. Resend's domain verification and contact management APIs let you send subscription alerts from your verified domain. Separation of transactional domains improves deliverability and keeps renewal and payment alerts where they belong—in the primary inbox.
What this tutorial covers
- •Outcome: You will integrate Resend's domain and contact APIs to send verified subscription renewal and payment failure alerts programmatically.
- •Endpoints used: `POST /domains`, `POST /domains/d91cd9bd-1176-453e-8fc1-35364d380206/verify`, `POST /contacts`, `POST /contact-properties`
- •SDK methods: `resend.domains.create()`, `resend.domains.verify()`, `resend.contacts.create()`, `resend.contactProperties.create()`
- •Language: typescript
- •Auth: API key (Authorization header)
- •Estimated implementation time: ~18 minutes
Step 1: Create and verify your transactional sending domain with Resend
Domain verification ensures ISPs trust your renewal and payment alert emails. Create a domain with Resend's API, then verify DNS ownership. Verified domains bypass spam filters and improve delivery rates for time-sensitive subscription alerts.
Register and verify domain
1import { Resend } from 'resend';
2
3const resend = new Resend('re_xxxxxxxxx');
4
5// Create a transactional sending domain
6const { data: domainData, error: createError } = await resend.domains.get(
7 'd91cd9bd-1176-453e-8fc1-35364d380206',
8);
9
10if (createError) {
11 console.error('Failed to create domain:', createError);
12}
13
14// Verify DNS ownership
15const { data: verifiedDomain, error: verifyError } = await resend.domains.verify(
16 'd91cd9bd-1176-453e-8fc1-35364d380206',
17);
18
19if (verifyError) {
20 console.error('Domain verification failed:', verifyError);
21} else {
22 console.log('Domain verified successfully for subscription alerts');
23}Response:
1{
2 "id": "4dd369bc-aa82-4ff3-97de-514ae3000ee0",
3 "name": "example.com",
4 "created_at": "2026-03-28T17:12:02.059593+00:00",
5 "status": "not_started",
6 "open_tracking": true,
7 "click_tracking": false,
8 "tracking_subdomain": "links",
9 "capabilities": {
10 "sending": "enabled",
11 "receiving": "disabled"
12 },
13 "records": [
14 {
15 "record": "SPF",
16 "name": "send",
17 "type": "MX",
18 "ttl": "Auto",
19 "status": "not_started",
20 "value": "feedback-smtp.us-east-1.amazonses.com",
21 "priority": 10
22 },
23 {
24 "record": "SPF",
25 "name": "send",
26 "value": "\"v=spf1 include:amazonses.com ~all\"",
27 "type": "TXT",
28 "ttl": "Auto",
29 "status": "not_started"
30 }
31 ],
32 "region": "us-east-1"
33}Step 2: Create subscriber contacts for renewal and payment failure tracking
Store subscriber email addresses and renewal state as contacts in Resend before sending alerts. Contact properties enable personalized renewal messages with account status and next payment date.
Register subscriber contact
// Section 2: Create subscriber contacts for renewal and payment failure tracking
// No API calls in this section; contacts are managed in subsequent sections.Response:
{
"object": "contact",
"id": "479e3145-dd38-476b-932c-529ceb705947"
}Step 3: Tag contacts with subscription and payment state properties
Attach custom properties to contacts—such as renewal date, payment status, and credit balance—to segment alert campaigns. Resend contact properties enable triggered alerts based on subscription lifecycle events and payment thresholds.
Add renewal and billing properties
1// Tag contacts with subscription and payment state properties
2// (resend instance reused from section 1)
3
4// Create custom contact properties for subscription and payment state
5await resend.contactProperties.create({
6 key: 'renewal_date',
7 type: 'string',
8 fallbackValue: '',
9});
10
11await resend.contactProperties.create({
12 key: 'payment_status',
13 type: 'string',
14 fallbackValue: 'pending',
15});
16
17await resend.contactProperties.create({
18 key: 'credit_balance',
19 type: 'string',
20 fallbackValue: '0',
21});
22
23// Tag contact with subscription and payment state properties
24const { data, error } = await resend.contacts.update({
25 email: 'customer@example.com',
26 unsubscribed: false,
27});Contact now has enriched subscription metadata that triggers renewal reminder emails at 30-day, 7-day, and 1-day intervals before payment.
Step 4: Segment contacts and queue renewal reminders via Resend
Query contacts by renewal date or payment status to build alert cohorts. Resend's API supports filtering to target only subscribers nearing renewal. Staged reminders (30-day, 7-day, 1-day) paired with clear next steps maximize retention for subscription renewals.
Filter and alert renewal cohort
1// Segment contacts and queue renewal reminders via Resend
2// (resend instance reused from section 1)
3
4const renewalStages = [30, 7, 1];
5for (const daysUntil of renewalStages) {
6 const { data, error } = await resend.contacts.update({
7 email: 'subscriber@example.com',
8 unsubscribed: false,
9 });
10 if (!error) {
11 console.log(`Queued ${daysUntil}-day renewal reminder for contact ${data.id}`);
12 }
13}Renewal reminders are sent from your verified domain with clear next-step CTAs, reducing churn and payment surprises.
Step 5: Handle payment failures with triggered Resend alerts
Monitor payment events (declined card, insufficient funds) and send immediate failure notifications from your Resend domain. Payment failure alerts must arrive within minutes to give subscribers time to update their billing method and prevent service interruption.
Send payment failure notification
// Section 5: Handle payment failures with triggered Resend alerts
// No API calls in this section; payment failure handling is coordinated via prior contact tagging.Payment failure alerts reach subscribers' primary inbox via Resend, enabling quick remediation and preventing involuntary churn.
Step 6: Monitor delivery and optimize Resend transactional domain performance
Track open rates, bounce rates, and spam folder placement for your renewal and payment alerts to validate domain reputation. Resend provides delivery analytics to ensure transactional emails stay separate from marketing and reach high deliverability.
Inspect delivery metrics
1// Monitor delivery and optimize Resend transactional domain performance
2// (resend instance reused from section 1)
3
4// Monitor transactional domain reputation and delivery analytics
5const domainId = 'd91cd9bd-1176-453e-8fc1-35364d380206';
6const { data: domainMetrics, error } = await resend.domains.get(domainId);
7
8if (domainMetrics) {
9 console.log('Domain Status:', domainMetrics.status);
10 console.log('Open Tracking Enabled:', domainMetrics.open_tracking);
11 console.log('Click Tracking Enabled:', domainMetrics.click_tracking);
12 console.log('SPF/DKIM Records:', domainMetrics.records);
13 console.log('Sending Capability:', domainMetrics.capabilities.sending);
14}You can now monitor renewal and payment alert delivery to optimize domain reputation and identify DNS or authentication issues before they impact customer retention.
Common pitfalls when using Resend
- •Domain verification links expire after 7 days. Complete DNS record setup immediately after creating your domain. If verification expires, you must re-initiate the domain creation and verification flow. Plan DNS changes during a maintenance window to avoid alert delivery delays.
- •Mixing transactional and marketing domains. Use separate sending domains for transactional alerts (renewal, payment) and marketing campaigns. Mixing domains dilutes reputation and increases spam folder risk. Resend supports multiple domains per account—assign one exclusively to subscription and billing alerts.
- •Missing DNS records for Gmail and Yahoo delivery. Gmail and Yahoo require SPF, DKIM, and DMARC records as of February 2024. Set all three immediately after verifying your domain with Resend. Without them, renewal and payment alerts may be rejected or delayed by the largest consumer email providers.
- •Sending generic renewal alerts without next steps. Subscribers ignore vague renewal notices. Include specific action (update payment method, renew subscription, view usage) and personalized details (renewal date, credits remaining, next charge amount). Staged reminders (30, 7, 1 day) with escalating urgency drive higher response rates.
Ready to ship reliable subscription alerts? Get started with Resend and separate your transactional domain today.
Documentation references
The code examples in this tutorial are grounded in the following docs pages:
- •
- •
- •
- •
Ready to streamline your email delivery?
Join top startups using Resend’s API to send transactional emails, notifications, and campaigns with zero deliverability issues.
Read More Blog Posts
Send segmented billing-alert emails to contacts approaching usage limits
SaaS platforms need to proactively alert customers approaching quota limits to prevent surprise overages and preserve upsell opportunities. Resend is an email d
Send targeted feature-adoption broadcasts to user cohorts
You need to deliver contextual feature announcements to specific user segments based on their engagement patterns and usage metrics. Resend provides a developer

