Sending Emails
SubscribeFlow sends emails through Resend. You write templates in MJML, send transactional emails to individual recipients, and run campaigns to reach tagged segments of your subscriber base.
Templates
Templates use MJML for responsive email markup. Variables are inserted with {{variable_name}} syntax.
Create a template
template = await client.templates.create(
name="Welcome Email",
subject="Welcome to {{company}}, {{name}}!",
mjml_content="""
<mjml>
<mj-body>
<mj-section>
<mj-column>
<mj-text>Hello {{name}}, welcome to {{company}}!</mj-text>
</mj-column>
</mj-section>
</mj-body>
</mjml>
""",
category="transactional",
)
print(f"Template created: {template.slug}")
const template = await client.templates.create({
name: 'Welcome Email',
subject: 'Welcome to {{company}}, {{name}}!',
mjml_content: `
<mjml>
<mj-body>
<mj-section>
<mj-column>
<mj-text>Hello {{name}}, welcome to {{company}}!</mj-text>
</mj-column>
</mj-section>
</mj-body>
</mjml>
`,
category: 'transactional',
});
console.log('Template created:', template.slug);
curl -X POST https://api.subscribeflow.net/api/v1/templates \
-H "X-API-Key: sf_live_..." \
-H "Content-Type: application/json" \
-d '{
"name": "Welcome Email",
"subject": "Welcome to {{company}}, {{name}}!",
"mjml_content": "<mjml><mj-body><mj-section><mj-column><mj-text>Hello {{name}}, welcome to {{company}}!</mj-text></mj-column></mj-section></mj-body></mjml>",
"category": "transactional"
}'
Preview a template
Render a template with sample variables before sending.
Send a transactional email
Transactional emails go to a single recipient immediately.
Tip
Use idempotency_key to prevent duplicate sends. If you retry a request with the same key, SubscribeFlow returns the original result instead of sending again.
Campaigns
Campaigns send a template to all subscribers matching a tag filter. The workflow is: create a draft, configure the tag filter, preview the recipient count, and send.
Create a campaign
Preview recipient count
Before sending, check how many subscribers will receive the campaign.
Send and monitor
// Send
const result = await client.campaigns.send('campaign-id');
console.log(`Sending to ${result.total_recipients} recipients`);
// Check status later
const campaign = await client.campaigns.get('campaign-id');
console.log('Status:', campaign.status);
// Cancel if needed
await client.campaigns.cancel('campaign-id');
# Send
curl -X POST https://api.subscribeflow.net/api/v1/campaigns/CAMPAIGN_ID/send \
-H "X-API-Key: sf_live_..."
# Check status
curl https://api.subscribeflow.net/api/v1/campaigns/CAMPAIGN_ID \
-H "X-API-Key: sf_live_..."
# Cancel
curl -X POST https://api.subscribeflow.net/api/v1/campaigns/CAMPAIGN_ID/cancel \
-H "X-API-Key: sf_live_..."
Email triggers
Triggers send an email automatically when a specific event occurs -- for example, a welcome email whenever a new subscriber is created.
Hands-On: Send your first campaign
Create a template, set up a campaign, and send it to your newsletter subscribers.
import asyncio
from subscribeflow import SubscribeFlowClient
async def main():
async with SubscribeFlowClient(api_key="sf_live_...") as client:
# 1. Create a template
template = await client.templates.create(
name="First Newsletter",
subject="Hello from {{company}}!",
mjml_content="""
<mjml>
<mj-body>
<mj-section>
<mj-column>
<mj-text font-size="20px">
Hello from {{company}}!
</mj-text>
<mj-text>
This is our first newsletter. Thanks for subscribing!
</mj-text>
</mj-column>
</mj-section>
</mj-body>
</mjml>
""",
category="marketing",
)
# 2. Create a campaign
campaign = await client.campaigns.create(
name="First Newsletter",
template_id=template.id,
tag_filter={"include_tags": ["newsletter"], "match": "any"},
)
# 3. Preview recipients
count = await client.campaigns.count_recipients(
include_tags=["newsletter"],
)
print(f"Will send to {count} subscribers")
# 4. Send
result = await client.campaigns.send(campaign.id)
print(f"Campaign sent to {result.total_recipients} recipients")
asyncio.run(main())
import { SubscribeFlowClient } from '@subscribeflow/sdk';
const client = new SubscribeFlowClient({
apiKey: 'sf_live_...',
});
// 1. Create a template
const template = await client.templates.create({
name: 'First Newsletter',
subject: 'Hello from {{company}}!',
mjml_content: `
<mjml>
<mj-body>
<mj-section>
<mj-column>
<mj-text font-size="20px">
Hello from {{company}}!
</mj-text>
<mj-text>
This is our first newsletter. Thanks for subscribing!
</mj-text>
</mj-column>
</mj-section>
</mj-body>
</mjml>
`,
category: 'marketing',
});
// 2. Create a campaign
const campaign = await client.campaigns.create({
name: 'First Newsletter',
template_id: template.id,
tag_filter: { include_tags: ['newsletter'], match: 'any' },
});
// 3. Preview recipients
const count = await client.campaigns.countRecipients(campaign.id);
console.log(`Will send to ${count.count} subscribers`);
// 4. Send
const result = await client.campaigns.send(campaign.id);
console.log(`Campaign sent to ${result.total_recipients} recipients`);
# 1. Create a template (save the returned ID)
TEMPLATE_ID=$(curl -s -X POST https://api.subscribeflow.net/api/v1/templates \
-H "X-API-Key: sf_live_..." \
-H "Content-Type: application/json" \
-d '{
"name": "First Newsletter",
"subject": "Hello from {{company}}!",
"mjml_content": "<mjml><mj-body><mj-section><mj-column><mj-text>Hello from {{company}}!</mj-text></mj-column></mj-section></mj-body></mjml>",
"category": "marketing"
}' | jq -r '.id')
# 2. Create a campaign
CAMPAIGN_ID=$(curl -s -X POST https://api.subscribeflow.net/api/v1/campaigns \
-H "X-API-Key: sf_live_..." \
-H "Content-Type: application/json" \
-d "{
\"name\": \"First Newsletter\",
\"template_id\": \"$TEMPLATE_ID\",
\"tag_filter\": {\"include_tags\": [\"newsletter\"], \"match\": \"any\"}
}" | jq -r '.id')
# 3. Send
curl -X POST "https://api.subscribeflow.net/api/v1/campaigns/$CAMPAIGN_ID/send" \
-H "X-API-Key: sf_live_..."