Errors
Errors from https://api.koltrix.com/api/v2 are JSON with an error string:
{ "error": "missing permission: send" }The error text is written for a person and may change wording. Decide what to
do from the HTTP status, and for 429 from the code field (see below).
Successful responses use 200, 201 (created), 202 (accepted for sending)
and 204 (deleted, empty body).
Should I retry?
| Status | Retry? |
|---|---|
400, 401, 403, 404 | No. Fix the request, key or data first. |
409 | Yes, after a short wait, with the same Idempotency-Key. |
429 without code | Yes, after Retry-After seconds. |
429 with "code": "quota_exceeded" | Not until resets_at. Tell a person. |
500 | Yes, with backoff. For POST /api/v2/emails, retry with the same Idempotency-Key and nothing is sent twice. |
503 | Yes, with the same Idempotency-Key. |
A good default: retry 409, 429 (rate limit), 500 and 503 with
exponential backoff starting at one second, give up after a few minutes, and
log everything else for a person to look at.
400 Bad Request
The request can't be processed as sent.
error | Endpoint | Fix |
|---|---|---|
invalid body | Any with a body | Send valid JSON with Content-Type: application/json, and check field types: to, cc and bcc are arrays. |
from, to, subject are required | POST /emails | Include all three, non-empty. |
from address is not a valid email | POST /emails | from must contain an address, like [email protected] or Acme <[email protected]>. |
subject and body_html required | POST /lists/:id/broadcast | Include both. |
from_address required (and list has none configured) | POST /lists/:id/broadcast | Pass from_address, or set one on the list. |
csv body required | POST /lists/:id/subscribers/import | Send {"csv": "…"} with the file's contents. |
name is required | POST /lists, POST /sequences | Include a non-empty name. |
subject is required | POST /sequences/:id/steps | Include a non-empty subject. |
invalid email: … | POST /lists/:id/subscribers | The email isn't a valid address. |
401 Unauthorized
The API key is missing or not accepted. See Authentication.
error | Fix |
|---|---|
missing Bearer token | Send Authorization: Bearer kx_…. |
invalid api key format | The token must start with kx_. |
invalid or revoked api key | The key doesn't exist or was revoked. Create a new one. |
403 Forbidden
The key is valid but may not do this.
error | Fix |
|---|---|
missing permission: send (or read, newsletter) | Use a key with that scope. Which scope each endpoint needs. |
from address '…' is not registered for this account. The domain is verified — add this exact address in Dashboard → Domains. | Add the address under Settings → Domains & addresses → your domain → Add address. |
from address '…' is not registered for this account. Add and verify the domain in Dashboard → Domains first, then add the mailbox. | Verify the domain first, then add the address. |
404 Not Found
error | Meaning |
|---|---|
message not found | No message with this id in this workspace. Straight after sending it can also mean the message is still queued; poll again in a second. |
list not found | No list with this id in this workspace. |
subscriber not found | No subscriber with this id. |
A path that doesn't exist at all returns 404 too.
409 Conflict
a request with this Idempotency-Key is still in progress: a retry arrived
while the first request with the same key was still running. Wait a moment and
retry with the same key; you'll get the first request's response. See
Retrying safely.
429 Too Many Requests
Two different things answer 429. Tell them apart by the code field.
Rate limit, no code:
{ "error": "rate limit exceeded — 60 requests per minute per API key" }Wait for the number of seconds in the Retry-After header, then continue.
Send quota, "code": "quota_exceeded":
{
"code": "quota_exceeded",
"error": "You've hit today's API sending limit. It resets at midnight UTC, or upgrade to send more now.",
"kind": "api_sends",
"limit": 200,
"used": 200,
"window": "day",
"resets_at": "2026-10-03T00:00:00Z",
"upgrade_url": "https://app.koltrix.com/settings/billing"
}Retrying won't help until resets_at. Surface it to a person. Details in
Limits and quotas.
500 Internal Server Error
Something failed on Koltrix's side. The error text describes it. Retry with
backoff; if it keeps happening, email [email protected] with the time and the
endpoint.
POST /api/v2/emails releases its Idempotency-Key when it fails before the
message is queued, so retrying with the same key is safe and sends at most one
message.
503 Service Unavailable
idempotency store unavailable, please retry: Koltrix couldn't check the
Idempotency-Key, so it sent nothing rather than risk sending twice. Retry with
the same key.
SMTP relay
The SMTP relay answers with SMTP reply codes, not HTTP statuses. They are listed in SMTP relay → Reply codes.