Features Pricing Compare Cost calculator Guides Quickstarts Docs All systems nominal

API reference

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.

Last reviewed:
Authentication

All API requests require a Bearer token in the Authorization header.

Header
Authorization: Bearer sv_live_xxxxxxxxxxxxxxxxxxxxxxxx

The key above is a placeholder. Create a free account to get your own and start sending.

POST /v1/send

Send a transactional email through a verified domain.

Request body (JSON)

FieldTypeRequiredDescription
fromstringYesSender address: domain must be verified in your account
from_namestringNoDisplay name for the sender (e.g. My App). Shown as "My App <[email protected]>" in the recipient's inbox.
tostring | arrayYesRecipient 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.
subjectstringYesEmail subject line
htmlstringOne ofHTML body of the email
textstringOne ofPlain-text body (fallback). At least one of html or text is required.
tagstringNoOptional 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_opensbooleanNoWhether 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_clicksbooleanNoWhether 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_idintegerNoID of a stored email template. The template's subject, HTML, and text are used as defaults; explicit subject, html, text params override them.
template_aliasstringNoAlias of a stored email template (alternative to template_id). Aliases are URL-safe identifiers you set when creating a template.
variablesobjectNoKey-value pairs for template variable substitution. Replaces {{key}} placeholders in the template's subject, HTML, and text.
send_atstringNoSchedule 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.

Optional headers

HeaderDescription
Idempotency-KeyPrevents 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.

Example request

curl
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 response: single recipient 200

JSON
{
  "success":    true,
  "message_id": "0102018f1234abcd-...",
  "log_id":     42
}

Multi-recipient request example

JSON body
{
  "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.

Multi-recipient response 200 / 207

JSON
{
  "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.

Error responses

StatusCause
401Missing or invalid API key
422Validation error: invalid address, missing field, recipient on blocklist, domain not verified, or too many recipients
429Daily send limit reached; resets at midnight UTC
207Multi-recipient partial success; some sends failed (check results array)
502SES send failed (single recipient) or all recipients failed (multi-recipient)
POST /v1/send/batch

Send up to 500 unique emails in a single request. Each message can have different content, recipients, templates, and scheduling.

Request body (JSON)

FieldTypeRequiredDescription
messagesarrayYesArray of message objects. Max 500.
Each message object:
fromstringYesSender address: domain must be verified
tostringYesSingle recipient email address
subjectstringYes*Email subject (*can come from template)
html / textstringOne of*Email body (*can come from template)
template_aliasstringNoTemplate alias for this message
variablesobjectNoTemplate variable substitution
send_atstringNoSchedule this message for future delivery
tagstringNoTag for this message

Supports the Idempotency-Key header. Daily send limit is checked against the full batch count upfront.

Response 200 / 207

JSON
{
  "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 }
  ]
}
DELETE /v1/scheduled/{id}

Cancel a scheduled email before it is sent. Only works while the email status is scheduled.

Path parameters

ParameterTypeDescription
idintegerThe log_id returned when the email was scheduled

Success response 200

JSON
{
  "success":   true,
  "cancelled": 42
}
GET /v1/domains

List all domains registered on your account and their verification status.

Example request

curl
curl https://api.sendvia.io/v1/domains \
  -H "Authorization: Bearer sv_live_xxxxxxxxxxxxxxxxxxxxxxxx"

Success response 200

JSON
{
  "domains": [
    {
      "id":         1,
      "domain":     "yourdomain.com",
      "verified":   1,
      "aws_region": "us-east-1",
      "created_at": "2024-01-15 10:30:00"
    }
  ]
}
GET /v1/stats

Retrieve aggregate send statistics for your account. Optionally filter by tag and/or date range.

Query parameters

ParameterTypeRequiredDescription
tagstringNoFilter to emails with this tag. Alphanumeric, hyphens and underscores only, max 64 characters.
fromstringNoStart of date range, inclusive. Format: YYYY-MM-DD (e.g. 2025-01-01).
tostringNoEnd of date range, inclusive. Format: YYYY-MM-DD (e.g. 2025-01-31).

Example request

curl
curl "https://api.sendvia.io/v1/stats?tag=welcome-email&from=2025-01-01" \
  -H "Authorization: Bearer sv_live_xxxxxxxxxxxxxxxxxxxxxxxx"

Success response 200

JSON
{
  "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
  }
}
GET /v1/blocklist

