API reference
Public developer REST endpoints, grouped by resource. Account, billing, admin, auth, and internal routes are intentionally documented separately from this API-key surface.
Request anatomy
Build requests from the versioned base URL, a scoped bearer key, and JSON only when a body is present.
curl -X POST https://sendix.dev/api/v1/emails \
-H "Authorization: Bearer $SENDIX_API_KEY" \
-H "Content-Type: application/json" \
-H "Accept: application/json" \
-H "X-Request-Id: checkout-order_9f83a2" \
-H "Idempotency-Key: order_9f83a2-receipt" \
-d '{
"from": "[email protected]",
"to": "[email protected]",
"subject": "Your receipt",
"text": "Thank you for your order."
}'| Header | When | Purpose |
|---|---|---|
| Authorization | Required | Bearer API key with the endpoint's scope. |
| Content-Type | JSON body | Set to application/json for non-empty request bodies. |
| Idempotency-Key | Create send | Makes an ambiguous network retry return the original email ID. |
| X-Request-Id | Recommended | 8–128 safe characters for log and support correlation. |
The API also accepts a valid X-Correlation-Id when X-Request-Id is absent. Sendix reflects the selected ID in the response. Do not place credentials or sensitive recipient data in either identifier.
Responses
Branch on the HTTP status first, then use the machine-readable error code.
201 Created
X-Request-Id: checkout-order_9f83a2
Content-Type: application/json
{ "id": "2f0b4d7e-..." }
400 Bad Request
X-Request-Id: checkout-order_9f83a2
Content-Type: application/json
{
"error": {
"code": "validation_error",
"message": "Invalid request",
"details": { "fieldErrors": { "to": ["Invalid email"] } },
"request_id": "checkout-order_9f83a2"
}
}A 200 or 201 response contains JSON. 202 means asynchronous work was accepted, not completed. 204 has no response body. Error responses use an error object; validation and domain errors can add details, and server-generated errors include a correlation request ID.
Safe mutations
Email creation
Use one stable Idempotency-Key per logical email. It must be 8–128 characters using letters, digits, dot, underscore, colon, or hyphen. The body field idempotency_key is equivalent; if both are sent, they must match.
Updates and deletes
Read the current resource state before workflows that depend on it, then handle 404 and 409 explicitly. For example, only a scheduled email can be rescheduled or cancelled; a worker may advance its state between your read and mutation.
429, and selected 5xx responses with a finite backoff budget. Validation, authentication, permission, ownership, and state conflicts require a code or data change rather than another identical request.Attachments and images
Send files and images by passing base64-encoded attachment objects to POST /emails.
Sendix accepts up to 20 attachments per message, with a 10 MB limit per file and 25 MB total attachment limit. Executable and script-like attachment types are blocked to reduce abuse and mailbox-provider risk.
curl -X POST https://sendix.dev/api/v1/emails \
-H "Authorization: Bearer $SENDIX_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"from": "[email protected]",
"to": ["[email protected]"],
"subject": "Invoice",
"text": "Your invoice is attached.",
"attachments": [
{
"filename": "invoice.pdf",
"contentType": "application/pdf",
"content": "JVBERi0xLjQK..."
},
{
"filename": "receipt.png",
"contentType": "image/png",
"content": "iVBORw0KGgo..."
}
]
}'Spam risk check
Use POST /emails/spam-check before a large rollout or template launch.
The endpoint returns a score, triggered rules, recommendations, and a sendability flag. It does not replace SPF, DKIM, DMARC, clean lists, or gradual warmup; it gives developers a fast preflight signal before submitting real traffic.
curl -X POST https://sendix.dev/api/v1/emails/spam-check \
-H "Authorization: Bearer $SENDIX_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"from": "[email protected]",
"subject": "Your invoice is ready",
"html": "<p>Your invoice is attached.</p>",
"text": "Your invoice is attached."
}'Emails
Outbound transactional mail — single send, batch, schedule, cancel, attachments.
| Method | Path | Scope | Description |
|---|---|---|---|
| POST | /emails | email:send | Send a single transactional email. |
| POST | /emails/spam-check | email:send | Score subject/body risk before sending. |
| POST | /emails/batch | email:send | Send up to 100 messages in one round-trip. |
| GET | /emails | email:read | List sends with status / domain / search filters. |
| GET | /emails/{id} | email:read | Fetch a single send with its full delivery timeline. |
| GET | /emails/{id}/events | email:read | List webhook/event outbox records for one send. |
| GET | /emails/{id}/attempts | email:read | List SMTP delivery attempts for one send. |
| PATCH | /emails/{id} | email:send | Re-schedule a not-yet-sent message. |
| POST | /emails/{id}/cancel | email:send | Cancel a scheduled message before the queue picks it up. |
| GET | /emails/{id}/attachments | email:read | List the attachments staged with a send. |
| GET | /emails/{id}/attachments/{aid} | email:read | Download a signed URL for a single attachment. |
Inbound
Email arriving on configured inboxes, parsed and signed.
| Method | Path | Scope | Description |
|---|---|---|---|
| GET | /emails/receiving | email:read | List received messages with pagination. |
| GET | /emails/receiving/{id} | email:read | Fetch a received message with parsed headers and body. |
| GET | /emails/receiving/{id}/attachments | email:read | List attachments for a received message. |
| GET | /emails/receiving/{id}/attachments/{attachmentId} | email:read | Download a signed URL for one inbound attachment. |
| POST | /emails/receiving | email:send | Controlled inbound ingest for tests and internal integrations. |
| PATCH | /emails/receiving/{id} | email:read | Update the read or starred state of a received message. |
| POST | /emails/receiving/{id}/reply | email:send | Reply to a received message through the outbound pipeline. |
| GET | /emails/receiving/health | email:read | Check inbound receiver and MX readiness. |
| GET | /emails/receiving/forwarding | email:read | List inbound forwarding rules. |
| POST | /emails/receiving/forwarding | domain:manage | Create an inbound forwarding rule. |
| PATCH | /emails/receiving/forwarding/{ruleId} | domain:manage | Update an inbound forwarding rule. |
| DELETE | /emails/receiving/forwarding/{ruleId} | domain:manage | Delete an inbound forwarding rule. |
Domains
Sending domains plus DNS records (SPF / DKIM / DMARC) and verification state.
| Method | Path | Scope | Description |
|---|---|---|---|
| GET | /domains | domain:read | List domains in the workspace. |
| POST | /domains | domain:manage | Register a new sending domain. |
| GET | /domains/{id} | domain:read | Fetch one domain with its current DNS records. |
| PATCH | /domains/{id} | domain:manage | Update sending or receiving settings for a domain. |
| POST | /domains/{id}/verify | domain:manage | Re-run SPF / DKIM / DMARC checks. |
| POST | /domains/{id}/cloudflare/apply | domain:manage | Apply generated DNS records through the connected Cloudflare account. |
| POST | /domains/{id}/domain-connect/cloudflare-url | domain:manage | Create a signed Cloudflare Domain Connect URL; the optional records object selects mail, inbound, or combined setup. |
| POST | /domains/{id}/receiving | domain:manage | Enable or disable receiving after receiver and MX checks pass. |
| DELETE | /domains/{id} | domain:manage + dashboard session + fresh 2FA when enabled | Remove a domain from the workspace. |
Managed customers
Downstream customer and domain lifecycle for SaaS and ecommerce platforms.
| Method | Path | Scope | Description |
|---|---|---|---|
| GET | /managed-tenants | tenant:read | List managed customers and current plan limits. |
| POST | /managed-tenants | tenant:manage | Idempotently create a customer using your external id. |
| GET | /managed-tenants/by-external-id/{externalId} | tenant:read | Resolve a customer using the stable id from your own system. |
| GET | /managed-tenants/{id} | tenant:read | Fetch a customer with its attached domains. |
| PATCH | /managed-tenants/{id} | tenant:manage | Update metadata, provider, name, or pause state. |
| DELETE | /managed-tenants/{id} | tenant:manage | Delete a customer after removing all attached domains. |
| POST | /managed-tenants/{id}/domains | tenant:manage | Register a sending domain for a customer. |
| DELETE | /managed-tenants/{id}/domains/{domainId} | tenant:manage | Remove a customer domain and its Sendix domain resource. |
API keys
Programmatic credentials with per-scope authorisation and optional IP allow-lists.
| Method | Path | Scope | Description |
|---|---|---|---|
| GET | /api-keys | dashboard session | List keys with their scopes and last-used timestamp. |
| POST | /api-keys | dashboard session + fresh 2FA when enabled | Mint a new key (returned in plaintext exactly once). |
| POST | /api-keys/{id}/rotate | dashboard session + fresh 2FA when enabled | Issue a new secret while keeping the same id. |
| DELETE | /api-keys/{id} | dashboard session + fresh 2FA when enabled | Revoke a key immediately. |
Webhooks
HMAC-signed event delivery with automatic retries and replay.
| Method | Path | Scope | Description |
|---|---|---|---|
| GET | /webhook-events | webhook:read | Catalog of every event you can subscribe to. |
| GET | /webhooks | webhook:read | List endpoints registered in the workspace. |
| POST | /webhooks | webhook:manage | Register a new endpoint and event subscription. |
| GET | /webhooks/{id} | webhook:read | Fetch a single endpoint with its secret prefix. |
| PATCH | /webhooks/{id} | webhook:manage | Update url / events / description. |
| DELETE | /webhooks/{id} | webhook:manage | Delete the endpoint. |
| POST | /webhooks/{id}/test | webhook:manage | Queue a signed Sendix event to verify the endpoint. |
| POST | /webhooks/{id}/test/live | webhook:manage + dashboard session + fresh 2FA when enabled | Attempt an immediate live test delivery with fresh dashboard 2FA. |
| POST | /webhooks/{id}/rotate-secret | webhook:manage + dashboard session + fresh 2FA when enabled | Rotate the HMAC signing secret. |
| GET | /webhook-deliveries | webhook:read | List delivery attempts across all endpoints. |
| GET | /webhooks/{id}/deliveries | webhook:read | List delivery attempts for one endpoint. |
| POST | /webhook-deliveries/{deliveryId}/replay | webhook:manage + dashboard session + fresh 2FA when enabled | Replay a failed webhook delivery. |
Templates
HTML templates with versioning, preview, and live rendering.
| Method | Path | Scope | Description |
|---|---|---|---|
| GET | /templates | template:read | List templates and current active version. |
| POST | /templates | template:manage | Create a new template with version 1 active. |
| GET | /templates/{id} | template:read | Fetch a template with the latest source. |
| PATCH | /templates/{id} | template:manage | Create the next active version. |
| DELETE | /templates/{id} | template:manage | Archive (soft-delete) the template. |
| POST | /templates/{id}/publish | template:manage | Activate an existing template version. |
| POST | /templates/{id}/duplicate | template:manage | Fork into a new template with the same source. |
| POST | /templates/{id}/preview | template:manage | Render with preview variables for a preview pane. |
| POST | /templates/render | template:manage | Render arbitrary source without saving. |
| POST | /templates/{id}/test-send | template:manage + email:send | Send a test message from a template. |
| POST | /templates/test-send | email:send + verified account email | Send unsaved template source as a test message. |
| PUT | /templates/{id}/draft | template:manage | Save draft source without publishing it. |
| GET | /templates/{id}/versions | template:read | List the immutable versions of a template. |
| GET | /templates/{id}/versions/{version} | template:read | Fetch one template version. |
| GET | /templates/{id}/stats | template:read | Read delivery and engagement statistics for a template. |
Audience
Contacts, audiences, segments, and subscription state.
| Method | Path | Scope | Description |
|---|---|---|---|
| GET | /audience/lists | audience:read | List audiences in the workspace. |
| POST | /audience/lists | audience:manage | Create a new audience. |
| GET | /audience/lists/{id} | audience:read | Fetch an audience list. |
| PATCH | /audience/lists/{id} | audience:manage | Update an audience list. |
| DELETE | /audience/lists/{id} | audience:manage | Delete an audience list. |
| GET | /audience/contacts | audience:read | List contacts. |
| POST | /audience/contacts | audience:manage | Add or upsert a contact. |
| PATCH | /audience/contacts/{id} | audience:manage | Update a contact. |
| DELETE | /audience/contacts/{id} | audience:manage | Delete a contact. |
| POST | /audience/contacts/import | audience:manage | Import contacts into an audience. |
| POST | /audience/contacts/{id}/send-confirmation | audience:manage + verified sender domain | Send a double opt-in confirmation to one contact. |
| POST | /audience/lists/{id}/send-confirmations | audience:manage + verified sender domain | Send double opt-in confirmations to eligible list contacts. |
| GET | /audience/confirm/{token} | signed confirmation token | Apply consent from a signed double opt-in link. |
| GET | /segments | audience:read | List dynamic segments. |
| POST | /segments | audience:manage | Create a segment from a filter expression. |
| GET | /segments/{id} | audience:read | Fetch a segment. |
| PATCH | /segments/{id} | audience:manage | Update a segment. |
| DELETE | /segments/{id} | audience:manage | Delete a segment. |
| GET | /segments/{id}/contacts | audience:read | List contacts in a segment. |
| POST | /segments/{id}/contacts | audience:manage | Add contacts to a segment. |
| DELETE | /segments/{id}/contacts/{contactId} | audience:manage | Remove one contact from a segment. |
| GET | /topics | audience:read | List subscription topics. |
| POST | /topics | audience:manage | Create a subscription topic. |
| GET | /topics/{id} | audience:read | Fetch a topic. |
| PATCH | /topics/{id} | audience:manage | Update a topic. |
| DELETE | /topics/{id} | audience:manage | Delete a topic. |
| GET | /contacts/{id}/topics | audience:read | List topic subscriptions for a contact. |
| POST | /contacts/{id}/topics | audience:manage | Subscribe a contact to a topic. |
| PATCH | /contacts/{id}/topics | audience:manage | Update contact topic subscriptions. |
| DELETE | /contacts/{id}/topics/{topicId} | audience:manage | Unsubscribe a contact from a topic. |
| GET | /contact-properties | audience:read | List custom contact properties. |
| POST | /contact-properties | audience:manage | Create a custom contact property. |
| GET | /contact-properties/{id} | audience:read | Fetch a custom contact property. |
| PATCH | /contact-properties/{id} | audience:manage | Update a custom contact property. |
| DELETE | /contact-properties/{id} | audience:manage | Delete a custom contact property. |
| GET | /contacts/{id}/properties | audience:read | List custom property values for a contact. |
| PUT | /contacts/{id}/properties/{propertyId} | audience:manage | Set one custom property value for a contact. |
Broadcasts
One-off campaigns to an audience or segment with scheduling and throttling.
| Method | Path | Scope | Description |
|---|---|---|---|
| GET | /broadcasts | email:read | List broadcasts (status + audience + scheduled time). |
| POST | /broadcasts | email:send | Draft a new broadcast. |
| GET | /broadcasts/{id} | email:read | Fetch broadcast detail with composition + stats. |
| PATCH | /broadcasts/{id} | email:send | Edit subject / body / audience / schedule. |
| DELETE | /broadcasts/{id} | email:send | Delete an unsent draft. |
| POST | /broadcasts/{id}/send | email:send | Send immediately or queue at the scheduled time. |
| POST | /broadcasts/{id}/cancel | email:send | Cancel an in-flight or scheduled broadcast. |
| GET | /broadcasts/{id}/recipients | email:read | Page through the per-recipient delivery roster. |
| GET | /broadcasts/summary | email:read | Read aggregate broadcast counts by state. |
| POST | /broadcasts/audience-estimate | email:read | Estimate the eligible recipient count before saving a broadcast. |
| GET | /broadcasts/{id}/stats | email:read | Read delivery and engagement statistics for a broadcast. |
| GET | /broadcasts/{id}/recipient-errors | email:read | List recipient-level failures for a broadcast. |
| POST | /broadcasts/{id}/duplicate | email:send | Create a new draft from an existing broadcast. |
Automations
Manual-run flows with retries, branches, run history, and event ingest.
| Method | Path | Scope | Description |
|---|---|---|---|
| GET | /automations | automation:read | List automations and their enabled state. |
| POST | /automations | automation:manage | Create a new automation definition. |
| GET | /automations/{id} | automation:read | Fetch the definition + most recent runs. |
| PATCH | /automations/{id} | automation:manage | Edit steps / triggers / metadata. |
| DELETE | /automations/{id} | automation:manage | Archive the automation. |
| POST | /automations/{id}/duplicate | automation:manage | Duplicate an automation definition. |
| POST | /automations/{id}/run | automation:run | Trigger an external run with an arbitrary payload. |
| GET | /automations/{id}/runs | automation:read | List automation run history. |
| GET | /automations/{id}/runs/{runId} | automation:read | Fetch one automation run. |
| POST | /automations/{id}/stop | automation:manage | Stop an active automation run. |
| POST | /automations/events | automation:run + verified account email | Trigger eligible automations from a typed event. |
| GET | /automations/_meta | automation:read | Read automation metadata for builders and forms. |
| GET | /automations/summary | automation:read | Read aggregate automation and run counts. |
| POST | /automations/{id}/publish | automation:manage | Validate and publish the current automation draft. |
| POST | /automations/{id}/test | automation:run + verified account email | Run an automation with test input. |
| GET | /automations/{id}/versions | automation:read | List published automation versions. |
| POST | /automations/{id}/versions/{version}/rollback | automation:manage | Restore a previous automation version. |
| GET | /automation-credentials | automation:read | List credential metadata without returning secrets. |
| POST | /automation-credentials | automation:manage | Create an encrypted credential for HTTP steps. |
| PATCH | /automation-credentials/{id} | automation:manage | Update credential metadata and safe request settings. |
| POST | /automation-credentials/{id}/rotate | automation:manage | Replace the encrypted credential secret. |
| POST | /automation-credentials/{id}/test | automation:manage | Test a credential against a safe HTTP target. |
| DELETE | /automation-credentials/{id} | automation:manage | Delete a credential that no automation references. |
Suppressions
Workspace-wide do-not-send list, automatically maintained from bounces and complaints.
| Method | Path | Scope | Description |
|---|---|---|---|
| GET | /suppressions | suppression:read | List entries (paginated, filterable by reason). |
| POST | /suppressions | suppression:manage | Manually add an address. |
| DELETE | /suppressions/{email} | suppression:manage | Remove an address (e.g. after explicit re-opt-in). |
| GET | /unsubscribe/{token} | signed unsubscribe token | Render a signed one-click unsubscribe confirmation. |
| POST | /unsubscribe/{token} | signed unsubscribe token | Apply a signed one-click unsubscribe. |
Stats
Aggregate, daily, and time-series reporting on the workspace.
| Method | Path | Scope | Description |
|---|---|---|---|
| GET | /stats/overview | analytics:read | Top-line totals over the last N days. |
| GET | /stats/daily?days=30 | analytics:read | Daily breakdown with zero-fill for gaps. |
| GET | /stats/timeseries | analytics:read | Per-event time-series, suitable for charts. |
| GET | /stats/top | analytics:read | Top recipient ISPs and status mix. |
| GET | /stats/deliverability?days=30 | analytics:read | Deliverability scorecard, provider health, domain authentication, and actions. |
Logs
Structured per-recipient timeline for every message the workspace has sent.
| Method | Path | Scope | Description |
|---|---|---|---|
| GET | /logs | logs:read | Query logs with search / time / status filters. |
| GET | /logs/{id} | logs:read | Fetch one log entry with the full event tape. |
| GET | /logs/_counts | logs:read | Fetch grouped log counts for dashboard filters. |
Sending nodes
Read the available Sendix-owned delivery nodes visible to the workspace.
| Method | Path | Scope | Description |
|---|---|---|---|
| GET | /sending-nodes | authenticated | List authenticated delivery nodes available for domain setup. |
Events
Public event ingest for product timelines, analytics, and custom workflows.
| Method | Path | Scope | Description |
|---|---|---|---|
| POST | /events | automation:manage | Create a typed platform event. |
| GET | /events | automation:read | List recent platform events. |
| GET | /events/{id} | automation:read | Fetch one platform event. |
| PATCH | /events/{id} | automation:manage | Update a platform event. |
| DELETE | /events/{id} | automation:manage | Delete a platform event. |
| POST | /events/{id}/send | automation:run | Send a platform event into automation/webhook flows. |

