Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.sendmux.ai/llms.txt

Use this file to discover all available pages before exploring further.

The Sendmux API uses standard HTTP status codes and returns a consistent error envelope so you can handle failures programmatically.

Error response format

{
  "ok": false,
  "error": {
    "code": "invalid_parameter",
    "message": "A human-readable description of the error.",
    "param": "from_date",
    "doc_url": "https://docs.sendmux.ai/api-reference/errors#invalid_parameter",
    "retryable": false
  },
  "meta": {
    "request_id": "req_clxxxxxxxxxxxxxxxxxxxxxxxxx"
  }
}
FieldDescription
codeStable machine-readable code from the table below. Branch your client logic on this, not on the message text.
messageHuman-readable description suitable for logs or surfacing to internal tools. Wording may change without notice.
paramOnly present when the error is tied to a specific request field — typically the field that failed validation.
doc_urlAnchor link into this page. Useful for surfacing inline help.
retryabletrue when the same request can succeed on a later attempt without changes. See Retryable + Retry-After.
errorsOnly present on accumulated validation failures. See Validation errors with multiple issues.
Every response also carries an X-Request-Id HTTP header that matches meta.request_id verbatim. Always include request_id when contacting support.

Retryable + Retry-After

The retryable field tells you whether retrying the same request is likely to succeed. Defaults follow this policy:
HTTP statusDefault retryableWhy
429trueTransient — back off until the rate-limit window resets.
5xxtrueTransient — backend issue or downstream component briefly unavailable.
4xx otherfalseCaller-side problem — fix the request before retrying.
When retryable is true for a 429 or 503, the response also carries a Retry-After HTTP header with the recommended wait in seconds. Honour that value rather than retrying immediately.
HTTP/1.1 429 Too Many Requests
Retry-After: 30
Content-Type: application/json
A handful of codes override the default policy explicitly — most notably idempotency_conflict is false (the same key + same body needs your client to either wait for the in-flight request to finish or use a fresh key).

Validation errors with multiple issues

When a request body fails Zod schema validation on multiple fields, the error envelope carries an errors array so you can surface every issue in a single round-trip.
{
  "ok": false,
  "error": {
    "code": "invalid_parameter",
    "message": "Invalid request parameters.",
    "param": "filter_rules.0.action",
    "doc_url": "https://docs.sendmux.ai/api-reference/errors#invalid_parameter",
    "retryable": false,
    "errors": [
      { "field": "filter_rules.0.action", "code": "invalid_enum_value", "message": "Expected 'allow' | 'deny'." },
      { "field": "filter_rules.2.pattern", "code": "too_small", "message": "String must contain at least 1 character(s)." }
    ]
  },
  "meta": { "request_id": "req_clxxxxxxxxxxxxxxxxxxxxxxxxx" }
}
The param at the top of the error matches the first issue’s field for backwards compatibility. The full list lives in errors[]. Status is 400 for syntactic problems (invalid_parameter) and 422 for semantic violations (validation_error).

Error codes

authentication_required

HTTP 401 — The request has no Authorization header or the API key is invalid, expired, or revoked.
# Fix: include a valid API key
curl https://app.sendmux.ai/api/v1/providers \
  -H "Authorization: Bearer smx_root_your_key_here"

insufficient_permissions

HTTP 403 — The API key is valid but lacks the required permission for this endpoint. Check the permission table to see which permission each endpoint requires.

invalid_parameter

HTTP 400 — A query parameter has an invalid format or value. The param field identifies which parameter is at fault.

missing_parameter

HTTP 400 — A required query parameter is missing from the request.

not_found

HTTP 404 — The requested resource does not exist, or it belongs to a different team than the one associated with your API key.

conflict

HTTP 409 — The request can’t be applied because of the resource’s current state. Examples: deleting a domain while mailboxes still live on it, creating a mailbox whose email address is already in use, or sending a PATCH / PUT with an If-Match header that doesn’t match the current ETag (optimistic concurrency conflict). Re-fetch the resource and reconcile before retrying.

idempotency_conflict

HTTP 409 — Returned when an Idempotency-Key request header is reused either (a) while the original request is still being processed (transient — wait briefly and retry to receive the completed response), or (b) with a request body whose fingerprint differs from the original (permanent — fix the client to use a fresh key for the new request). See the Idempotency guide.

validation_error

HTTP 422 — A request body parsed cleanly as JSON but fails a semantic rule. Common cases include shrinking a mailbox quota below its current usage, referencing a provider or delivery group from a different team, or submitting more than 1,000 filter rules in a single request. The param field identifies the first offending field; the errors array enumerates every issue.

rate_limit_exceeded

HTTP 429 — You have exceeded the rate limit of 600 requests per minute. The response carries a Retry-After HTTP header with the recommended wait in seconds; back off until then before retrying. retryable is true.

payload_too_large

HTTP 413 — The request body exceeds the server-side size limit. Trim the body or split into smaller requests.

service_unavailable

HTTP 503 — A downstream component needed to serve this request is temporarily unavailable. The response may carry a Retry-After header. Requests are safe to retry with exponential backoff (retryable is true). If this persists for more than a few minutes, contact support with the request_id from the response.

internal_error

HTTP 500 — An unexpected server error occurred. retryable is true because the failure is server-side, but if it persists, contact support with the request_id from the response.