List up to 200 email addresses on your blocklist, sorted by most recently blocked.

Example request

curl
curl https://api.sendvia.io/v1/blocklist \
  -H "Authorization: Bearer sv_live_xxxxxxxxxxxxxxxxxxxxxxxx"

Success response 200

JSON
{
  "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)

POST /v1/blocklist/unblock

Remove an email address from your blocklist, allowing sends to resume.

Request body (JSON)

FieldTypeRequiredDescription
emailstringYesThe email address to remove from the blocklist

Example request

curl
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 response 200

JSON
{
  "success":   true,
  "unblocked": "[email protected]"
}

Email Templates

Store reusable email templates with variable placeholders. Reference them by ID or alias when sending.

GET /v1/templates

List all your email templates.

Success response 200

JSON
{
  "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"
    }
  ]
}
POST /v1/templates

Create a new email template.

Request body (JSON)

FieldTypeRequiredDescription
namestringYesInternal name for this template (max 255 chars)
aliasstringNoURL-safe identifier for API lookups. Letters, numbers, hyphens, underscores only (max 64 chars). Must be unique per account.
subjectstringNoDefault subject line. Supports {{variable}} placeholders.
htmlstringNoHTML body. Supports {{variable}} placeholders.
textstringNoPlain-text body. Supports {{variable}} placeholders.

Success response 201

JSON
{
  "id": 3,
  "name": "Welcome Email",
  "alias": "welcome",
  "created_at": "2025-01-10 09:00:00"
}
PUT /v1/templates/{id}

Update an existing template. Partial updates supported: only provide the fields you want to change.

Request body (JSON)

Same fields as POST /v1/templates, but all are optional.

Success response 200

JSON
{
  "id": 3,
  "name": "Welcome Email v2",
  "alias": "welcome",
  "subject": "Welcome, {{name}}!",
  "updated_at": "2025-01-15 14:30:00"
}
DELETE /v1/templates/{id}

Delete a template permanently.

Success response 200

JSON
{
  "success": true,
  "deleted_id": 3
}

Mailing Lists Premium

Manage mailing lists and subscribers programmatically. All list endpoints require a premium plan.

GET /v1/lists

List all your mailing lists with subscriber counts.

curl
curl https://api.sendvia.io/v1/lists \
  -H "Authorization: Bearer sv_live_xxxxxxxxxxxxxxxxxxxxxxxx"

Success response 200

JSON
{
  "lists": [
    {
      "id": 1,
      "name": "Product Updates",
      "created_at": "2024-06-01 09:00:00",
      "subscriber_count": 1250
    }
  ]
}
POST /v1/lists

Create a new mailing list.

Request body (JSON)

FieldTypeRequiredDescription
namestringYesList name (max 255 characters)

Success response 201

JSON
{
  "id": 5,
  "name": "My New List",
  "created_at": "2024-06-15 12:00:00"
}
DELETE /v1/lists/{id}

Delete a mailing list and all its subscribers. Fails with 409 if the list is referenced by a queued or sending newsletter.

Success response 200

JSON
{
  "success": true,
  "deleted_id": 5
}
POST /v1/lists/{id}/subscribers

Add subscribers to a list in batch. Duplicates and invalid emails are silently skipped. Max 1000 per request.

Request body (JSON)

FieldTypeRequiredDescription
subscribersarrayYesArray of email strings or objects with email, name, and any additional merge tag fields

