HTTP-level errors (request failed)
Returned by the API router itself. Always a structured JSON body:Run-level errors (run failed)
A run that got past validation but failed mid-flight hasstatus: "failed" with machine-readable error_code + human error_message. Your polling code should branch on status first, then inspect these.
Full error code reference
missing_api_key · 401
missing_api_key · 401
Authorization: Bearer ... header on the request.Fix: attach the header. See authentication.invalid_api_key · 401
invalid_api_key · 401
hck_live_<12>.<32> with a single dot. If the secret itself looks wrong, mint a new key in Settings → API Keys.revoked_api_key · 401
revoked_api_key · 401
insufficient_scope · 403
insufficient_scope · 403
runs:write, runs:read) cover almost everything. You only need flows:read explicitly if you’re listing or fetching saved flows.monthly_cap_exceeded · 402
monthly_cap_exceeded · 402
insufficient_credits · 402
insufficient_credits · 402
Idempotency-Key. Existing reservations on the failed run are released automatically.flow_not_found · 404
flow_not_found · 404
flow_id you passed doesn’t exist or isn’t accessible to the key’s owner.Fix: verify with GET /flows. Flows in another user’s account (unless public) aren’t visible.run_not_found · 404
run_not_found · 404
run_not_cancellable · 404
run_not_cancellable · 404
completed, failed, or cancelled.Fix: nothing to do — the run is already in a terminal state.missing_flow · 400
missing_flow · 400
POST /runs body has neither flow_id nor flow_schema.Fix: supply one. See runs.conflicting_flow · 400
conflicting_flow · 400
flow_id and flow_schema. They’re mutually exclusive.Fix: pick one.invalid_flow_schema · 400
invalid_flow_schema · 400
flow_schema failed structural validation — missing nodes, bad node types, malformed edges, cycles, etc.Fix: the response body includes Zod error details. The same validator runs in the visual editor, so any flow that loads in the UI will accept here.invalid_input_step · 400
invalid_input_step · 400
inputs.prompts[N] or inputs.media[N] references a step index that doesn’t exist in the flow (or isn’t a non-negative integer).Fix: call GET /flows/:id and use the required_inputs[].step_order values it returns.input_type_mismatch · 400
input_type_mismatch · 400
media_input step.Fix: send prompts only to text_input / text_editor steps and media only to media_input steps. GET /flows/:id returns the correct mapping in required_inputs.invalid_input_value · 400
invalid_input_value · 400
media entry is malformed — missing url, or type isn’t one of image / video / audio.Fix: each media entry must be { "url": "https://…", "type": "image" | "video" | "audio" }.media_type_not_accepted · 400
media_type_not_accepted · 400
inputs.media[N].type doesn’t match what the step accepts. For example, sending "image" to a step toggled to accept only video.Fix: read required_inputs[].accepted_media_types from GET /flows/:id and send a matching type.unknown_node_type · run failed
unknown_node_type · run failed
flow_schema. Check the node support matrix — every type the visual editor produces is supported.worker_error · run failed
worker_error · run failed
Idempotency-Key; credits spent up to the failure are already released.render_failed · run failed
render_failed · run failed
Retry decision tree
Is it a 4xx that you control?
Is it a 500?
Idempotency-Key each time so you don’t duplicate runs.Is the run stuck running for > 10 minutes?
POST /runs/:id/cancel, then retry with a new key.Did the run fail with worker_error or render_failed?
Idempotency-Key. The failed run’s reservations are already released.Catching errors with the SDK
Both SDKs raise typed errors you can branch on bycode or status:
Idempotency + retries
Always resend with the sameidempotency_key on network errors. The SDKs do not auto-retry today, so wrap your own loop:
(user_id, Idempotency-Key), so the second call returns the already-created run instead of making a duplicate.
Contact + escalation
Run into an error that isn’t covered here? Open a support ticket from the app, or email[email protected] with:
- The run ID
- The full response body of
GET /runs/:id - A short description of what you expected