Skip to main content
An EigenPal API request and the run it describes have separate outcomes. HTTP status describes the API request. execution.status describes the run. A successful GET /api/v1/runs/{id} returns HTTP 200 even when that run failed. A workflow rejection code such as 422 is in error.statusCode, not the HTTP response status.

API request errors

A non-2xx response means the API request could not be completed. Its body uses ApiErrorEnvelope, distinct from a run’s error object:
The example illustrates a validation error. Actual messages and fields depend on the request. Use issues[].code for programmatic decisions and issues[].field to locate invalid input. Messages are explanatory text, not stable identifiers. Optional hint and docsUrl fields provide more help. Keep requestId for support and log correlation. This lists common API errors; each endpoint’s reference documents its supported responses. Business status codes configured in a workflow are a separate set. A network error or lost response does not prove a run was never created. If a run ID is known, inspect that run before submitting it again. Do not assume run creation is idempotent or that repeated POST requests cannot duplicate work.

Accepted runs and HTTP success responses

For POST /api/v1/runs and POST /api/v1/runs/{id}/rerun: GET /api/v1/runs/{id} returns 200 when it successfully retrieves a visible run, regardless of processing outcome. A 404 means the run is missing or inaccessible. finished: true includes completed, failed, cancelled, and rejected. Only execution.status: "completed" indicates successful execution. waiting is non-terminal and can represent a pause for human review. A successful execution does not itself prove the extracted business values are correct. execution.schemaValid is a separate schema verdict; null means no verdict was recorded.

Structured run errors

A failed run can be retrieved with HTTP 200 and this outcome (other run fields omitted):
  • code: machine-readable processing failure identifier.
  • message: human-readable explanation. Do not parse it to identify failure types.
  • statusCode: optional numeric business code authored in control.fail. It is not the status of the HTTP request and is absent for untyped failures.
  • step: optional name of the control.fail step that rejected the run.
  • retryable: another attempt might succeed. This does not schedule a retry.
The same error shape is used in run lists, run detail, and synchronous terminal start/rerun responses. No expand is needed to obtain it. error is absent while the run is in flight and null on terminal runs with no error recorded. For phase, category, and provider diagnostics, request ?expand=debug and inspect debug.observability.failure. Operator messages and raw diagnostics are not part of the public error object. Failed runs in Studio show the copyable error payload in the Output section; run exports preserve it too.

Processing failure codes

This is a reference of common run-level codes, not a closed enum. New and specialized codes can be added. Handle unfamiliar codes with a generic failure path and retain the run ID. Individual step attempts may have more specific provider or HTTP failure codes; those are distinct from the run-level code.

Workflow-specific outcome documentation

Select a workflow and version in Developers > Connect to see every statically declared Fail outcome, including its business code, declaring step, branch conditions, and message template. The response selector includes each rejection, standard processing failures (including input, output, model, and phase failures), and cancellation alongside successful responses. Each documented outcome has a response example. HTTP request errors have separate status codes, schemas, and examples. Messages and retryability in standard examples are illustrative; inspect the actual response. The scoped OpenAPI download and Swagger preview include the same outcomes under HTTP 200, with named rejection schemas and selectable response examples. The x-eigenpal-workflow-failures operation extension carries the inventory for tools. Changing the selected workflow version updates its declared outcomes. Resolvable inline and waited child-workflow rejections are included. Dynamic, unavailable, recursive targets, or inventories exceeding documentation limits are explicitly marked as unresolved. Detached child-run outcomes belong to the child’s own documentation. Processing codes remain open to input, provider, runtime, output, and system failures; always implement a generic failure path.

Business rejections with control.fail

Use Fail to reject an otherwise processable document:
The condition is optional. True stops the workflow; false skips this step. Without a condition it always stops when reached. Codes can be integers from 400 through 599 and default to 422. Their business meaning is defined by the workflow author. Even a configured 500 is a deliberate workflow rejection, not proof of an API server error and not a reason to replay it automatically. A control.fail outcome has execution.status: "failed" and error.code: "workflow_rejected"; it does not set the execution status to rejected. The latter is used for runs refused before processing, for example by an email policy.

Retries and reruns

In Studio, click the workflow name to open Workflow settings > Retries. This sets the default for eligible steps. A step’s Inherit workflow default option shows the effective default and provides a Workflow retry settings button. Step overrides take precedence. There are separate retry mechanisms:
  • SDK HTTP retries: retry API transport failures under the SDK’s policy. A returned run with execution.status: "failed" does not throw an HTTP error or trigger SDK request retries.
  • File retrieval: temporary source failures get up to two additional fetch attempts. Permanent reference, access, and configuration errors do not. Exhaustion fails the run; retryable: true does not create another run.
  • Durable step retries: opt in at workflow or step level. Current support covers Website Reader and HTTP GET/HEAD, with a three-total-attempt worker ceiling and a five-minute elapsed budget. Unsafe writes, email, file outputs, and workflow invocations are not automatically replayed this way. AI providers can have separate request retries. Concurrent parallel branches have additional replay restrictions.
  • Reruns: create a new run using the source input. They use the latest automation version unless version=original is requested. Consider external side effects before replaying an entire workflow.
  • Webhook retries: retry notification delivery independently of processing. A failed delivery does not make a successful run fail. See webhook delivery and retries.

Migration from string errors and legacy endpoints

The unified Runs API now returns error as an object instead of a string. Use error.message for display, error.code for classification, and error.statusCode for a workflow’s numeric business rejection code. Regenerate or update API clients for the new schema. Historical failures recover the business code and step when the stored failure record retains the typed envelope. A plain historical message alone cannot reconstruct a lost code and is returned as unknown_error without statusCode. The legacy POST /api/v1/workflows/{id}/run compatibility endpoint retains its string error and executionId response shape and returns 201 for accepted runs, including when waiting. Migrate to POST /api/v1/runs and GET /api/v1/runs/{id} for the structured contract described above.