Submit a decision on an approval
const url = 'https://example.com/v1/approvals/2489E9AD-2EE2-8E00-8EC9-32D5F69181C0/complete';const options = { method: 'POST', headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'}, body: '{"decision":"approve","rationale":"example","value":"example","factText":"example"}'};
try { const response = await fetch(url, options); const data = await response.json(); console.log(data);} catch (error) { console.error(error);}curl --request POST \ --url https://example.com/v1/approvals/2489E9AD-2EE2-8E00-8EC9-32D5F69181C0/complete \ --header 'Authorization: Bearer <token>' \ --header 'Content-Type: application/json' \ --data '{ "decision": "approve", "rationale": "example", "value": "example", "factText": "example" }'Records the decision (HitlBinding.submitReview). When the approval carries a waitTokenId and the decision is approve or reject, also completes the waitpoint so the suspended run resumes, with { decided, rationale?, decidedBy, approvalId }: the run’s journal records who decided which approval (decidedBy is user:<userId>).
Authorizations
Section titled “Authorizations”Parameters
Section titled “Parameters”Path Parameters
Section titled “Path Parameters”ApprovalId — opaque branded string (a UUID).
Header Parameters
Section titled “Header Parameters”Caller-supplied idempotency key, scoped to the caller: the same key from someone else in the tenant is their own request (from 0.1.5). Retries with the same key return the original response byte-identical (per docs/API-ROUTE-CONVENTIONS.md §3.1). A retry sent while the first request still runs is answered 409 idempotency-key-in-flight with Retry-After, on a runtime whose store holds keys (from 0.1.5); retry after it, and you get the first request’s answer. An answer that carries a secret (a new API key or public run token, a session token, a generated signing secret) isn’t kept: a retry gets 409 idempotency-key-replay-withheld, with the first request’s status and when it succeeded (from 0.1.5). A request whose key store can’t be read before it runs is answered 503 idempotency-store-unavailable with Retry-After: nothing ran, so retry with the same key (from 0.3.0).
Request Bodyrequired
Section titled “Request Bodyrequired”object
Payload passed to the run waitpoint (RunBinding.completeToken) when the approval is linked to a suspended run and the decision is approve or reject. Refused (400 bad-input) for an agent’s tool-call or session gate (tool-call:pending, agent-turn:session-hitl-gate): those resume on the decision alone.
Only with decision: approve, on the approval of a fact an agent wants to remember (subjectKind: fact): the text the fact holds once approved, in place of the agent’s. The approval keeps the agent’s text as its description, and its decision records this one. More than spaces, at most 2000 characters. Refused (400 bad-input) on any other decision or approval.
Responses
Section titled “Responses”Decision recorded.
A recorded decision, and what it did to the run waiting on the approval. runStatus is the run’s status when the decision couldn’t resolve its waitpoint because the run had already ended (e.g. cancelled after the decision was recorded); the decision stands.
object
object
object
Reviewer role class. Hierarchy: standard < senior < admin.
object
object
The reviewer’s decision, once one is recorded. Absent while the approval is open, and when it ended without one (it expired, a timeout escalated it, or its run’s end withdrew it).
object
Who decided, as an actor: user:<userId>, the reviewer’s user. The run’s journal and provenance name the decider the same way. The Kindgi runtime always records it; a deployment whose HITL binding doesn’t leaves it out.
Reviewer role class. Hierarchy: standard < senior < admin.
The provider of the session the reviewer decided with: site:<id> for a site’s sign-in, an identity provider’s id for a single sign-on session. Absent for an API key, and on decisions an older runtime recorded.
The reviewer’s display name when they decided: a person renamed since still shows as they were. Absent on decisions an older runtime recorded.
The text a reviewer approved a remembered fact with, in place of the agent’s (the approval’s description), which the fact now holds. Absent when the fact was approved as the agent wrote it.
Who asked for it, when recorded: user:<id>, service_account:<id> or system:<what>.
Whether the person who asked may not approve it (four eyes). A runtime that knows it always sends it, false included.
Why it was withdrawn, when its run’s end withdrew it (a reviewer’s withdrawal has its decision instead).
The approval this one was escalated from.
The approval this one was escalated to.
The one member who may decide it.
object
The person’s account the call would use.
object
The app’s entry id.
The account’s label at the app: an email address, a login.
object
Reviewer role class. Hierarchy: standard < senior < admin.
The text a reviewer approved a remembered fact with, in place of the agent’s (the approval’s description), which the fact now holds. Absent when the fact was approved as the agent wrote it.
Present only when kind === "escalated".
object
object
Reviewer role class. Hierarchy: standard < senior < admin.
object
object
The reviewer’s decision, once one is recorded. Absent while the approval is open, and when it ended without one (it expired, a timeout escalated it, or its run’s end withdrew it).
object
Who decided, as an actor: user:<userId>, the reviewer’s user. The run’s journal and provenance name the decider the same way. The Kindgi runtime always records it; a deployment whose HITL binding doesn’t leaves it out.
Reviewer role class. Hierarchy: standard < senior < admin.
The provider of the session the reviewer decided with: site:<id> for a site’s sign-in, an identity provider’s id for a single sign-on session. Absent for an API key, and on decisions an older runtime recorded.
The reviewer’s display name when they decided: a person renamed since still shows as they were. Absent on decisions an older runtime recorded.
The text a reviewer approved a remembered fact with, in place of the agent’s (the approval’s description), which the fact now holds. Absent when the fact was approved as the agent wrote it.
Who asked for it, when recorded: user:<id>, service_account:<id> or system:<what>.
Whether the person who asked may not approve it (four eyes). A runtime that knows it always sends it, false included.
Why it was withdrawn, when its run’s end withdrew it (a reviewer’s withdrawal has its decision instead).
The approval this one was escalated from.
The approval this one was escalated to.
The one member who may decide it.
object
The person’s account the call would use.
object
The app’s entry id.
The account’s label at the app: an email address, a login.
True when the approval had a waitTokenId and this call resolved the run’s waitpoint: approve and reject complete it; withdraw cancels it, so the run ends (failed, hitl-withdrawn).
Example
{ "kind": "terminal", "approval": { "requiredRole": "standard", "status": "pending", "decision": { "decision": "approve", "reviewerRoleAtDecision": "standard" }, "withdrawnBecause": "run-cancelled", "approver": { "kind": "member" } }, "decision": { "decision": "approve", "reviewerRoleAtDecision": "standard" }, "nextApproval": { "requiredRole": "standard", "status": "pending", "decision": { "decision": "approve", "reviewerRoleAtDecision": "standard" }, "withdrawnBecause": "run-cancelled", "approver": { "kind": "member" } }, "runStatus": "pending", "resume": { "kind": "ok" }}Malformed request body.
object
object
Stable machine-readable discriminant. Values match domain error codes (see docs/API-ROUTE-CONVENTIONS.md §4.3).
Optional, kind-specific.
object
Server-assigned request id; also echoed via X-Request-Id header.
Examplegenerated
{ "error": { "code": "example", "message": "example", "details": {}, "requestId": "example" }}Missing / malformed / expired / revoked bearer token.
object
object
Stable machine-readable discriminant. Values match domain error codes (see docs/API-ROUTE-CONVENTIONS.md §4.3).
Optional, kind-specific.
object
Server-assigned request id; also echoed via X-Request-Id header.
Examplegenerated
{ "error": { "code": "example", "message": "example", "details": {}, "requestId": "example" }}Reviewer role too low, or no reviewer row for this user.
object
object
Stable machine-readable discriminant. Values match domain error codes (see docs/API-ROUTE-CONVENTIONS.md §4.3).
Optional, kind-specific.
object
Server-assigned request id; also echoed via X-Request-Id header.
Examplegenerated
{ "error": { "code": "example", "message": "example", "details": {}, "requestId": "example" }}No approval visible to the caller with that id.
object
object
Stable machine-readable discriminant. Values match domain error codes (see docs/API-ROUTE-CONVENTIONS.md §4.3).
Optional, kind-specific.
object
Server-assigned request id; also echoed via X-Request-Id header.
Examplegenerated
{ "error": { "code": "example", "message": "example", "details": {}, "requestId": "example" }}Idempotency-Key was reused with a different body, or resource-state conflict.
object
object
Stable machine-readable discriminant. Values match domain error codes (see docs/API-ROUTE-CONVENTIONS.md §4.3).
Optional, kind-specific.
object
Server-assigned request id; also echoed via X-Request-Id header.
Examplegenerated
{ "error": { "code": "example", "message": "example", "details": {}, "requestId": "example" }}The request body is over the API’s limit (request-too-large; details.maxBytes says how much).
object
object
Stable machine-readable discriminant. Values match domain error codes (see docs/API-ROUTE-CONVENTIONS.md §4.3).
Optional, kind-specific.
object
Server-assigned request id; also echoed via X-Request-Id header.
Examplegenerated
{ "error": { "code": "example", "message": "example", "details": {}, "requestId": "example" }}Server error (unmapped domain code or framework crash).
object
object
Stable machine-readable discriminant. Values match domain error codes (see docs/API-ROUTE-CONVENTIONS.md §4.3).
Optional, kind-specific.
object
Server-assigned request id; also echoed via X-Request-Id header.
Examplegenerated
{ "error": { "code": "example", "message": "example", "details": {}, "requestId": "example" }}The Idempotency-Key store couldn’t be read before the request ran (idempotency-store-unavailable), so nothing was changed; Retry-After (whole seconds) says when to try again with the same key.
object
object
Stable machine-readable discriminant. Values match domain error codes (see docs/API-ROUTE-CONVENTIONS.md §4.3).
Optional, kind-specific.
object
Server-assigned request id; also echoed via X-Request-Id header.
Examplegenerated
{ "error": { "code": "example", "message": "example", "details": {}, "requestId": "example" }}