Emails
Send transactional emails and retrieve their delivery status.
SMTP Bridge
Legacy systems can submit mail over SMTP and still use the same verified domains, rate limits, suppression checks, queueing, logs, and webhooks as the HTTP API.
Host: smtp.smtpfa.st Port: 587 or 2525 Security: STARTTLS Username: smtpfast Password: YOUR_SMTPFAST_API_KEY
The API key must include the email:send scope. Port 2525 is available for environments that block standard SMTP submission ports.
/v1/emailsSend a single email. The request accepts all standard fields plus Resend-compatible fields like tags and headers.
Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
| from | string | Yes | Sender email address (must be on a verified domain) |
| to | string | string[] | Yes | Recipient email address or array of addresses |
| subject | string | Yes | Email subject line |
| html | string | No | HTML body of the email |
| text | string | No | Plain text fallback body |
| cc | string | string[] | No | CC recipients |
| bcc | string | string[] | No | BCC recipients |
| reply_to | string | string[] | No | Reply-to address(es) |
| tags | array | No | Array of { name, value } pairs for categorization |
| headers | object | No | Custom email headers as key-value pairs |
Request Body
{
"from": "[email protected]",
"to": ["[email protected]"],
"cc": ["[email protected]"],
"reply_to": "[email protected]",
"subject": "Welcome!",
"html": "<h1>Hello!</h1><p>Welcome to our platform.</p>",
"text": "Hello! Welcome to our platform.",
"tags": [
{ "name": "category", "value": "onboarding" }
],
"headers": {
"X-Entity-Ref-ID": "abc-123"
}
}Response
{
"id": "email_abc123"
}/v1/emails/batchSend up to 100 emails in a single request. The body is a JSON array of email objects, each accepting the same fields as the single-send endpoint (from, to, subject, html/text, cc, bcc, reply_to, tags, headers, scheduled_at). Each email is queued and dispatched independently.
Request Body
[
{
"from": "[email protected]",
"to": "[email protected]",
"subject": "Welcome!",
"html": "<h1>Hello User 1!</h1>",
"tags": [{ "name": "campaign", "value": "welcome" }]
},
{
"from": "[email protected]",
"to": ["[email protected]", "[email protected]"],
"subject": "Weekly digest",
"html": "<h1>Your week</h1>",
"scheduled_at": "2026-04-10T14:00:00Z"
}
]Response
{
"batch_id": "batch_abc123",
"count": 2,
"emails": [
{ "id": "email_abc123", "status": "queued" },
{ "id": "email_def456", "status": "scheduled" }
]
}/v1/emailsList sent emails, newest first. Bodies are not included; fetch one by id for those. Requires the email:read scope.
Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
| limit | integer | No | Page size, 1-100. Defaults to 50. |
| page | integer | No | 1-based page number. Ignored when a cursor is given. |
| after | string | No | Return emails older than this id. Not included in the result. Use either after or before, not both. |
| before | string | No | Return emails newer than this id. |
| status | string | No | Filter by current status, e.g. delivered, bounced, scheduled. |
| to | string | No | Exact recipient address. |
Response
{
"data": [
{
"id": "email_abc123",
"from": "[email protected]",
"to": ["[email protected]"],
"subject": "Welcome!",
"status": "delivered",
"source": "api",
"created_at": "2026-04-05T12:00:00Z",
"delivered_at": "2026-04-05T12:00:03Z",
"bounced_at": null,
"error_message": null
}
],
"page": 1,
"limit": 50,
"total": 1284,
"has_more": true
}To find what has not gone out yet, filter on status=scheduled. For per-event detail rather than per-email, use the event log, which needs the logs:read scope.
/v1/emails/:idReschedule an email that has not been sent yet. Only the send time can change; to change the content, cancel it and send again. Requires the email:send scope.
Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
| id | string | Yes | The email ID |
| scheduled_at | string | Yes | New send time in ISO 8601. Must be in the future and within 30 days. |
Response
{
"object": "email",
"id": "email_abc123",
"scheduled_at": "2026-04-09T09:00:00Z"
}/v1/emails/:id/cancelStop an email that has not been sent yet. Works while it is scheduled or queued. Requires the email:send scope.
Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
| id | string | Yes | The email ID |
Response
{
"object": "email",
"id": "email_abc123"
}When cancelling is too late
Both of these return 409 once the send has started, and say which states they would have accepted. A message already handed to the provider cannot be recalled. Emails that belong to a broadcast are refused as well: cancel or reschedule the broadcast instead, so its recipient bookkeeping stays correct.
/v1/emails/:idRetrieve the details and delivery events for a specific email.
Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
| id | string | Yes | The email ID returned from the send endpoint |
Response
{
"id": "email_abc123",
"from": "[email protected]",
"to": ["[email protected]"],
"subject": "Welcome!",
"html": "<h1>Hello!</h1>",
"text": null,
"status": "delivered",
"source": "api",
"created_at": "2026-04-05T12:00:00Z",
"sent_at": "2026-04-05T12:00:01Z",
"delivered_at": "2026-04-05T12:00:03Z",
"bounced_at": null,
"unsubscribed_at": "2026-04-06T08:14:22Z",
"last_event": "unsubscribed",
"events": [
{ "type": "queued", "timestamp": "2026-04-05T12:00:00Z" },
{ "type": "sent", "timestamp": "2026-04-05T12:00:01Z" },
{ "type": "delivered", "timestamp": "2026-04-05T12:00:03Z" },
{ "type": "unsubscribed", "timestamp": "2026-04-06T08:14:22Z" }
]
}About unsubscribed
When the recipient hits the one-click List-Unsubscribe link tied to a delivered message, SMTPfast records an unsubscribed event on the email and sets unsubscribed_at. The top-level status field intentionally stays at its terminal delivery value (delivered, bounced, …) — unsubscribe is a post-delivery recipient action, not a delivery outcome. Check unsubscribed_at (or filter the events array) to detect opt-outs without losing the original delivery state.
Error Codes
| Code | Meaning |
|---|---|
| 400 | Invalid request body (missing required fields, malformed email) |
| 401 | Missing or invalid API key |
| 403 | Domain not verified or sending not allowed for this key |
| 404 | Email ID not found |
| 429 | Rate limit exceeded |