Welcome to the AutoRelay REST API. Our developer platform delivers the same intuitive, one-line send shape as Resend and Postmark, while integrating first-class email campaigns, lists, contact management, and real-time outbound webhooks.
The API conforms to the REST standard, using secure Bearer tokens for authentication and returning predictable, JSON-structured responses. A machine-readable contract is available for code generation in the SDKs section: openapi.yaml.
Get up and running with AutoRelay in less than 60 seconds.
Go to **Project Settings → API keys** in your dashboard. Click **Generate new key** and copy it once. Plain keys are hashed at rest.
Include your API key as a Bearer token in the header of every HTTP request:Authorization: Bearer ak_live_...
Make a POST request to the `/emails` endpoint. Check the code panel on the right side of this section to test.
You can copy the code snippet on the right to trigger your first email. By default, you can send emails from the domain hello@autorelay.net, which is a shared sandbox sender (free, capped at 100 emails/day per project). To send using your own verified domain, configure a domain under .
curl -X POST https://autorelay.net/api/v1/emails \
-H "Authorization: Bearer ak_live_<your-key>" \
-H "Content-Type: application/json" \
-d '{
"to": "you@example.com",
"from": "AutoRelay <hello@autorelay.net>",
"subject": "Hello from AutoRelay",
"html": "<p>It works.</p>"
}'{
"id": "em_abc123",
"success": true,
"messageId": "0100018f-7c6f-a0e0-..."
}All requests directed to the AutoRelay endpoints must authorize using the header format below. Access keys are project-scoped, meaning they isolate lists, templates, and logs safely between separate environments.
ak_live_<64-character-hex> or ak_test_<64-character-hex> for testing.# Header format Authorization: Bearer ak_live_your_key_here # Base API Endpoint https://autorelay.net/api/v1
AutoRelay uses standard HTTP response codes to indicate the success or failure of an API request. In general, `2xx` codes indicate success, `4xx` codes indicate caller validation errors, and `5xx` codes indicate server-side infrastructure issues.
| Status | Meaning | Recommended Mitigation |
|---|---|---|
| 400 | Validation error (e.g. invalid email syntax, missing body parameter) | Inspect error body detail, format correctly, and retry. |
| 401 | Unauthorized (invalid or expired API key) | Validate the Authorization header structure. Verify the key isn't revoked. |
| 402 | Quota exceeded | Your monthly email limits or active plan quota was met. Upgrade in billing settings. |
| 403 | Account flagged or suspended for reputation issues | All mail outbound is paused. Contact support immediately to recover reputation credentials. |
| 404 | Resource not found | Verify the request URL path variable (e.g. listId, emailId) is typed correctly. |
| 429 | Rate limit exceeded | Slow down request volume. Respect the `Retry-After` response header. |
| 500 | Internal Server Error | Failure on our side. Retry with exponential backoff. Monitor **status.autorelay.net**. |
All error payloads return JSON with a single `"error"` key detailing the response. For 403 blocks triggered by reputation locks, the payload also returns `"accountStatus"`.
{
"error": "Account is flagged for review due to high bounce rate. Contact support@autorelay.net.",
"accountStatus": "flagged"
}Rate limits are evaluated in a sliding window, counted per the scope shown for each endpoint (usually your project API key). If you exceed a limit, you will receive a `429 Rate Limit Exceeded` response. The limits below are the exact values currently enforced.
| Method | Endpoint | Scope | Limit |
|---|---|---|---|
| POST | /api/v1/emailsSend a single email | per project key | 100 / min |
| POST | /api/v1/emails/batchSend a batch (up to 100) | per project key | 10 / min |
| Method | Endpoint | Scope | Limit |
|---|---|---|---|
| GET | /api/v1/contactsList contacts | per project key | 60 / min |
| POST | /api/v1/contactsCreate a contact | per project key | 30 / min |
| GET | /api/v1/contacts/:idRead a contact | per project key | 60 / min |
| PUT | /api/v1/contacts/:idUpdate a contact | per project key | 30 / min |
| DELETE | /api/v1/contacts/:idDelete a contact | per project key | 30 / min |
| POST | /api/v1/contacts/importBulk import contacts | per project key | 5 / hour |
| Method | Endpoint | Scope | Limit |
|---|---|---|---|
| GET | /api/v1/listsList lists | per project key | 60 / min |
| POST | /api/v1/listsCreate a list | per project key | 20 / hour |
| Method | Endpoint | Scope | Limit |
|---|---|---|---|
| GET | /api/v1/campaignsList campaigns | per project key | 60 / min |
| POST | /api/v1/campaignsCreate a campaign | per project key | 20 / hour |
| GET | /api/v1/campaigns/:idRead a campaign | per project key | 60 / min |
| PUT | /api/v1/campaigns/:idUpdate a campaign | per project key | 30 / min |
| DELETE | /api/v1/campaigns/:idDelete a campaign | per project key | 30 / min |
| POST | /api/v1/campaigns/:id/launchLaunch a campaign | per project key | 5 / hour |
| Method | Endpoint | Scope | Limit |
|---|---|---|---|
| GET | /api/v1/templatesList templates | per project key | 60 / min |
| Method | Endpoint | Scope | Limit |
|---|---|---|---|
| GET | /api/v1/assetsList assets | per project key | 60 / min |
| POST | /api/v1/assetsUpload an asset | per project key | 30 / min |
| Method | Endpoint | Scope | Limit |
|---|---|---|---|
| POST | /api/v1/domainsAdd a sending domain | per project key | 10 / hour |
| Method | Endpoint | Scope | Limit |
|---|---|---|---|
| POST | /api/v1/webhooksRegister a webhook | per project key | 20 / hour |
| Method | Endpoint | Scope | Limit |
|---|---|---|---|
| GET | /api/v1/statsRead aggregate stats | per project key | 30 / min |
| Method | Endpoint | Scope | Limit |
|---|---|---|---|
| POST | /api/v1/otp/sendSend an OTP code | per project key | 20 / hour |
| POST | /api/v1/otp/sendOTP codes to one recipient | per recipient | 5 / hour |
| POST | /api/v1/otp/verifyVerify an OTP code | per project key | 10 / min |
| POST | /api/v1/unsubscribeProcess an unsubscribe (public) | per IP | 60 / min |
Choose the best mechanism for your use-case.
Best for password resets, order confirmations, and notifications. Sends immediately without needing a pre-configured contact list. Can support key-value `tags` which are echoed back to webhook payloads. Supports batch send calls up to 100 recipients.
POST /api/v1/emails
Best for product updates and newsletter broadcasts. Requires a target contact list. The send operation executes asynchronously as a background queue runner, safeguarding reputation limits and pacing delivery.
Enforces strict CAN-SPAM and GDPR alignment. Automatically dispatches verification pins to incoming subscribers to prevent spam sign-ups.
AutoRelay supports two modes of pagination depending on the dataset characteristics.
Used by list resources like `/contacts`. Straightforward navigation parameters that let you jump to specific index pages.
Used by active log resources like `/emails`. High-performance streaming that mitigates item duplication when new data is inserted while scanning.
To prevent duplicate actions caused by network latency or transient connection timeouts, you can pass an `Idempotency-Key` header with any state-changing POST or PATCH request.
If a request with an existing key is received, AutoRelay returns the cached response of the original call without executing the operation again.
# Header parameter
Idempotency-Key: 7c9e3e58-a0b4-4f4c-...AutoRelay proactively protects sending IP reputability by monitoring bounce and complaint rates. If rates cross safety thresholds within a 24-hour window, mutating endpoints will return `403 Forbidden` with an explanation.
| Status | Definition | Recovery Process |
|---|---|---|
| active | Healthy account state. Normal sending capabilities. | Maintain low bounce rate (<2%) and clean list opt-in lists. |
| flagged | Bounce rate ≥ 2% OR Complaint rate ≥ 0.05% in the last 24h. Outbound sends paused. | Email **support@autorelay.net**. We will review list opt-ins and restore access within 24h. |
| suspended | Critical reputation hit (e.g. spamtrap match). Manual audit required. | Requires compliance review. Contact support to schedule an evaluation. |
| deactivated | Repeated abuse or compliance violation. Terminal state. | None. Account is permanently closed. |
Endpoints to dispatch single or batch emails, retrieve delivery states, and view stats.
/api/v1/emailsSend a single transactional email. You must supply either `html` content or a `template_id` saved in the dashboard. If both are passed, `template_id` wins and `html` is ignored.
| Parameter | Type | Required | Description |
|---|---|---|---|
| to | string | required | Recipient email address. |
| from | string | required | Sender name and email (e.g. 'Jane <jane@domain.com>'). |
| subject | string | required | Email subject line. |
| html | string | optional | Raw inline HTML. Required if template_id is absent. |
| template_id | string | optional | ID of saved template. Required if html is absent. |
| data | object | optional | Flat key-value map for template variable interpolation. |
| tags | object | optional | Metadata returned in webhook events. |
curl -X POST https://autorelay.net/api/v1/emails \
-H "Authorization: Bearer ak_live_..." \
-H "Content-Type: application/json" \
-d '{
"to": "user@example.com",
"from": "Acme <noreply@yourdomain.com>",
"subject": "Reset Password",
"html": "<p>Click <a href=\"https://...\">here</a></p>",
"tags": { "type": "password-reset", "userId": "u_123" }
}'{
"id": "em_abc123",
"success": true,
"messageId": "0100018f-..."
}/api/v1/emails/batchSend up to 100 emails in a single API call. Each row evaluates independently and can mix template and inline HTML formats.
| Parameter | Type | Required | Description |
|---|---|---|---|
| emails | array | required | List of up to 100 email objects structured exactly like single send API. |
curl -X POST https://autorelay.net/api/v1/emails/batch \
-H "Authorization: Bearer ak_live_..." \
-H "Content-Type: application/json" \
-d '{
"emails": [
{
"to": "alice@example.com",
"from": "Acme <noreply@yourdomain.com>",
"subject": "Hi Alice",
"html": "<p>Hello</p>"
},
{
"to": "bob@example.com",
"from": "Acme <noreply@yourdomain.com>",
"subject": "Hi Bob",
"template_id": "tpl_123",
"data": { "name": "Bob" }
}
]
}'{
"object": "batch",
"batch_id": "batch_xyz",
"total": 2,
"sent": 2,
"failed": 0,
"data": [
{ "id": "em_a1", "to": "alice@example.com", "status": "sent", "error": null },
{ "id": "em_b2", "to": "bob@example.com", "status": "sent", "error": null }
]
}/api/v1/emailsRead list of emails sent through the account, with cursor-based pagination.
| Parameter | Type | Required | Description |
|---|---|---|---|
| limit | number | optional | Results count returned. Max 100, default 20. |
| startingAfter | string | optional | Cursor ID representing index after last item. |
| status | string | optional | Filter by status: queued, sent, failed, opened, clicked. |
| order | string | optional | Sorting order: asc, desc. Defaults to asc. |
curl "https://autorelay.net/api/v1/emails?limit=2" \
-H "Authorization: Bearer ak_live_..."{
"emails": [
{ "id": "em_1", "to": "alice@domain.com", "status": "sent", "opens": 1 },
{ "id": "em_2", "to": "bob@domain.com", "status": "failed", "opens": 0 }
],
"total": 120
}/api/v1/emails/:emailIdLookup delivery logs, active open/click count stats, and chronologically mapped tracking events for a single email.
| Parameter | Type | Required | Description |
|---|---|---|---|
| emailId | string | required | Unique target email identifier. |
curl https://autorelay.net/api/v1/emails/em_abc123 \
-H "Authorization: Bearer ak_live_..."{
"email": {
"id": "em_abc123",
"to": "alice@example.com",
"status": "sent",
"opens": 1,
"clicks": 0
},
"events": [
{ "type": "queued", "createdAt": "2026-05-25T10:00:00Z" },
{ "type": "sent", "createdAt": "2026-05-25T10:00:02Z" },
{ "type": "opened", "createdAt": "2026-05-25T10:15:30Z" }
]
}/api/v1/statsReturns project-scoped counters mapping bounce rates, complaint metrics, domain quantities, and monthly usage spikes.
Useful for plotting dashboard charts or dynamically tracking plan health on admin frameworks.
curl https://autorelay.net/api/v1/stats \
-H "Authorization: Bearer ak_live_..."{
"contacts": 1500,
"campaigns": {
"total": 45,
"sending": 1,
"completed": 40
},
"emailsThisMonth": 12500,
"domains": 2
}Endpoints to construct custom subscriber entries, read paginated listings, or trigger bulk uploads.
/api/v1/contactsCreate a new subscriber inside an active list.
| Parameter | Type | Required | Description |
|---|---|---|---|
| string | required | Subscriber email address. | |
| name | string | optional | Full name parameter. |
| listId | string | required | Target list ID to insert contact. |
curl -X POST https://autorelay.net/api/v1/contacts \
-H "Authorization: Bearer ak_live_..." \
-H "Content-Type: application/json" \
-d '{
"email": "alice@example.com",
"name": "Alice Smith",
"listId": "lst_xyz"
}'{
"id": "con_123",
"email": "alice@example.com",
"name": "Alice Smith",
"status": "subscribed",
"listId": "lst_xyz"
}/api/v1/contactsList contacts with offset pagination, filtering, and search criteria.
| Parameter | Type | Required | Description |
|---|---|---|---|
| listId | string | required | Filter contacts belonging to this list. |
| page | number | optional | Index page. Defaults to 1. |
| pageSize | number | optional | Item quantity. Max 200, defaults to 50. |
| search | string | optional | Wildcard search key matching name or email. |
| status | string | optional | Status filter: subscribed, unsubscribed, bounced. |
curl "https://autorelay.net/api/v1/contacts?listId=lst_xyz&page=1&pageSize=2" \
-H "Authorization: Bearer ak_live_..."{
"contacts": [
{ "id": "con_1", "email": "a@example.com", "status": "subscribed" },
{ "id": "con_2", "email": "b@example.com", "status": "unsubscribed" }
],
"pagination": {
"total": 450,
"page": 1,
"pageSize": 2
}
}/api/v1/contacts/importImport up to 10,000 contacts at once in a single request. Skips existing emails.
| Parameter | Type | Required | Description |
|---|---|---|---|
| listId | string | required | Target subscriber list ID. |
| contacts | array | required | Array of subscriber objects (each with email and optional name). |
curl -X POST https://autorelay.net/api/v1/contacts/import \
-H "Authorization: Bearer ak_live_..." \
-H "Content-Type: application/json" \
-d '{
"listId": "lst_xyz",
"contacts": [
{ "email": "joe@example.com", "name": "Joe" },
{ "email": "kim@example.com", "name": "Kim" }
]
}'{
"success": true,
"importedCount": 2,
"skippedCount": 0
}/api/v1/contacts/:contactIdRead a single contact by ID.
Returns the contact's profile fields and current subscription `status`.
curl https://autorelay.net/api/v1/contacts/con_123 \
-H "Authorization: Bearer ak_live_..."{
"success": true,
"data": {
"id": "con_123",
"email": "alice@example.com",
"name": "Alice Smith",
"company": null,
"listId": "lst_xyz",
"status": "subscribed",
"createdAt": "2026-05-25T10:00:00.000Z"
}
}/api/v1/contacts/:contactIdUpdate a contact. Send any subset of the fields below.
| Parameter | Type | Required | Description |
|---|---|---|---|
| name | string | optional | Full name. |
| string | optional | Subscriber email address. | |
| status | string | optional | Only 'subscribed' or 'unsubscribed' — bounce/complaint states are platform-managed. |
| company | string | optional | Company name. |
| listId | string | optional | Move the contact to a different list. |
curl -X PUT https://autorelay.net/api/v1/contacts/con_123 \
-H "Authorization: Bearer ak_live_..." \
-H "Content-Type: application/json" \
-d '{ "name": "Jane Doe", "status": "unsubscribed" }'{
"success": true
}/api/v1/contacts/:contactIdPermanently remove a contact from your project.
This is irreversible. To stop emailing a contact without losing their record, set `status` to `unsubscribed` via the update endpoint instead.
curl -X DELETE https://autorelay.net/api/v1/contacts/con_123 \
-H "Authorization: Bearer ak_live_..."{
"success": true
}Endpoints to isolate subscriber groups for newsletter broadcasts and campaigns.
/api/v1/listsCreate a new contact mailing list.
| Parameter | Type | Required | Description |
|---|---|---|---|
| name | string | required | Human readable list label. |
curl -X POST https://autorelay.net/api/v1/lists \
-H "Authorization: Bearer ak_live_..." \
-H "Content-Type: application/json" \
-d '{ "name": "Subscribers" }'{
"id": "lst_xyz",
"name": "Subscribers",
"createdAt": "2026-05-25T10:00:00Z"
}/api/v1/listsRetrieve every contact list in the project, each with its live contact count.
Use the returned `id` values as the `listId` parameter when creating contacts, importing in bulk, or launching campaigns.
curl https://autorelay.net/api/v1/lists \
-H "Authorization: Bearer ak_live_..."{
"success": true,
"data": [
{ "id": "lst_xyz", "name": "Subscribers", "contactCount": 1240 }
]
}Endpoints to draft broadcasts, review progress, verify templates, and initiate launches.
/api/v1/campaignsInitialize a draft campaign targeted at a contact list.
| Parameter | Type | Required | Description |
|---|---|---|---|
| name | string | required | Internal campaign label. |
| subject | string | required | Broadcast subject line. |
| fromEmail | string | required | Sender domain email (e.g. news@domain.com). |
| listId | string | required | Target recipient list identifier. |
| content | string | required | HTML template body markup. |
curl -X POST https://autorelay.net/api/v1/campaigns \
-H "Authorization: Bearer ak_live_..." \
-H "Content-Type: application/json" \
-d '{
"name": "Spring Sale",
"subject": "Discount!",
"fromEmail": "sales@yourdomain.com",
"listId": "lst_xyz",
"content": "<h1>Save 20%</h1>"
}'{
"id": "cmp_123",
"name": "Spring Sale",
"status": "draft",
"listId": "lst_xyz"
}/api/v1/campaignsList campaigns with offset pagination, optionally filtered by status.
| Parameter | Type | Required | Description |
|---|---|---|---|
| page | number | optional | Index page. Defaults to 1. |
| pageSize | number | optional | Items per page. Defaults to 20. |
| status | string | optional | Filter: draft, sending, or completed. |
curl "https://autorelay.net/api/v1/campaigns?page=1&pageSize=20&status=completed" \
-H "Authorization: Bearer ak_live_..."{
"success": true,
"data": [
{ "id": "cmp_123", "name": "Spring Sale", "status": "completed", "sentCount": 1240 }
],
"pagination": { "total": 12, "page": 1, "pageSize": 20 }
}/api/v1/campaigns/:campaignId/launchTrigger campaign delivery. Spawns an isolated background runner job that processes the recipient list. Updates the campaign status from `draft` to `sending`.
Once launched, updating the draft layout content or recipient list is blocked. Querying the campaign metadata status (`GET /api/v1/campaigns/:id`) details active queue percentages.
curl -X POST https://autorelay.net/api/v1/campaigns/cmp_123/launch \
-H "Authorization: Bearer ak_live_..."{
"success": true,
"jobId": "job_camp_123",
"status": "sending"
}/api/v1/campaigns/:campaignIdRead campaign metadata and live send statistics. Poll this while a launch is in progress to track delivery.
`status` moves `draft` → `sending` → `completed`. The `stats` object is populated as delivery, open, and click events arrive.
curl https://autorelay.net/api/v1/campaigns/cmp_123 \
-H "Authorization: Bearer ak_live_..."{
"success": true,
"data": {
"id": "cmp_123",
"status": "completed",
"sentCount": 1240,
"stats": { "delivered": 1198, "opened": 524, "clicked": 87 }
}
}/api/v1/campaigns/:campaignIdEdit a draft campaign. Once a campaign is launched its content and recipient list are locked.
| Parameter | Type | Required | Description |
|---|---|---|---|
| name | string | optional | Internal campaign label. |
| subject | string | optional | Broadcast subject line. |
| fromEmail | string | optional | Sender domain email. |
| listId | string | optional | Target recipient list identifier. |
| content | string | optional | HTML template body markup. |
curl -X PUT https://autorelay.net/api/v1/campaigns/cmp_123 \
-H "Authorization: Bearer ak_live_..." \
-H "Content-Type: application/json" \
-d '{ "subject": "Updated subject line" }'{
"success": true,
"data": {
"id": "cmp_123",
"status": "draft",
"subject": "Updated subject line"
}
}/api/v1/campaigns/:campaignIdDelete a campaign. Only drafts can be deleted — a launched campaign owns delivery logs and analytics that are preserved.
Attempting to delete a campaign that has already been launched returns `409 Conflict` with the message `Only draft campaigns can be deleted`.
curl -X DELETE https://autorelay.net/api/v1/campaigns/cmp_123 \
-H "Authorization: Bearer ak_live_..."{
"id": "cmp_123",
"deleted": true
}Read layouts built inside the visual dashboard editor.
/api/v1/templatesList saved templates for use with the Send API (`template_id` parameter).
Templates are designed visually in the dashboard at **/app/templates**. Use the returned ID values to send transactional emails via our SDKs or HTTP requests.
curl https://autorelay.net/api/v1/templates \
-H "Authorization: Bearer ak_live_..."{
"templates": [
{
"id": "tpl_abc123",
"name": "Welcome Email",
"subject": "Welcome!",
"createdAt": "2026-05-20T12:00:00Z"
}
]
}Upload and host files (images, PDFs, any type up to 2MB) and reuse the public link in emails, templates and campaigns.
/api/v1/assetsUpload a file as `multipart/form-data` (field name `file`, scope `assets.write`). Returns the hosted asset with a public `url`. Max size 2MB.
The returned `url` is permanent and public — drop it into an image block, a button link, or a transactional email.
curl -X POST https://autorelay.net/api/v1/assets \
-H "Authorization: Bearer ak_live_..." \
-F "file=@/path/to/logo.png"{
"object": "asset",
"id": "...",
"name": "logo.png",
"url": "https://storage.googleapis.com/.../logo.png",
"content_type": "image/png",
"category": "image",
"size": 20480,
"created_at": "2026-06-19T12:00:00Z"
}/api/v1/assetsList uploaded assets (scope `assets.read`). Filter by `category` (`image`, `pdf`, `document`, `video`, `audio`, `other`) and paginate with `cursor`.
Results are ordered newest-first and follow the standard list envelope with `has_more` and `next_cursor`.
curl "https://autorelay.net/api/v1/assets?category=image" \
-H "Authorization: Bearer ak_live_..."{
"object": "list",
"data": [
{ "object": "asset", "id": "...", "name": "logo.png", "url": "https://..." }
],
"has_more": false,
"next_cursor": null
}Endpoints to register domains, retrieve DKIM/CNAME records, and trigger verification checks.
/api/v1/domainsAdd a new sending domain. Returns DKIM tokens to publish as DNS CNAME records.
| Parameter | Type | Required | Description |
|---|---|---|---|
| domain | string | required | Apex domain or subdomain (e.g. mail.domain.com). |
curl -X POST https://autorelay.net/api/v1/domains \
-H "Authorization: Bearer ak_live_..." \
-H "Content-Type: application/json" \
-d '{ "domain": "yourdomain.com" }'{
"id": "dom_abc",
"domain": "yourdomain.com",
"status": "pending",
"dkimTokens": [
"token1_val",
"token2_val",
"token3_val"
]
}/api/v1/domainsList every sending domain in the project with its verification status.
`status` is one of `pending` or `verified`. Fetch a single domain to get the full DKIM/CNAME record set.
curl https://autorelay.net/api/v1/domains \
-H "Authorization: Bearer ak_live_..."{
"object": "list",
"data": [
{
"id": "dom_abc",
"object": "domain",
"domain": "yourdomain.com",
"status": "verified",
"dkim_tokens": ["token1_val", "token2_val", "token3_val"],
"verified_at": "2026-05-25T10:00:00.000Z",
"created_at": "2026-05-25T09:00:00.000Z"
}
]
}/api/v1/domains/:domainId/verifyTrigger immediate verification check for registered DKIM, SPF, and DMARC records.
Check out the **Domain Setup** guide in the section below for details on required DNS records.
curl -X POST https://autorelay.net/api/v1/domains/dom_abc/verify \
-H "Authorization: Bearer ak_live_..."{
"status": "verified",
"domain": "yourdomain.com"
}/api/v1/domains/:domainIdFetch a single domain with its DKIM tokens and the exact CNAME records to publish on your DNS.
The `dns_records` array gives you ready-to-paste CNAME entries. Once they propagate, call the verify endpoint to flip `status` to `verified`.
curl https://autorelay.net/api/v1/domains/dom_abc \
-H "Authorization: Bearer ak_live_..."{
"id": "dom_abc",
"object": "domain",
"domain": "yourdomain.com",
"status": "verified",
"dkim_tokens": ["token1_val", "token2_val", "token3_val"],
"dns_records": [
{
"type": "CNAME",
"name": "token1_val._domainkey.yourdomain.com",
"value": "token1_val.dkim.amazonses.com"
}
],
"verified_at": "2026-05-25T10:00:00.000Z",
"created_at": "2026-05-25T09:00:00.000Z"
}/api/v1/domains/:domainIdRemove a sending domain. This also removes its verified sending identity.
After deletion you can no longer send from addresses on this domain until it is re-added and re-verified.
curl -X DELETE https://autorelay.net/api/v1/domains/dom_abc \
-H "Authorization: Bearer ak_live_..."{
"id": "dom_abc",
"deleted": true
}Endpoints to register URLs and subscribe to real-time events.
/api/v1/webhooksRegister a new webhook endpoint and event subscriptions.
| Parameter | Type | Required | Description |
|---|---|---|---|
| url | string | required | Destination HTTPS target URL endpoint on your server. |
| events | array | required | List of events. Supported values: email.sent, email.opened, email.clicked, email.bounced, email.complained, email.failed. |
curl -X POST https://autorelay.net/api/v1/webhooks \
-H "Authorization: Bearer ak_live_..." \
-H "Content-Type: application/json" \
-d '{
"url": "https://yourapp.com/hooks/autorelay",
"events": ["email.opened", "email.clicked"]
}'{
"id": "whk_123",
"url": "https://yourapp.com/hooks/autorelay",
"secret": "whsec_abcd123...",
"events": ["email.opened", "email.clicked"],
"isActive": true
}/api/v1/webhooksList all webhook endpoints registered for the project.
The signing `secret` is only returned once at creation time, so it is omitted from list and read responses.
curl https://autorelay.net/api/v1/webhooks \
-H "Authorization: Bearer ak_live_..."{
"object": "list",
"data": [
{
"id": "whk_123",
"object": "webhook",
"url": "https://yourapp.com/hooks/autorelay",
"events": ["email.opened", "email.clicked"],
"active": true,
"created_at": "2026-05-25T10:00:00.000Z"
}
]
}/api/v1/webhooks/:webhookIdRead a single webhook endpoint.
Returns the current `url`, subscribed `events`, and whether the endpoint is `active`.
curl https://autorelay.net/api/v1/webhooks/whk_123 \
-H "Authorization: Bearer ak_live_..."{
"id": "whk_123",
"object": "webhook",
"url": "https://yourapp.com/hooks/autorelay",
"events": ["email.opened", "email.clicked"],
"active": true,
"created_at": "2026-05-25T10:00:00.000Z"
}/api/v1/webhooks/:webhookIdUpdate a webhook's URL, event subscriptions, or active state. Send any subset of the fields.
| Parameter | Type | Required | Description |
|---|---|---|---|
| url | string | optional | New destination HTTPS endpoint. |
| events | array | optional | Replacement list of subscribed events (non-empty). |
| active | boolean | optional | Pause or resume deliveries without deleting the webhook. |
curl -X PATCH https://autorelay.net/api/v1/webhooks/whk_123 \
-H "Authorization: Bearer ak_live_..." \
-H "Content-Type: application/json" \
-d '{ "events": ["email.failed"], "active": false }'{
"id": "whk_123",
"object": "webhook",
"url": "https://yourapp.com/hooks/autorelay",
"events": ["email.failed"],
"active": false,
"created_at": "2026-05-25T10:00:00.000Z"
}/api/v1/webhooks/:webhookId/deliveriesList failed delivery attempts for a webhook so you can debug endpoint outages.
| Parameter | Type | Required | Description |
|---|---|---|---|
| limit | number | optional | Max rows to return. 1–100, defaults to 50. |
curl "https://autorelay.net/api/v1/webhooks/whk_123/deliveries?limit=20" \
-H "Authorization: Bearer ak_live_..."{
"object": "list",
"webhook_id": "whk_123",
"has_more": false,
"data": [
{
"id": "whd_1",
"object": "webhook_delivery",
"event_id": "evt_abc",
"event_type": "email.opened",
"status": "failed",
"error": "connect ETIMEDOUT",
"attempts": 3,
"replay_count": 0,
"last_attempt_at": "2026-05-25T10:05:00.000Z",
"created_at": "2026-05-25T10:00:00.000Z",
"resolved_at": null
}
]
}/api/v1/webhooks/:webhookIdRemove a webhook endpoint. Deliveries stop immediately.
To temporarily stop deliveries without losing the endpoint config, PATCH `active` to `false` instead.
curl -X DELETE https://autorelay.net/api/v1/webhooks/whk_123 \
-H "Authorization: Bearer ak_live_..."{
"id": "whk_123",
"deleted": true
}The **unsubscribe** endpoints are public — they authenticate with a signed token carried in the email link, so no API key is needed. The **OTP** endpoints **do require your API key** (scope `emails.send`) and send real email, so call them from your backend — never the browser.
/api/v1/otp/sendGenerate and dispatch a 6-digit confirmation pin to an email address.
| Parameter | Type | Required | Description |
|---|---|---|---|
| string | required | Destination email address. | |
| purpose | string | required | OTP objective. Set to 'subscribe' for list signups. |
curl -X POST https://autorelay.net/api/v1/otp/send \
-H "Authorization: Bearer ak_live_..." \
-H "Content-Type: application/json" \
-d '{ "email": "user@domain.com" }'{
"ok": true,
"expiresAt": "2026-05-25T10:10:00.000Z"
}/api/v1/otp/verifyVerify a dispatched OTP code.
| Parameter | Type | Required | Description |
|---|---|---|---|
| string | required | Subscriber email. | |
| code | string | required | 6-digit OTP string. |
| purpose | string | required | Matches code generation purpose. |
curl -X POST https://autorelay.net/api/v1/otp/verify \
-H "Authorization: Bearer ak_live_..." \
-H "Content-Type: application/json" \
-d '{ "email": "user@domain.com", "code": "123456" }'{
"ok": true
}/api/v1/unsubscribeMark subscriber status unsubscribed from the corresponding list using a secure link token.
| Parameter | Type | Required | Description |
|---|---|---|---|
| token | string | required | Cryptographic unsubscribe token generated server-side. |
curl -X POST https://autorelay.net/api/v1/unsubscribe \
-H "Content-Type: application/json" \
-d '{ "token": "tok_unsub_abc123" }'{
"ok": true
}/api/v1/unsubscribeThe destination behind the `{{unsubscribe_url}}` merge field. Opening it applies the token and returns a browser-ready confirmation page.
| Parameter | Type | Required | Description |
|---|---|---|---|
| token | string | required | Signed unsubscribe token, passed as a query parameter. |
# Users click this link directly from the email footer —
# no API call needed. It renders an HTML confirmation page.
https://autorelay.net/api/v1/unsubscribe?token=tok_unsub_abc123<!-- 200 text/html -->
<!-- A "You've been unsubscribed" confirmation page. -->Verify domain ownership via DNS records to remove limits and send from your custom email addresses.
Add the following five records to your DNS provider. While DKIM is technically sufficient for email authorization, most email clients (e.g. Gmail, Outlook) will filter your messages as spam if SPF and DMARC records are absent.
| Type | Host / Name | Value | Purpose |
|---|---|---|---|
| CNAME | <token1>._domainkey | <token1>.dkim.amazonses.com | DKIM verification (1/3) |
| CNAME | <token2>._domainkey | <token2>.dkim.amazonses.com | DKIM verification (2/3) |
| CNAME | <token3>._domainkey | <token3>.dkim.amazonses.com | DKIM verification (3/3) |
| TXT | @ (apex) | "v=spf1 include:amazonses.com ~all" | SPF validation policy |
| TXT | _dmarc | "v=DMARC1; p=none; rua=mailto:postmaster@domain.com" | DMARC delivery reports |
CNAME, Name: <token1>._domainkey, Target: <token1>.dkim.amazonses.com.Cryptographically verify incoming payloads to ensure they originate from AutoRelay.
Every webhook request sent to your server includes three signature headers:
| Header | Value |
|---|---|
| X-Webhook-Signature | Hex HMAC-SHA256 signature calculated from the raw payload body. |
| X-Webhook-Id | Unique event uuid. Recommended for deduplication tracking. |
| X-Webhook-Event | Payload event category type (e.g. email.opened). |
# Webhook Header Verification
X-Webhook-Signature: <computed-hmac-sha256>
X-Webhook-Id: evt_abc123
X-Webhook-Event: email.openedIntegrate AutoRelay with ready-made SDK packages.
| Language | Package Manager | Source / Import |
|---|---|---|
| OpenAPI 3.1 Spec | Swagger / Redoc generator | Download openapi.yaml |
For local integration and sandbox development, you can route calls directly to your local instance.
http://localhost:3000/api/v1To avoid burning through your email quota during development, generate a **Test Mode Key** (`ak_test_...`) in your dashboard. Outbound emails dispatched with a test key are logged in your developer dashboard for verification, but are not actually delivered.
# Local testing headers
Authorization: Bearer ak_test_sandbox_key
Content-Type: application/jsonTrack system uptime, incident history, and current operational efficiency:
status.autorelay.netDirect contact line to our developer relations team for assistance:
support@autorelay.netGenerate an API key in your project settings and start sending emails in minutes.