Overview

Do anything the console does from your own code: the Duraton HTTP API's base URL, authentication, conventions, and full endpoint map.

Everything the console does goes through Duraton's HTTP API, and so can you. It is plain JSON over HTTP - no SDK required to trigger events, read runs, or control them.

curl "$DURATON_URL/runs?limit=5" \
  -H "Authorization: Bearer $DURATON_API_KEY"

Base URL

Your workspace's base URL is shown in the console under API Keys (for example https://run.duraton.dev); it is the value you set DURATON_URL to. All paths below are relative to it. A workspace holds one or more projects that share this base URL; each project has its own API keys, and the key is what scopes a request to a single project.

Authentication

Every request needs an API key, presented as a Bearer token. Issue one in the console under API Keys:

curl "$DURATON_URL/runs" \
  -H "Authorization: Bearer $DURATON_API_KEY"

Keys carry a scope. A public (read-only) key can call the GET endpoints; writes (every POST, PATCH, and DELETE, plus the /connect upgrade) need a secret key.

ResponseWhen
401 UnauthorizedThe key is missing or unknown.
403 ForbiddenA public (read-only) key attempted a write, or the project is suspended.

Conventions

  • Request and response bodies are JSON. Send POST and PATCH bodies as a JSON object.
  • Reads return 200; writes return 200, 201, 202, or 204 depending on the route. The full map, and the failure codes, are in errors.
  • Listings are newest-first and bounded. GET /runs, GET /webhook-deliveries, and GET /webhook-source-deliveries use keyset pagination via the X-Next-Cursor header; the other listings take a limit (see limits).

Runs

Method + pathPurpose
GET /runsList and filter runs, newest first, with an X-Next-Cursor header.
GET /runs/{id}One run, with its input and result.
GET /runs/{id}/stepsThe run's steps, in order.
GET /runs/{id}/logsThe run's ctx.log lines, oldest first.
GET /runs/{id}/streamLive SSE timeline of one run (status + logs).
GET /runs/streamLive SSE stream of run status transitions across the project.
GET /runs/statsAggregate run counts for a filter.
GET /runs/timeseriesRun counts bucketed over time, with duration averages.
POST /runs/{id}/explainStream a plain-language explanation of a failed run (SSE).
GET /ai/spendAI token/cost rollup - totals plus by-hour, by-model, by-workflow.
GET /sessionsConversation sessions: runs grouped by session id.

Control

Method + pathPurpose
POST /runs/{id}/cancelCancel a run.
POST /runs/{id}/pausePause a run at its next step boundary.
POST /runs/{id}/resumeResume a paused run.
POST /runs/{id}/replayReplay a finished run as a new run.
POST /runs/{id}/retry-from-stepFork a finished run from a named step.
POST /runs/{id}/forkFork with one declared AI change as a shadow run.
POST /runs/bulk-replayReplay every finished run matching a filter.
GET /control-actionsThe control-action audit log, newest first.

Events

Method + pathPurpose
POST /eventsTrigger workflows by sending an event. Returns 202.
GET /eventsRead the event log.
GET /events/{id}One event log record.
GET /events/streamLive event tail (Server-Sent Events).

Approvals and evals

Method + pathPurpose
GET /approvalsThe project's approvals, newest first.
GET /approvals/{id}One approval, with its proposed tool call.
POST /approvals/{id}/decisionApprove or deny an open approval; the parked run resumes.
GET /runs/{id}/scoresA run's scores, newest first.
POST /runs/{id}/scoresRecord a score on a run. Returns 201.
GET /datasets POST /datasetsList or create datasets of test cases.
GET /datasets/{id}One dataset.
GET /datasets/{id}/items POST /datasets/{id}/itemsList or append test cases.
POST /datasets/{id}/evalFan a dataset through a workflow as an eval run-set.
GET /datasets/{id}/eval-runsThe dataset's eval run-sets, newest first.
GET /eval-sets/{id}One eval run-set with its score aggregates.

Webhooks

Method + pathPurpose
POST /webhooks/{token}Public: a signature-verified inbound webhook mapped onto an event. Returns 202.
GET /webhook-deliveriesThe outbound delivery log, newest first.
GET /webhook-deliveries/{id}One delivery with its attempt log.
POST /webhook-deliveries/{id}/redeliverRe-queue a delivery for a fresh attempt. Returns 204.
GET /webhook-source-deliveriesThe inbound source delivery log, newest first.
GET /webhook-source-deliveries/{id}One inbound delivery with its stored body and attempt log.
POST /webhook-source-deliveries/{id}/replayRe-ingest a verified inbound delivery's stored body. Returns 200 with the replay outcome.
GET POST PATCH DELETE /webhook-endpoints[/{id}]Manage outbound subscriptions (secrets shown once).
GET /webhook-endpoints/statsPer-endpoint delivery health over a window.
GET POST PATCH DELETE /webhook-sources[/{id}]Manage inbound sources (secrets shown once).

Registry

Method + pathPurpose
GET /workflowsList registered workflows, each with its flowControl config and the advisory steps manifest when declared.
POST /workflows/{app}/{name}/triggerStart one off-schedule run of a registered workflow - works even for a cron-only workflow. Returns 202.
GET /appsList registered apps.
GET /runnersList connected runners with their metadata and liveness.
GET /flow-stateLive flow-control buffers (debounce, batch, concurrency draw).

The runner protocol (POST /register, the invoke call, GET /connect) is documented separately in the wire protocol, and the same operations are available to AI agents as MCP tools.

On this page