Approvals API

Decide the runs waiting on a person from your own tooling: list open approvals and approve, deny, or approve with edits over HTTP.

An approval is a step that parks its run in needs_attention until someone approves or denies it; the decision resumes the run from its checkpoint. Reads work with a public key; the decision needs a secret key.

Endpoints

Method + pathPurpose
GET /approvalsThe project's approvals, newest first.
GET /approvals/{id}One approval, with the proposed tool call and its context.
POST /approvals/{id}/decisionApprove or deny an open approval; the parked run resumes.

Listing

GET /approvals accepts:

ParamMeaningDefault
statusOne of pending, escalated, approved, denied. pending and escalated are open, awaiting a decision. An unknown value returns 400.all
runIdOnly one run's approvals.all
limitPage size, 1-1000. A non-integer returns 400.100

A decided approval stays listable as its audit trail. Each approval is:

{
  "id": "01JZR4A0...", "runId": "01JZR3Z9...",
  "workflow": "support.refund", "app": "support", "step": "refund-gate",
  "tool": "issue-refund",
  "args": { "orderId": "A1", "amount": 4200, "currency": "usd" },
  "risk": "high",
  "policy": "tools.issue-refund -> require approval",
  "summary": "Refund 4200 to A1 for a duplicate charge",
  "escalatesTo": "#support-leads",
  "status": "pending",
  "requestedAt": "2026-07-01T10:00:00Z",
  "expiresAt": "2026-07-01T10:30:00Z"
}
FieldMeaning
id, runIdThe approval and the run parked on it.
workflow, appJoined from the parked run.
stepThe step.approval name in the workflow.
tool, argsThe proposed action awaiting sign-off.
riskThe declared risk level.
policy, summary, contextAnnotations for whoever reviews it. Absent when not set.
escalatesToThe escalation target once expiresAt passes.
statuspending, escalated, approved, or denied.
requestedAt, expiresAtWhen it was requested, and when it escalates. expiresAt absent without a timeout.
decidedAt, decidedBy, editedArgsSet once decided: when, by whom, and the decider's edited arguments (approve-with-edits). Absent while open.

Deciding

POST /approvals/{id}/decision applies the decision and resumes the run:

{ "status": "approved", "decidedBy": "ali", "args": { "orderId": "A1", "amount": 2100, "currency": "usd" } }

status must be approved or denied. decidedBy labels the decision (it defaults to the calling API key). args, when present, replaces the proposed tool arguments on the approved decision - approve-with-edits; the workflow receives them as the effective decision.args. The response is the decided approval.

import { createClient } from "@duraton/sdk/client";

const duraton = createClient({ url: process.env.DURATON_URL! });
const open = await duraton.approvals.list({ status: "pending" });
await duraton.approvals.decide(open[0].id, { status: "approved" });

Error codes

StatusWhen
400An unknown status filter; a decision whose status is not approved/denied; or invalid args JSON.
404The approval id does not exist.
409Deciding an approval that is already decided.

On this page