Example request

JSON body
{
  "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.

Success response 200

JSON
{
  "added":   45,
  "skipped": 5,
  "total":   50
}
POST /v1/lists/{id}/import

Upload a CSV file for async import. The CSV is queued and processed by the background cron. Max file size: 10 MB.

Request

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}}.

subscribers.csv
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
curl -X POST https://api.sendvia.io/v1/lists/1/import \
  -H "Authorization: Bearer sv_live_xxxxxxxxxxxxxxxxxxxxxxxx" \
  -F "[email protected]"

Success response 202

JSON
{
  "import_id": 12,
  "status":    "pending"
}
GET /v1/lists/{id}/import/{importId}

Poll the progress of a CSV import.

Success response 200

JSON
{
  "import_id":  12,
  "status":     "processing",
  "total_rows": 5000,
  "imported":   2300,
  "skipped":    45
}

status values: pending, processing, done, failed

Newsletters Premium

Create, send, and monitor newsletters via the API. All newsletter endpoints require a premium plan.

GET /v1/newsletters

List all newsletters. Optionally filter by status with ?status=draft,sent (comma-separated).

Success response 200

JSON
{
  "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"
    }
  ]
}
POST /v1/newsletters

Create a new newsletter draft.

Request body (JSON)

FieldTypeRequiredDescription
namestringYesInternal name for this newsletter
from_addressstringYesSender email: domain must be verified
from_namestringNoDisplay name for the sender
reply_tostringNoReply-to address
subjectstringYesEmail subject line
body_htmlstringOne ofHTML body
body_textstringOne ofPlain-text body. At least one of body_html or body_text is required.
list_idsarrayYesArray of mailing list IDs to send to
track_opensbooleanNoEnable open tracking (default: true)
track_clicksbooleanNoEnable click tracking (default: true)

Success response 201

JSON
{
  "id": 7,
  "name": "July Newsletter",
  "status": "draft",
  "created_at": "2024-07-01 10:00:00"
}
GET /v1/newsletters/{id}

Get full newsletter details including body content and aggregate send stats.

Success response 200

JSON
{
  "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
  }
}
PUT /v1/newsletters/{id}

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.

Request body (JSON)

Same fields as POST /v1/newsletters, but all are optional. Only provided fields are updated.

Success response 200

JSON
// Returns the updated newsletter object
{
  "id": 7,
  "name": "Updated Name",
  "subject": "New Subject",
  "status": "draft",
  ...
}
DELETE /v1/newsletters/{id}

Delete a newsletter and all its send records. Only draft, sent, or stopped newsletters can be deleted.

Success response 200

JSON
{
  "success": true,
  "deleted_id": 7
}
POST /v1/newsletters/{id}/send

Queue a draft newsletter for sending. The background cron processes the actual delivery. Only draft newsletters can be sent; returns 409 otherwise.

Example request

curl
curl -X POST https://api.sendvia.io/v1/newsletters/7/send \
  -H "Authorization: Bearer sv_live_xxxxxxxxxxxxxxxxxxxxxxxx"

Success response 200

JSON
{
  "success": true,
  "newsletter_id": 7,
  "status": "queued",
  "total_recipients": 450
}
GET /v1/newsletters/{id}/status

Get real-time send progress for a newsletter.

Success response 200

JSON
{
  "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
}
Error codes (Lists & Newsletters)
StatusCause
201Resource created (list, newsletter draft)
202CSV import accepted (async processing)
400Invalid JSON body
401Missing or invalid API key
403Not on premium plan, domain banned, or missing DNS records
404Resource not found (list, newsletter, import)
409Conflict: newsletter not in editable/sendable state, or list used by active send
422Validation error: missing required fields, invalid values
Code examples
PHP
$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'];
Log Retention

Email logs (including body content) are retained based on your plan:

PlanFull logBody content
Free7 days3 days
Premium90 days45 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.