API Reference
Complete endpoint reference for the SentinMail REST API with examples in cURL, JavaScript, and Python
Overview
This is a complete reference of all SentinMail API endpoints. For getting-started guides, see Authentication, Sending Emails, and Newsletter Subscriptions.
Base URL: https://api.sentinmail.app
Authentication: All endpoints require an X-API-Key header unless marked as Public.
Machine-readable spec: OpenAPI 3.0 (YAML)
Sending Emails
POST /api/emails/send/to-list/
Send a saved template to all subscribers in a list. Supports scheduling.
1curl -X POST https://api.sentinmail.app/api/emails/send/to-list/ \2 -H "X-API-Key: fm_your_api_key_here" \3 -H "Content-Type: application/json" \4 -d '{5 "name": "March Newsletter",6 "template_id": "TEMPLATE_UUID",7 "smtp_config_id": "SMTP_CONFIG_UUID",8 "list_id": "LIST_UUID"9 }'1const response = await fetch('https://api.sentinmail.app/api/emails/send/to-list/', {2 method: 'POST',3 headers: {4 'X-API-Key': process.env.SENTINMAIL_API_KEY,5 'Content-Type': 'application/json',6 },7 body: JSON.stringify({8 name: 'March Newsletter',9 template_id: 'TEMPLATE_UUID',10 smtp_config_id: 'SMTP_CONFIG_UUID',11 list_id: 'LIST_UUID',12 }),13});14const campaign = await response.json();1import requests2 3response = requests.post(4 'https://api.sentinmail.app/api/emails/send/to-list/',5 headers={'X-API-Key': 'fm_your_api_key_here'},6 json={7 'name': 'March Newsletter',8 'template_id': 'TEMPLATE_UUID',9 'smtp_config_id': 'SMTP_CONFIG_UUID',10 'list_id': 'LIST_UUID',11 },12)13campaign = response.json()| Field | Type | Required | Description |
|---|---|---|---|
name | string | Yes | Campaign name (max 255) |
template_id | UUID | Yes | Template to send |
smtp_config_id | UUID | Yes | SMTP config to use |
list_id | UUID | Yes | Target subscriber list |
scheduled_for | ISO-8601 | No | Schedule delivery (null = now) |
attachment_ids | UUID[] | No | Media file attachments |
POST /api/emails/send/to-receivers/
Send a saved template to specific recipients with per-recipient personalization.
1curl -X POST https://api.sentinmail.app/api/emails/send/to-receivers/ \2 -H "X-API-Key: fm_your_api_key_here" \3 -H "Content-Type: application/json" \4 -d '{5 "name": "Renewal Reminder",6 "template_id": "TEMPLATE_UUID",7 "smtp_config_id": "SMTP_CONFIG_UUID",8 "receivers": [9 {"email": "john@example.com", "first_name": "John", "plan": "Pro"},10 {"email": "jane@example.com", "first_name": "Jane", "plan": "Enterprise"}11 ]12 }'1const response = await fetch('https://api.sentinmail.app/api/emails/send/to-receivers/', {2 method: 'POST',3 headers: {4 'X-API-Key': process.env.SENTINMAIL_API_KEY,5 'Content-Type': 'application/json',6 },7 body: JSON.stringify({8 name: 'Renewal Reminder',9 template_id: 'TEMPLATE_UUID',10 smtp_config_id: 'SMTP_CONFIG_UUID',11 receivers: [12 { email: 'john@example.com', first_name: 'John', plan: 'Pro' },13 { email: 'jane@example.com', first_name: 'Jane', plan: 'Enterprise' },14 ],15 }),16});17const campaign = await response.json();1import requests2 3response = requests.post(4 'https://api.sentinmail.app/api/emails/send/to-receivers/',5 headers={'X-API-Key': 'fm_your_api_key_here'},6 json={7 'name': 'Renewal Reminder',8 'template_id': 'TEMPLATE_UUID',9 'smtp_config_id': 'SMTP_CONFIG_UUID',10 'receivers': [11 {'email': 'john@example.com', 'first_name': 'John', 'plan': 'Pro'},12 {'email': 'jane@example.com', 'first_name': 'Jane', 'plan': 'Enterprise'},13 ],14 },15)16campaign = response.json()| Field | Type | Required | Description |
|---|---|---|---|
name | string | Yes | Campaign name |
template_id | UUID | Yes | Template to send |
smtp_config_id | UUID | Yes | SMTP config to use |
receivers | object[] | Yes | Recipients (each must have email) |
scheduled_for | ISO-8601 | No | Schedule delivery |
attachment_ids | UUID[] | No | Media file attachments |
Receiver object: Any field beyond email becomes a [[variable]] template variable. Optional cc and bcc arrays are supported.
POST /api/emails/send/custom/
Send custom subject + HTML body without a saved template. Best for transactional emails.
1curl -X POST https://api.sentinmail.app/api/emails/send/custom/ \2 -H "X-API-Key: fm_your_api_key_here" \3 -H "Content-Type: application/json" \4 -d '{5 "name": "Order Confirmation",6 "smtp_config_id": "SMTP_CONFIG_UUID",7 "subject": "Order #[[order_id]] confirmed, [[first_name]]!",8 "body": "<h1>Thanks, [[first_name]]!</h1><p>Order #[[order_id]] for [[product]] is confirmed. Total: $[[total]]</p>",9 "receivers": [10 {11 "email": "john@example.com",12 "first_name": "John",13 "order_id": "12345",14 "product": "Wireless Headphones",15 "total": "79.99"16 }17 ]18 }'1const response = await fetch('https://api.sentinmail.app/api/emails/send/custom/', {2 method: 'POST',3 headers: {4 'X-API-Key': process.env.SENTINMAIL_API_KEY,5 'Content-Type': 'application/json',6 },7 body: JSON.stringify({8 name: 'Order Confirmation',9 smtp_config_id: 'SMTP_CONFIG_UUID',10 subject: 'Order #[[order_id]] confirmed, [[first_name]]!',11 body: '<h1>Thanks, [[first_name]]!</h1><p>Order #[[order_id]] confirmed.</p>',12 receivers: [{13 email: 'john@example.com',14 first_name: 'John',15 order_id: '12345',16 product: 'Wireless Headphones',17 total: '79.99',18 }],19 }),20});21const campaign = await response.json();1import requests2 3response = requests.post(4 'https://api.sentinmail.app/api/emails/send/custom/',5 headers={'X-API-Key': 'fm_your_api_key_here'},6 json={7 'name': 'Order Confirmation',8 'smtp_config_id': 'SMTP_CONFIG_UUID',9 'subject': 'Order #[[order_id]] confirmed, [[first_name]]!',10 'body': '<h1>Thanks!</h1><p>Order #[[order_id]] confirmed.</p>',11 'receivers': [{12 'email': 'john@example.com',13 'first_name': 'John',14 'order_id': '12345',15 'product': 'Wireless Headphones',16 'total': '79.99',17 }],18 },19)20campaign = response.json()| Field | Type | Required | Description |
|---|---|---|---|
name | string | Yes | Campaign name |
smtp_config_id | UUID | Yes | SMTP config to use |
subject | string | Yes | Subject line (supports [[variables]]) |
body | string | Yes | HTML body (supports [[variables]]) |
receivers | object[] | Yes | Recipients |
attachment_ids | UUID[] | No | Media file attachments |
Subscribers
POST /api/emails/subscribers/
Add a subscriber.
1curl -X POST https://api.sentinmail.app/api/emails/subscribers/ \2 -H "X-API-Key: fm_your_api_key_here" \3 -H "Content-Type: application/json" \4 -d '{"email": "newuser@example.com", "first_name": "Jane", "last_name": "Doe"}'1const response = await fetch('https://api.sentinmail.app/api/emails/subscribers/', {2 method: 'POST',3 headers: {4 'X-API-Key': process.env.SENTINMAIL_API_KEY,5 'Content-Type': 'application/json',6 },7 body: JSON.stringify({8 email: 'newuser@example.com',9 first_name: 'Jane',10 last_name: 'Doe',11 }),12});13const subscriber = await response.json();1import requests2 3response = requests.post(4 'https://api.sentinmail.app/api/emails/subscribers/',5 headers={'X-API-Key': 'fm_your_api_key_here'},6 json={'email': 'newuser@example.com', 'first_name': 'Jane', 'last_name': 'Doe'},7)8subscriber = response.json()GET /api/emails/subscribers/
List subscribers. Supports ?search=, ?ordering=, ?page=.
GET /api/emails/subscribers/{id}/
Get a single subscriber.
PATCH /api/emails/subscribers/{id}/
Update subscriber fields.
DELETE /api/emails/subscribers/{id}/
Permanently delete a subscriber.
POST /api/emails/subscribers/bulk/
Bulk import from CSV. Send as multipart/form-data with a file field.
1curl -X POST https://api.sentinmail.app/api/emails/subscribers/bulk/ \2 -H "X-API-Key: fm_your_api_key_here" \3 -F "file=@subscribers.csv"CSV format: email,first_name,last_name
POST /api/emails/subscribers/bulk-delete/
Delete multiple subscribers by ID.
1{ "subscriber_ids": ["UUID_1", "UUID_2"] }POST /api/emails/subscribers/bulk-update-lists/
Add or remove subscribers from lists in bulk.
1{2 "subscriber_ids": ["SUB_ID_1", "SUB_ID_2"],3 "add_to_lists": ["LIST_ID"],4 "remove_from_lists": []5}GET /api/emails/subscribers/export/
Export all subscribers as a CSV file download.
Subscriber Lists
POST /api/emails/lists/
Create a subscriber list.
1curl -X POST https://api.sentinmail.app/api/emails/lists/ \2 -H "X-API-Key: fm_your_api_key_here" \3 -H "Content-Type: application/json" \4 -d '{"name": "Weekly Newsletter", "description": "Weekly product updates"}'1const response = await fetch('https://api.sentinmail.app/api/emails/lists/', {2 method: 'POST',3 headers: {4 'X-API-Key': process.env.SENTINMAIL_API_KEY,5 'Content-Type': 'application/json',6 },7 body: JSON.stringify({8 name: 'Weekly Newsletter',9 description: 'Weekly product updates',10 }),11});12const list = await response.json();1import requests2 3response = requests.post(4 'https://api.sentinmail.app/api/emails/lists/',5 headers={'X-API-Key': 'fm_your_api_key_here'},6 json={'name': 'Weekly Newsletter', 'description': 'Weekly product updates'},7)8list_data = response.json()GET /api/emails/lists/
List all subscriber lists.
GET /api/emails/lists/{id}/
Get list details.
PATCH /api/emails/lists/{id}/
Update list name or description.
DELETE /api/emails/lists/{id}/
Delete a list.
Email Templates
POST /api/emails/templates/
Create an email template.
1curl -X POST https://api.sentinmail.app/api/emails/templates/ \2 -H "X-API-Key: fm_your_api_key_here" \3 -H "Content-Type: application/json" \4 -d '{5 "name": "Welcome Email",6 "subject": "Welcome, [[first_name]]!",7 "body": "<h1>Welcome!</h1><p>Thanks for joining, [[first_name]].</p>",8 "template_mode": "basic",9 "template_type": "marketing"10 }'1const response = await fetch('https://api.sentinmail.app/api/emails/templates/', {2 method: 'POST',3 headers: {4 'X-API-Key': process.env.SENTINMAIL_API_KEY,5 'Content-Type': 'application/json',6 },7 body: JSON.stringify({8 name: 'Welcome Email',9 subject: 'Welcome, [[first_name]]!',10 body: '<h1>Welcome!</h1><p>Thanks for joining, [[first_name]].</p>',11 template_mode: 'basic',12 template_type: 'marketing',13 }),14});15const template = await response.json();1import requests2 3response = requests.post(4 'https://api.sentinmail.app/api/emails/templates/',5 headers={'X-API-Key': 'fm_your_api_key_here'},6 json={7 'name': 'Welcome Email',8 'subject': 'Welcome, [[first_name]]!',9 'body': '<h1>Welcome!</h1><p>Thanks for joining, [[first_name]].</p>',10 'template_mode': 'basic',11 'template_type': 'marketing',12 },13)14template = response.json()| Field | Type | Required | Description |
|---|---|---|---|
name | string | Yes | Template name |
subject | string | Yes | Subject line (supports [[variables]]) |
body | string | No | HTML body |
template_mode | string | No | basic or visual |
template_type | string | No | marketing or transactional |
GET /api/emails/templates/
List templates.
GET /api/emails/templates/{id}/
Get template details.
PATCH /api/emails/templates/{id}/
Update a template.
DELETE /api/emails/templates/{id}/
Delete a template.
SMTP Configuration
POST /api/emails/smtp-configs/
Add an SMTP server configuration.
1curl -X POST https://api.sentinmail.app/api/emails/smtp-configs/ \2 -H "X-API-Key: fm_your_api_key_here" \3 -H "Content-Type: application/json" \4 -d '{5 "name": "Production SES",6 "host": "email-smtp.us-east-1.amazonaws.com",7 "port": 587,8 "username": "AKIAIOSFODNN7EXAMPLE",9 "password": "YOUR_SMTP_PASSWORD",10 "use_tls": true,11 "sender_name": "My App",12 "sender_email": "hello@myapp.com"13 }'1const response = await fetch('https://api.sentinmail.app/api/emails/smtp-configs/', {2 method: 'POST',3 headers: {4 'X-API-Key': process.env.SENTINMAIL_API_KEY,5 'Content-Type': 'application/json',6 },7 body: JSON.stringify({8 name: 'Production SES',9 host: 'email-smtp.us-east-1.amazonaws.com',10 port: 587,11 username: process.env.SES_USERNAME,12 password: process.env.SES_PASSWORD,13 use_tls: true,14 sender_name: 'My App',15 sender_email: 'hello@myapp.com',16 }),17});18const smtpConfig = await response.json();1import os2import requests3 4response = requests.post(5 'https://api.sentinmail.app/api/emails/smtp-configs/',6 headers={'X-API-Key': 'fm_your_api_key_here'},7 json={8 'name': 'Production SES',9 'host': 'email-smtp.us-east-1.amazonaws.com',10 'port': 587,11 'username': os.environ['SES_USERNAME'],12 'password': os.environ['SES_PASSWORD'],13 'use_tls': True,14 'sender_name': 'My App',15 'sender_email': 'hello@myapp.com',16 },17)18smtp_config = response.json()| Field | Type | Required | Description |
|---|---|---|---|
name | string | Yes | Display name |
host | string | Yes | SMTP server hostname |
port | integer | Yes | Port (usually 587 for TLS) |
username | string | Yes | SMTP username |
password | string | Yes | SMTP password |
use_tls | boolean | No | Enable TLS (default: true) |
sender_name | string | No | From name |
sender_email | string | Yes | From email address |
POST /api/emails/smtp/validate/
Test SMTP credentials without saving.
GET /api/emails/smtp-configs/
List SMTP configs.
PATCH /api/emails/smtp-configs/{id}/
Update an SMTP config.
DELETE /api/emails/smtp-configs/{id}/
Delete an SMTP config.
Campaigns
GET /api/emails/campaigns/
List all campaigns.
GET /api/emails/campaigns/{id}/
Get campaign details and status.
1curl https://api.sentinmail.app/api/emails/campaigns/CAMPAIGN_UUID/ \2 -H "X-API-Key: fm_your_api_key_here"1const response = await fetch(2 `https://api.sentinmail.app/api/emails/campaigns/${campaignId}/`,3 { headers: { 'X-API-Key': process.env.SENTINMAIL_API_KEY } }4);5const campaign = await response.json();6console.log(`Status: ${campaign.status}, Sent: ${campaign.sent_count}/${campaign.total_emails}`);1import requests2 3response = requests.get(4 f'https://api.sentinmail.app/api/emails/campaigns/{campaign_id}/',5 headers={'X-API-Key': 'fm_your_api_key_here'},6)7campaign = response.json()8print(f"Status: {campaign['status']}, Sent: {campaign['sent_count']}/{campaign['total_emails']}")Campaign statuses: pending, sending, completed, partial, failed, scheduled, cancelled
POST /api/emails/campaigns/{id}/resume/
Resume a failed or partially completed campaign. Already-sent recipients are skipped.
POST /api/emails/campaigns/{id}/cancel/
Cancel a scheduled campaign.
GET /api/emails/campaigns/{id}/analytics/
Get campaign analytics (opens, clicks, bounces).
GET /api/emails/campaigns/{id}/export/
Export campaign results as CSV.
Webhooks
POST /api/emails/webhook-endpoints/
Register a webhook to receive delivery events.
1curl -X POST https://api.sentinmail.app/api/emails/webhook-endpoints/ \2 -H "X-API-Key: fm_your_api_key_here" \3 -H "Content-Type: application/json" \4 -d '{5 "url": "https://yourapp.com/webhooks/sentinmail",6 "events": ["delivered", "opened", "clicked", "bounced", "unsubscribed"]7 }'1const response = await fetch('https://api.sentinmail.app/api/emails/webhook-endpoints/', {2 method: 'POST',3 headers: {4 'X-API-Key': process.env.SENTINMAIL_API_KEY,5 'Content-Type': 'application/json',6 },7 body: JSON.stringify({8 url: 'https://yourapp.com/webhooks/sentinmail',9 events: ['delivered', 'opened', 'clicked', 'bounced', 'unsubscribed'],10 }),11});1import requests2 3response = requests.post(4 'https://api.sentinmail.app/api/emails/webhook-endpoints/',5 headers={'X-API-Key': 'fm_your_api_key_here'},6 json={7 'url': 'https://yourapp.com/webhooks/sentinmail',8 'events': ['delivered', 'opened', 'clicked', 'bounced', 'unsubscribed'],9 },10)Event types: delivered, opened, clicked, bounced, unsubscribed
GET /api/emails/webhook-endpoints/
List registered webhooks.
PUT /api/emails/webhook-endpoints/{id}/
Update a webhook URL or events.
DELETE /api/emails/webhook-endpoints/{id}/
Delete a webhook.
Suppressions
POST /api/emails/suppressions/
Block emails to an address or domain.
1{"email": "bounced@example.com", "reason": "Hard bounce"}GET /api/emails/suppressions/
List suppressions.
DELETE /api/emails/suppressions/{id}/
Remove a suppression.
Segments
POST /api/emails/segments/
Create a dynamic subscriber segment based on rules.
1{2 "name": "Engaged Users",3 "description": "Opened an email in the last 30 days",4 "rules": {5 "conditions": [6 {"field": "last_opened", "operator": "within_days", "value": 30}7 ],8 "match": "all"9 }10}GET /api/emails/segments/
List segments.
PATCH /api/emails/segments/{id}/
Update segment rules.
DELETE /api/emails/segments/{id}/
Delete a segment.
Media Files
POST /api/emails/media/
Upload a file (multipart/form-data).
GET /api/emails/media/
List uploaded files.
DELETE /api/emails/media/{id}/
Delete a file.
Sent Emails & Events
GET /api/emails/sent-emails/
List all sent emails with delivery status.
GET /api/emails/events/
List email events (opens, clicks, bounces, unsubscribes).
Public Endpoints
These endpoints require no authentication and are used for subscriber-facing features.
| Endpoint | Method | Description |
|---|---|---|
/api/emails/public/subscribe/{company_id}/ | POST | Subscribe to newsletter (3/min rate limit per IP) |
/api/emails/public/confirm/{token}/ | POST | Confirm double opt-in subscription |
/api/emails/public/unsubscribe/{sent_email_id}/ | GET/POST | Unsubscribe from emails |
/api/emails/public/view/{sent_email_id}/ | GET | View email in browser |
/api/emails/public/preferences/{token}/ | GET/PUT | View/update subscriber preferences |
Common Integration Patterns
Transactional Email (e.g., Order Confirmation)
1// After order is placed2async function sendOrderConfirmation(order) {3 const response = await fetch('https://api.sentinmail.app/api/emails/send/custom/', {4 method: 'POST',5 headers: {6 'X-API-Key': process.env.SENTINMAIL_API_KEY,7 'Content-Type': 'application/json',8 },9 body: JSON.stringify({10 name: `Order ${order.id} confirmation`,11 smtp_config_id: process.env.SENTINMAIL_SMTP_ID,12 subject: 'Order #[[order_id]] confirmed!',13 body: '<h1>Thanks, [[first_name]]!</h1><p>Order #[[order_id]] confirmed. Total: $[[total]]</p>',14 receivers: [{15 email: order.customerEmail,16 first_name: order.customerName,17 order_id: order.id,18 total: order.total.toFixed(2),19 }],20 }),21 });22 return response.json();23}Newsletter Signup + Welcome Email
1// 1. Add subscriber2const subRes = await fetch('https://api.sentinmail.app/api/emails/subscribers/', {3 method: 'POST',4 headers: {5 'X-API-Key': process.env.SENTINMAIL_API_KEY,6 'Content-Type': 'application/json',7 },8 body: JSON.stringify({ email: userEmail, first_name: userName }),9});10const subscriber = await subRes.json();11 12// 2. Add to newsletter list13await fetch('https://api.sentinmail.app/api/emails/subscribers/bulk-update-lists/', {14 method: 'POST',15 headers: {16 'X-API-Key': process.env.SENTINMAIL_API_KEY,17 'Content-Type': 'application/json',18 },19 body: JSON.stringify({20 subscriber_ids: [subscriber.id],21 add_to_lists: [process.env.NEWSLETTER_LIST_ID],22 remove_from_lists: [],23 }),24});25 26// 3. Send welcome email27await fetch('https://api.sentinmail.app/api/emails/send/to-receivers/', {28 method: 'POST',29 headers: {30 'X-API-Key': process.env.SENTINMAIL_API_KEY,31 'Content-Type': 'application/json',32 },33 body: JSON.stringify({34 name: `Welcome - ${userEmail}`,35 template_id: process.env.WELCOME_TEMPLATE_ID,36 smtp_config_id: process.env.SENTINMAIL_SMTP_ID,37 receivers: [{ email: userEmail, first_name: userName }],38 }),39});Webhook-Driven Bounce Handling
1// Express.js webhook handler2app.post('/webhooks/sentinmail', (req, res) => {3 const event = req.body;4 res.status(200).send('OK'); // Acknowledge immediately5 6 switch (event.type) {7 case 'bounced':8 db.users.update({ email: event.recipient }, { email_valid: false });9 break;10 case 'unsubscribed':11 db.users.update({ email: event.recipient }, { marketing_opted_in: false });12 break;13 case 'opened':14 analytics.track('email_opened', { email: event.recipient, campaign: event.campaign_id });15 break;16 }17});1# Django webhook handler2from django.http import HttpResponse3from django.views.decorators.csrf import csrf_exempt4import json5 6@csrf_exempt7def sentinmail_webhook(request):8 event = json.loads(request.body)9 HttpResponse(status=200) # Acknowledge10 11 if event['type'] == 'bounced':12 User.objects.filter(email=event['recipient']).update(email_valid=False)13 elif event['type'] == 'unsubscribed':14 User.objects.filter(email=event['recipient']).update(marketing_opted_in=False)15 16 return HttpResponse(status=200)