Skip to main content

Envelope

{
  "error": {
    "code":    "insufficient_credits",
    "message": "Not enough credits to render, need 10, have 4.",
    "needed":  10,
    "have":    4
  }
}
code is stable and safe to switch on. message is for humans and may change. Extra structured fields are namespaced per error code.

Error codes

CodeHTTPMeaning
unauthenticated401Missing or invalid Authorization header.
rate_limited429Per-account rate cap hit. Honor Retry-After header AND retry_after_ms field.
invalid_args400Body or query failed validation.
workflow_not_found404No workflow with that id, or not owned by this user.
clip_not_found404Clip id doesn’t exist in the workflow graph.
track_not_found404Track id not derivable from the workflow’s edges.
job_not_found404Render job id doesn’t exist.
insufficient_credits402Reserve would go below zero. Includes needed, have.
monthly_cost_cap402Per-user upstream USD budget exceeded for the month.
workflow_too_large413Workflow JSON exceeds 5 MB ceiling.
ledger_read500Unrecoverable read error on the ledger; retryable.
upstream502An underlying generation provider returned a non-200.
timeout504Upstream call exceeded the per-route deadline.

Handling

const res = await fetch(url, { method: 'POST', headers, body });
if (!res.ok) {
  const { error } = await res.json();
  if (error.code === 'insufficient_credits') {
    // surface upgrade CTA with error.needed / error.have
  } else {
    // generic error surface, use error.message
  }
}