Errors

Work out what went wrong and what to do about it: the error body, the status codes the API returns, and how to handle each in the SDK and over MCP.

Every failed request returns a JSON body with an error field and an HTTP status code:

{ "error": "run already in a terminal state" }

The status code tells you the class of failure; the error string is a short, human-readable reason.

Success codes

curl -sS -o /dev/null -w "%{http_code}\n" -X POST "$DURATON_URL/events" \
  -H "Authorization: Bearer $DURATON_API_KEY" \
  -d '{"name":"ticket.created","app":"support-app","data":{"ticketId":"T-421"}}'
# 202
StatusReturned by
200 OKEvery read, the control writes (cancel, pause, resume, replay, retry-from-step, fork, bulk-replay), an approval decision, a PATCH on a webhook endpoint/source, and POST /webhook-source-deliveries/{id}/replay (returns the replay outcome).
201 CreatedPOST /runs/{id}/scores, POST /datasets, POST /datasets/{id}/items, POST /datasets/{id}/eval, POST /webhook-endpoints, POST /webhook-sources.
202 AcceptedPOST /events and POST /webhooks/{token} - the event is recorded; the runs it starts are asynchronous.
204 No ContentDELETE /webhook-endpoints/{id}, DELETE /webhook-sources/{id}, POST /webhook-deliveries/{id}/redeliver.

Status codes

StatusMeaning
400 Bad RequestThe request body is malformed, or a field is invalid - an event names a workflow that isn't registered, an event carries an unsupported character, an approval decision isn't approved/denied, a score is malformed, a dataset has no items to evaluate, or a GET /webhook-source-deliveries?status= value is outside the accepted set.
401 UnauthorizedThe API key is missing or unknown.
403 ForbiddenA read-only (public) key attempted a write, or the project is suspended after its workspace reached the plan limit.
404 Not FoundThe addressed resource - run, step, event, approval, dataset, dataset item, eval run, or webhook source/endpoint/delivery - does not exist.
409 ConflictThe request conflicts with current state (see below).
501 Not ImplementedThe requested capability isn't configured for this project (for example, failure explanations when no model is wired up).
502 Bad GatewayThe status reserved for a runner-not-registered condition. Note that triggering a run against an app with no live runner does not return this: POST /events is still accepted (202) and the run parks and retries, failing terminally only after the bounded no-runner wait elapses.
500 Internal Server ErrorAn unexpected fault. The body is a generic { "error": "internal error" }; the detail is logged server-side and never returned.

Conflicts (409)

A 409 means the resource is in a state that doesn't allow the operation. The common cases:

errorCause
run already in a terminal statePausing, resuming, or cancelling a run that already succeeded, failed, or was cancelled.
run is not in a terminal stateReplaying or forking a run that hasn't finished.
run is not pausedResuming a run that isn't paused.
run is not awaiting a decisionDeciding an approval on a run that isn't waiting for one.
run is not in a failed stateExplaining a run that didn't fail.
approval is not openApproving or denying an approval that was already decided.
step attempt already recordedA duplicate step result (a runner retried after Duraton already recorded the step).
webhook token already in useCreating an inbound source whose issued receive URL token collides (rare - the token is random).
webhook source name already in use / webhook endpoint name already in useA source/endpoint name isn't unique in the project.
webhook endpoint url already subscribedThe outbound URL is already registered in the project.
webhook delivery is in flightRedelivering a webhook whose current attempt hasn't settled.
dataset name already in useCreating a dataset whose name is taken in the project.

Conflicts are safe to surface to the caller and, where they reflect a race (a duplicate step, an in-flight delivery), safe to ignore.

Handling errors

Check the status code and read the error field:

curl -sS -o /tmp/body -w "%{http_code}" \
  -X POST "$DURATON_URL/runs/$RUN_ID/resume" \
  -H "Authorization: Bearer $DURATON_API_KEY"
# 409
cat /tmp/body
# { "error": "run is not paused" }

On this page