Skip to main content
Every error the Samsa API returns — for any endpoint, at any status — uses one consistent JSON envelope. Parse the machine-readable code, not the human message (messages may change; codes are stable).

The error envelope

{
  "error": {
    "type": "authentication_error",
    "code": "invalid_api_key",
    "message": "The provided API key is invalid, expired, or revoked.",
    "request_id": "req_8f14e45fceea167a"
  }
}
FieldDescription
error.typeBroad category, e.g. authentication_error, credit_error, rate_limit_error.
error.codeStable, specific code you branch on (the table below).
error.messageHuman-readable explanation. For display and logs — do not parse it.
error.request_idCorrelation id for this request, also returned as the X-Request-ID response header. Quote it when contacting support.
error.paramPresent on validation and scope errors — names the offending field or "scope".
Successful responses never contain an error object. Branch on the HTTP status first, then on error.code.

Error codes

HTTPcodetypeMeaning
401invalid_api_keyauthentication_errorMissing, malformed, unknown, expired, or revoked key.
403missing_scopepermission_errorValid key lacks the endpoint’s scope.
402insufficient_creditscredit_errorOrganization credit pool is below the action cost.
402subscription_inactivecredit_errorNo usable organization subscription.
404not_foundinvalid_request_errorUnknown id, or a resource owned by another organization.
422validation_errorinvalid_request_errorRequest body or parameters failed validation.
429rate_limitedrate_limit_errorPer-key request-rate window exceeded.
429too_many_active_jobsrate_limit_errorOrganization’s concurrent-job cap reached.
500internal_errorapi_errorUnexpected server error.

invalid_api_key

HTTP 401. The Authorization header is missing or malformed, or the key is unknown, expired, or revoked — or the key creator is no longer a member of the organization. Expired and unknown keys are intentionally indistinguishable.
{
  "error": {
    "type": "authentication_error",
    "code": "invalid_api_key",
    "message": "The provided API key is invalid, expired, or revoked.",
    "request_id": "req_8f14e45fceea167a"
  }
}
How to handle. Check the Authorization: Bearer samsa_sk_… header. If the key was revoked or expired, create a new one. Do not retry — the outcome will not change.

missing_scope

HTTP 403. The key is valid but lacks the scope the endpoint requires. param is "scope" and the message names the missing scope.
{
  "error": {
    "type": "permission_error",
    "code": "missing_scope",
    "message": "The API key is missing the required scope: images.generate.",
    "request_id": "req_1c9a3b7d2e5f4a80",
    "param": "scope"
  }
}
How to handle. An admin edits the key’s scopes (or issues a new key) to grant the named scope. Do not retry without changing the key.

insufficient_credits

HTTP 402. The organization’s spendable credit pool (subscription plus valid top-ups) is below the action’s cost. See Pricing.
{
  "error": {
    "type": "credit_error",
    "code": "insufficient_credits",
    "message": "Insufficient credits available.",
    "request_id": "req_2d5f4a801c9a3b7d"
  }
}
How to handle. Top up or upgrade the organization’s plan in the app, then retry. Nothing was charged and no job was created.

subscription_inactive

HTTP 402. The organization has no usable subscription (none active, in grace, or holding spendable top-ups). Distinct from insufficient_credits, where a subscription exists but the pool is too low.
{
  "error": {
    "type": "credit_error",
    "code": "subscription_inactive",
    "message": "No active subscription for this organization.",
    "request_id": "req_4a801c9a3b7d2d5f"
  }
}
How to handle. Reactivate billing for the organization in the app, then retry.

not_found

HTTP 404. The id is unknown, or it belongs to another organization. The two cases are indistinguishable by design, so existence is never disclosed across organizations.
{
  "error": {
    "type": "invalid_request_error",
    "code": "not_found",
    "message": "The requested resource was not found.",
    "request_id": "req_7d2d5f4a801c9a3b"
  }
}
How to handle. Verify the id, and that the key’s organization owns the resource. Do not retry.

validation_error

HTTP 422. The request body or a parameter failed validation. param names the offending field; message explains the constraint.
{
  "error": {
    "type": "invalid_request_error",
    "code": "validation_error",
    "message": "aspect_ratio must be one of: 1:1, 4:3, 4:5, 16:9, 21:9, 9:16",
    "request_id": "req_3b7d2d5f4a801c9a",
    "param": "aspect_ratio"
  }
}
How to handle. Fix the request per message and param, then resubmit. This is a client error — retrying the same request will fail identically.

rate_limited

HTTP 429. The key exceeded its per-key request-rate window. The response carries Retry-After and X-RateLimit-* headers. See Rate limits.
{
  "error": {
    "type": "rate_limit_error",
    "code": "rate_limited",
    "message": "API rate limit exceeded. Slow down and retry after the rate-limit window resets.",
    "request_id": "req_5f4a801c9a3b7d2d"
  }
}
How to handle. Back off and retry after the Retry-After interval. Use exponential backoff for repeated 429s.

too_many_active_jobs

HTTP 429. The organization has reached its cap on concurrent in-flight jobs. The message includes the current count and the limit, and a Retry-After header is set.
{
  "error": {
    "type": "rate_limit_error",
    "code": "too_many_active_jobs",
    "message": "Too many active jobs for this organization (5/5). Wait for in-flight jobs to finish before submitting more.",
    "request_id": "req_801c9a3b7d2d5f4a"
  }
}
How to handle. Wait for in-flight jobs to reach a terminal status (poll their GET endpoint or use a webhook) before submitting more, then retry after Retry-After.

internal_error

HTTP 500. An unexpected error on Samsa’s side. The response never leaks internal details — the request_id is your handle for support.
{
  "error": {
    "type": "api_error",
    "code": "internal_error",
    "message": "An internal error occurred. Contact support with the request_id.",
    "request_id": "req_9a3b7d2d5f4a801c"
  }
}
How to handle. Retry with backoff — 500s are often transient. If it persists, contact support@samsa.ai with the request_id.

Using request_id for support

Every error (and every success) carries a request_id, also returned as the X-Request-ID response header. It ties your client-side error, the response header, and Samsa’s server logs to one request. Log it, and quote it when you contact support@samsa.ai — it is the fastest way for us to find exactly what happened.
New error codes may be added over time (for example, additive per-endpoint codes). Treat an unrecognized code the same as its HTTP status class, and always branch on code rather than matching message text.