Every endpoint the sendvia REST API exposes: sending, scheduling, templates, domains, stats, the blocklist, mailing lists and newsletters. Authenticate with a bearer token and call it from anywhere; the examples below are curl, PHP, Python, Node.js and Go.
All API requests require a Bearer token in the Authorization header.
Authorization: Bearer sv_live_xxxxxxxxxxxxxxxxxxxxxxxx
The key above is a placeholder. Create a free account to get your own and start sending.
Send a transactional email through a verified domain.
| Field | Type | Required | Description |
|---|---|---|---|
from | string | Yes | Sender address: domain must be verified in your account |
from_name | string | No | Display name for the sender (e.g. My App). Shown as "My App <[email protected]>" in the recipient's inbox. |
to | string | array | Yes | Recipient email address (string), or an array of recipients for multi-send. Array elements can be email strings or {"email": "...", "name": "..."} objects. Max 50 recipients per request. Duplicates are automatically removed. |
subject | string | Yes | Email subject line |
html | string | One of | HTML body of the email |
text | string | One of | Plain-text body (fallback). At least one of html or text is required. |
tag | string | No | Optional label for this email (e.g. welcome, password-reset). Alphanumeric, hyphens and underscores only, max 64 characters. Visible in the dashboard and filterable on the stats page. |
track_opens | boolean | No | Whether to inject a 1×1 tracking pixel to detect email opens. Defaults to your account-level setting. Pass false to disable for this send. |
track_clicks | boolean | No | Whether to rewrite links in the HTML body through a click-tracking redirect. Defaults to your account-level setting. Pass false to disable for this send. |
template_id | integer | No | ID of a stored email template. The template's subject, HTML, and text are used as defaults; explicit subject, html, text params override them. |
template_alias | string | No | Alias of a stored email template (alternative to template_id). Aliases are URL-safe identifiers you set when creating a template. |
variables | object | No | Key-value pairs for template variable substitution. Replaces {{key}} placeholders in the template's subject, HTML, and text. |
send_at | string | No | Schedule the email for future delivery. ISO 8601 format (e.g. 2026-03-27T09:00:00Z). Must be in the future, max 72 hours ahead. Omit to send immediately. |
| Header | Description |
|---|---|
Idempotency-Key | Prevents duplicate sends on network retries. Any string up to 255 characters (UUID v4 recommended). If the same key is sent within 24 hours, the cached response is returned with an X-Idempotent-Replayed: true header instead of sending again. |
curl -X POST https://api.sendvia.io/v1/send \ -H "Authorization: Bearer sv_live_xxxxxxxxxxxxxxxxxxxxxxxx" \ -H "Content-Type: application/json" \ -d '{ "from": "[email protected]", "from_name": "My App", "to": "[email protected]", "subject": "Welcome to our service", "html": "<h1>Welcome!</h1><p>Thanks for signing up.</p>", "text": "Welcome! Thanks for signing up.", "tag": "welcome", "track_opens": true, "track_clicks": true }'
{
"success": true,
"message_id": "0102018f1234abcd-...",
"log_id": 42
}
{
"from": "[email protected]",
"to": [
"[email protected]",
{ "email": "[email protected]", "name": "Bob Smith" },
{ "email": "[email protected]", "name": "Carol" }
],
"subject": "Order confirmed",
"html": "<p>Your order has been confirmed.</p>"
}
Each recipient gets their own email with independent tracking (open/click) and delivery status. Blocked recipients are silently skipped and reported in the response.
{
"success": true,
"total": 3,
"sent": 2,
"failed": 0,
"results": [
{ "email": "[email protected]", "status": "sent", "message_id": "...", "log_id": 101 },
{ "email": "[email protected]", "status": "sent", "message_id": "...", "log_id": 102 },
{ "email": "[email protected]", "status": "blocked" }
]
}
200 = all sent, 207 = partial (some failed), 502 = all failed.
The response shape is determined by the input: string to returns the flat response, array to returns the results array.
| Status | Cause |
|---|---|
| 401 | Missing or invalid API key |
| 422 | Validation error: invalid address, missing field, recipient on blocklist, domain not verified, or too many recipients |
| 429 | Daily send limit reached; resets at midnight UTC |
| 207 | Multi-recipient partial success; some sends failed (check results array) |
| 502 | SES send failed (single recipient) or all recipients failed (multi-recipient) |
Send up to 500 unique emails in a single request. Each message can have different content, recipients, templates, and scheduling.
| Field | Type | Required | Description |
|---|---|---|---|
messages | array | Yes | Array of message objects. Max 500. |
| Each message object: | |||
from | string | Yes | Sender address: domain must be verified |
to | string | Yes | Single recipient email address |
subject | string | Yes* | Email subject (*can come from template) |
html / text | string | One of* | Email body (*can come from template) |
template_alias | string | No | Template alias for this message |
variables | object | No | Template variable substitution |
send_at | string | No | Schedule this message for future delivery |
tag | string | No | Tag for this message |
Supports the Idempotency-Key header. Daily send limit is checked against the full batch count upfront.
{
"success": true,
"total": 3,
"sent": 2,
"failed": 0,
"results": [
{ "index": 0, "status": "sent", "message_id": "...", "log_id": 101 },
{ "index": 1, "status": "scheduled", "log_id": 102 },
{ "index": 2, "status": "sent", "message_id": "...", "log_id": 103 }
]
}
Cancel a scheduled email before it is sent. Only works while the email status is scheduled.
| Parameter | Type | Description |
|---|---|---|
id | integer | The log_id returned when the email was scheduled |
{
"success": true,
"cancelled": 42
}
List all domains registered on your account and their verification status.
curl https://api.sendvia.io/v1/domains \
-H "Authorization: Bearer sv_live_xxxxxxxxxxxxxxxxxxxxxxxx"
{
"domains": [
{
"id": 1,
"domain": "yourdomain.com",
"verified": 1,
"aws_region": "us-east-1",
"created_at": "2024-01-15 10:30:00"
}
]
}
Retrieve aggregate send statistics for your account. Optionally filter by tag and/or date range.
| Parameter | Type | Required | Description |
|---|---|---|---|
tag | string | No | Filter to emails with this tag. Alphanumeric, hyphens and underscores only, max 64 characters. |
from | string | No | Start of date range, inclusive. Format: YYYY-MM-DD (e.g. 2025-01-01). |
to | string | No | End of date range, inclusive. Format: YYYY-MM-DD (e.g. 2025-01-31). |
curl "https://api.sendvia.io/v1/stats?tag=welcome-email&from=2025-01-01" \ -H "Authorization: Bearer sv_live_xxxxxxxxxxxxxxxxxxxxxxxx"
{
"stats": {
"total": "124",
"sent": "118",
"delivered": "115",
"opened": "98",
"bounced": "2",
"failed": "1",
"complained": "0"
},
"filters": {
"tag": "welcome-email",
"from": "2025-01-01",
"to": null
}
}
List up to 200 email addresses on your blocklist, sorted by most recently blocked.
curl https://api.sendvia.io/v1/blocklist \
-H "Authorization: Bearer sv_live_xxxxxxxxxxxxxxxxxxxxxxxx"
{
"blocklist": [
{
"email": "[email protected]",
"reason": "bounce",
"blocked_at": "2024-01-20 14:22:10"
}
]
}
reason values: bounce (hard bounce from SES), complaint (spam report), manual (added via dashboard)
Remove an email address from your blocklist, allowing sends to resume.
| Field | Type | Required | Description |
|---|---|---|---|
email | string | Yes | The email address to remove from the blocklist |
curl -X POST https://api.sendvia.io/v1/blocklist/unblock \ -H "Authorization: Bearer sv_live_xxxxxxxxxxxxxxxxxxxxxxxx" \ -H "Content-Type: application/json" \ -d '{"email": "[email protected]"}'
{
"success": true,
"unblocked": "[email protected]"
}
Store reusable email templates with variable placeholders. Reference them by ID or alias when sending.
List all your email templates.
{
"templates": [
{
"id": 1,
"name": "Welcome Email",
"alias": "welcome",
"subject": "Welcome, {{name}}!",
"created_at": "2025-01-10 09:00:00",
"updated_at": "2025-01-10 09:00:00"
}
]
}
Create a new email template.
| Field | Type | Required | Description |
|---|---|---|---|
name | string | Yes | Internal name for this template (max 255 chars) |
alias | string | No | URL-safe identifier for API lookups. Letters, numbers, hyphens, underscores only (max 64 chars). Must be unique per account. |
subject | string | No | Default subject line. Supports {{variable}} placeholders. |
html | string | No | HTML body. Supports {{variable}} placeholders. |
text | string | No | Plain-text body. Supports {{variable}} placeholders. |
{
"id": 3,
"name": "Welcome Email",
"alias": "welcome",
"created_at": "2025-01-10 09:00:00"
}
Update an existing template. Partial updates supported: only provide the fields you want to change.
Same fields as POST /v1/templates, but all are optional.
{
"id": 3,
"name": "Welcome Email v2",
"alias": "welcome",
"subject": "Welcome, {{name}}!",
"updated_at": "2025-01-15 14:30:00"
}
Delete a template permanently.
{
"success": true,
"deleted_id": 3
}
Manage mailing lists and subscribers programmatically. All list endpoints require a premium plan.
List all your mailing lists with subscriber counts.
curl https://api.sendvia.io/v1/lists \
-H "Authorization: Bearer sv_live_xxxxxxxxxxxxxxxxxxxxxxxx"
{
"lists": [
{
"id": 1,
"name": "Product Updates",
"created_at": "2024-06-01 09:00:00",
"subscriber_count": 1250
}
]
}
Create a new mailing list.
| Field | Type | Required | Description |
|---|---|---|---|
name | string | Yes | List name (max 255 characters) |
{
"id": 5,
"name": "My New List",
"created_at": "2024-06-15 12:00:00"
}
Delete a mailing list and all its subscribers. Fails with 409 if the list is referenced by a queued or sending newsletter.
{
"success": true,
"deleted_id": 5
}
Add subscribers to a list in batch. Duplicates and invalid emails are silently skipped. Max 1000 per request.
| Field | Type | Required | Description |
|---|---|---|---|
subscribers | array | Yes | Array of email strings or objects with email, name, and any additional merge tag fields |
{
"subscribers": [
"[email protected]",
{ "email": "[email protected]", "name": "Bob Smith", "company": "Acme Corp" }
]
}
Any additional fields beyond email and name are stored as merge tag data. Use them in newsletter bodies as {{field_name}} (e.g. {{company}}). Unknown tags render as blank.
{
"added": 45,
"skipped": 5,
"total": 50
}
Upload a CSV file for async import. The CSV is queued and processed by the background cron. Max file size: 10 MB.
Content-Type: multipart/form-data with a file field containing the CSV.
CSV format: header row auto-detected and skipped. First column must be email. Extra columns become merge tags usable in newsletters as {{column_name}}.
email,Name,Company,Plan [email protected],Alice,Acme Corp,pro [email protected],Bob,Widgets Inc,free [email protected],Carol,Startup Co,premium
Use these in your newsletter body: Hi {{Name}}, your {{Company}} account ({{Plan}}) ...
Unknown tags render as blank. Re-importing updates existing subscribers rather than creating duplicates.
curl -X POST https://api.sendvia.io/v1/lists/1/import \ -H "Authorization: Bearer sv_live_xxxxxxxxxxxxxxxxxxxxxxxx" \ -F "[email protected]"
{
"import_id": 12,
"status": "pending"
}
Poll the progress of a CSV import.
{
"import_id": 12,
"status": "processing",
"total_rows": 5000,
"imported": 2300,
"skipped": 45
}
status values: pending, processing, done, failed
Create, send, and monitor newsletters via the API. All newsletter endpoints require a premium plan.
List all newsletters. Optionally filter by status with ?status=draft,sent (comma-separated).
{
"newsletters": [
{
"id": 1,
"name": "June Update",
"from_address": "[email protected]",
"subject": "What's new in June",
"status": "sent",
"total_recipients": 450,
"sent_count": 448,
"created_at": "2024-06-01 09:00:00"
}
]
}
Create a new newsletter draft.
| Field | Type | Required | Description |
|---|---|---|---|
name | string | Yes | Internal name for this newsletter |
from_address | string | Yes | Sender email: domain must be verified |
from_name | string | No | Display name for the sender |
reply_to | string | No | Reply-to address |
subject | string | Yes | Email subject line |
body_html | string | One of | HTML body |
body_text | string | One of | Plain-text body. At least one of body_html or body_text is required. |
list_ids | array | Yes | Array of mailing list IDs to send to |
track_opens | boolean | No | Enable open tracking (default: true) |
track_clicks | boolean | No | Enable click tracking (default: true) |
{
"id": 7,
"name": "July Newsletter",
"status": "draft",
"created_at": "2024-07-01 10:00:00"
}
Get full newsletter details including body content and aggregate send stats.
{
"id": 7,
"name": "July Newsletter",
"from_address": "[email protected]",
"subject": "July Update",
"body_html": "<h1>Hello!</h1>...",
"status": "sent",
"list_ids": [1, 3],
"total_recipients": 450,
"stats": {
"queued": 0,
"sent": 50,
"delivered": 380,
"opened": 120,
"bounced": 2
}
}
Update a draft newsletter. Only drafts can be edited; returns 409 for other statuses. Partial updates supported: only provide the fields you want to change.
Same fields as POST /v1/newsletters, but all are optional. Only provided fields are updated.
// Returns the updated newsletter object { "id": 7, "name": "Updated Name", "subject": "New Subject", "status": "draft", ... }
Delete a newsletter and all its send records. Only draft, sent, or stopped newsletters can be deleted.
{
"success": true,
"deleted_id": 7
}
Queue a draft newsletter for sending. The background cron processes the actual delivery. Only draft newsletters can be sent; returns 409 otherwise.
curl -X POST https://api.sendvia.io/v1/newsletters/7/send \
-H "Authorization: Bearer sv_live_xxxxxxxxxxxxxxxxxxxxxxxx"
{
"success": true,
"newsletter_id": 7,
"status": "queued",
"total_recipients": 450
}
Get real-time send progress for a newsletter.
{
"newsletter_id": 7,
"status": "sending",
"total_recipients": 450,
"sent_count": 200,
"stats": {
"queued": 250,
"sent": 150,
"delivered": 48,
"bounced": 2
},
"started_at": "2024-07-01 10:05:00",
"completed_at": null
}
$ch = curl_init('https://api.sendvia.io/v1/send'); curl_setopt_array($ch, [ CURLOPT_RETURNTRANSFER => true, CURLOPT_POST => true, CURLOPT_HTTPHEADER => [ 'Authorization: Bearer sv_live_xxxxxxxxxxxxxxxxxxxxxxxx', 'Content-Type: application/json', ], CURLOPT_POSTFIELDS => json_encode([ 'from' => '[email protected]', 'to' => '[email protected]', 'subject' => 'Hello from sendvia', 'html' => '<p>Hello!</p>', ]), ]); $response = json_decode(curl_exec($ch), true); curl_close($ch); echo $response['message_id'];
Email logs (including body content) are retained based on your plan:
| Plan | Full log | Body content |
|---|---|---|
| Free | 7 days | 3 days |
| Premium | 90 days | 45 days |
After the body retention period, email content (HTML/text) is purged but metadata (to, from, subject, status, timestamps) is kept until the full retention period expires.