Reference
API Reference
SendBolt exposes a single versioned REST API at https://api.sendbolt.io/api/v1. Every endpoint accepts and returns JSON. The full machine-readable schema is published at /api/v1/openapi.json — paste that URL into Postman, Stoplight, or your codegen tool to produce a typed client. The interactive Swagger UI at /api/v1/docs is also embedded at the bottom of this page so you can try any call without leaving the docs.
Base URL
https://api.sendbolt.io/api/v1
All endpoints are HTTPS-only. Plain HTTP requests receive a 301 redirect to the HTTPS equivalent.
Authentication
Pass your API key as a Bearer token in the Authorization header. Keys are minted at Settings → API keys and are prefixed by mode:
sb_live_…— production. Real sends, real reputation impact, counts against monthly quota.sb_test_…— sandbox (W213). Sends are accepted, queued, and observable in the dashboard, then dropped before they leave the MTA. No reputation impact, no quota burn. Use these for CI and integration tests.
Full scope reference + key-rotation playbook: API keys & auth.
curl "https://api.sendbolt.io/api/v1/whoami" \
-H "Authorization: Bearer sb_live_..."Response envelope
Every response — success or error — uses the same JSON envelope:
// Success
{
"ok": true,
"data": { ... }
}
// Error
{
"ok": false,
"error": "invalid_scope",
"message": "The API key lacks the campaigns:write scope"
}Errors
Status codes follow standard REST semantics. error is a stable machine-readable slug; message is a human-readable hint that may change between releases.
| Status | error slug | Meaning |
|---|---|---|
| 200 | — | Success |
| 201 | — | Resource created |
| 400 | bad_request | Malformed JSON or unexpected field |
| 401 | unauthenticated | Missing / unparseable API key |
| 403 | invalid_scope / forbidden | Key valid but lacks the scope for this endpoint |
| 404 | not_found | Resource doesn't exist (or belongs to another tenant) |
| 409 | conflict | Idempotency clash or unique-constraint violation |
| 412 | no_verified_domain | W174 gate — tenant has no verified sending domain; verify SPF + DKIM + DMARC first |
| 422 | validation_error | A field is wrong; message names the field |
| 429 | rate_limited | Too many requests; honour Retry-After header |
| 402 | quota_exceeded | Monthly send cap hit; upgrade plan or wait for next billing cycle |
| 500 | internal | Server-side failure; safe to retry with exponential backoff |
Pagination
List endpoints use cursor-based pagination. Pass ?after=<cursor>&limit=50 (max 200). The response includes a next_cursor field — when it is null you have reached the last page.
{
"ok": true,
"data": [ ... ],
"next_cursor": "cur_01J...",
"total": 1234
}Rate limits
Default per-tenant limits. Apply per API key — multiple keys for one tenant get independent buckets.
| Endpoint class | Limit (default) |
|---|---|
POST /transactional/send | 600 req/min |
| Other write endpoints (campaigns, contacts, templates, ...) | 60 req/min |
| Read endpoints (lists, events, suppressions, ...) | 60 req/min |
| Bulk-import endpoints | 20 req/min (separate higher per-row cap inside the call) |
Every response includes X-RateLimit-Limit, X-RateLimit-Remaining, and X-RateLimit-Reset. On 429 the response also includes Retry-After in seconds — respect it. Higher caps available on Pro / Scale tiers; contact support.
Common endpoints
Send a transactional email
Single-recipient send. Blocked by the W174 verified-domain gate until at least one domain on the tenant has SPF + DKIM + DMARC green.
curl -X POST "$SENDBOLT_API_URL/api/v1/transactional/send" \
-H "Authorization: Bearer $SENDBOLT_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"to": "alice@example.com",
"from_email": "no-reply@acme.com",
"subject": "Confirm your Acme signup",
"body_text": "Hi Alice, confirm at https://acme.com/verify?t=abc123",
"body_html": "<p>Hi Alice,</p><p><a href=\"https://acme.com/verify?t=abc123\">Confirm</a></p>",
"bounce_risk_check_enabled": true
}'List contacts
curl "$SENDBOLT_API_URL/api/v1/contacts?limit=50" \
-H "Authorization: Bearer $SENDBOLT_API_KEY"Create a segment
Segments are query-defined audiences that re-evaluate at send-time — see affiliate tracking for the grammar.
curl -X POST "$SENDBOLT_API_URL/api/v1/segments" \
-H "Authorization: Bearer $SENDBOLT_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "Q4 affiliate cohort",
"definition": {
"op": "OR",
"rules": [
{ "type": "field", "field": "custom_fields.aff", "operator": "eq", "value": "42" },
{ "type": "field", "field": "custom_fields.SID", "operator": "contains", "value": "campaign-q4" }
]
}
}'Endpoint groups
| Group | Prefix | What it does |
|---|---|---|
| Transactional | /transactional/send | Single-recipient email — templates or raw HTML |
| Campaigns | /campaigns | Bulk sends; auto-attaches RFC 8058 List-Unsubscribe (W198) |
| Contacts | /contacts | Contact CRUD + bulk import (CSV / JSON) |
| Lists | /lists | Static contact lists + membership |
| Segments | /segments | Query-defined audiences; preview row count without sending |
| Templates | /templates | Reusable HTML / text templates with Liquid variable slots |
| Suppressions | /suppressions | Read / write the per-tenant suppression list |
| Events | /events | Open, click, bounce, complaint event feed |
| Domains | /domains | Sending-domain verification + DKIM key status; gates W174 |
| Inbound | /mail/mailboxes, /mail/messages | Workspace mailboxes + inbound message API |
| Reputation | /reputation | Per-domain trust score + deliverability metrics |
| Identity | /whoami | Verify auth + inspect key scopes / tenant ID |
SDKs (W220)
Both SDKs are generated from the same /api/v1/openapi.json spec, so every endpoint above has a typed method in both languages on the day it ships.
- TypeScript —
@sendbolt/sdk-ts(sdk/typescript). Built onopenapi-fetch; the schema export (@sendbolt/sdk-ts/schema) gives you path-level IntelliSense in your editor without a runtime cost. - Go —
github.com/sendbolt/sendbolt/sdk/go/sendbolt(sdk/go). Generated byoapi-codegen v2. UseNewClientWithResponsesfor typed request/response wrappers, orNewClientfor raw*http.Responseaccess.
Want to scaffold a client in a third language? Point your codegen tool of choice at /api/v1/openapi.json — contributions back to the repo welcome.
Interactive explorer
The widget below is Swagger UI pointing at the live spec. Click Authorize, paste your API key, and try any endpoint inline.
Loading interactive API explorer…