Skip to content

Submit a decision on an approval

View as Markdown
POST
/v1/approvals/{approvalId}/complete
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" }'

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>).

approvalId
required
string format: uuid

ApprovalId — opaque branded string (a UUID).

Idempotency-Key
string
>= 1 characters

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).

Media typeapplication/json
object
decision
required
string
Allowed values: approve reject escalate withdraw
rationale
string
value

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.

Decision recorded.

Media typeapplication/json

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
kind
required
string
Allowed values: terminal escalated
approval
required
object
id
required
string format: uuid
tenantId
required
string format: uuid
projectId
string format: uuid
subjectKind
required
string
subjectRef
required
object
key
additional properties
any
requiredRole
required

Reviewer role class. Hierarchy: standard < senior < admin.

string
Allowed values: standard senior admin
status
required
string
Allowed values: pending assigned in_review approved rejected escalated expired withdrawn
assignedTo
string format: uuid
batchKey
string
title
string
description
string
context
object
key
additional properties
any
provenanceRef
object
runId
required
string format: uuid
provenanceId
string format: uuid
waitTokenId
string
createdAt
required
string format: date-time
updatedAt
required
string format: date-time
decidedAt
string format: date-time
expiresAt
string format: date-time
decision

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
decision
required
string
Allowed values: approve reject escalate withdraw
decidedBy

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.

string
reviewerId
required
string format: uuid
reviewerRoleAtDecision
required

Reviewer role class. Hierarchy: standard < senior < admin.

string
Allowed values: standard senior admin
decidedAt
required
string format: date-time
rationale
string
sessionProvider

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.

string
deciderName

The reviewer’s display name when they decided: a person renamed since still shows as they were. Absent on decisions an older runtime recorded.

string
requestedBy

Who asked for it, when recorded: user:<id>, service_account:<id> or system:<what>.

string
separateApprover

Whether the person who asked may not approve it (four eyes). A runtime that knows it always sends it, false included.

boolean
withdrawnBecause

Why it was withdrawn, when its run’s end withdrew it (a reviewer’s withdrawal has its decision instead).

string
Allowed values: run-cancelled run-ended
escalatedFrom

The approval this one was escalated from.

string format: uuid
escalatedTo

The approval this one was escalated to.

string format: uuid
decision
required
object
id
required
string
approvalId
required
string format: uuid
reviewerId
required
string format: uuid
decision
required
string
Allowed values: approve reject escalate withdraw
rationale
string
reviewerRoleAtDecision
required

Reviewer role class. Hierarchy: standard < senior < admin.

string
Allowed values: standard senior admin
decidedAt
required
string format: date-time
nextApproval

Present only when kind === "escalated".

object
id
required
string format: uuid
tenantId
required
string format: uuid
projectId
string format: uuid
subjectKind
required
string
subjectRef
required
object
key
additional properties
any
requiredRole
required

Reviewer role class. Hierarchy: standard < senior < admin.

string
Allowed values: standard senior admin
status
required
string
Allowed values: pending assigned in_review approved rejected escalated expired withdrawn
assignedTo
string format: uuid
batchKey
string
title
string
description
string
context
object
key
additional properties
any
provenanceRef
object
runId
required
string format: uuid
provenanceId
string format: uuid
waitTokenId
string
createdAt
required
string format: date-time
updatedAt
required
string format: date-time
decidedAt
string format: date-time
expiresAt
string format: date-time
decision

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
decision
required
string
Allowed values: approve reject escalate withdraw
decidedBy

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.

string
reviewerId
required
string format: uuid
reviewerRoleAtDecision
required

Reviewer role class. Hierarchy: standard < senior < admin.

string
Allowed values: standard senior admin
decidedAt
required
string format: date-time
rationale
string
sessionProvider

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.

string
deciderName

The reviewer’s display name when they decided: a person renamed since still shows as they were. Absent on decisions an older runtime recorded.

string
requestedBy

Who asked for it, when recorded: user:<id>, service_account:<id> or system:<what>.

string
separateApprover

Whether the person who asked may not approve it (four eyes). A runtime that knows it always sends it, false included.

boolean
withdrawnBecause

Why it was withdrawn, when its run’s end withdrew it (a reviewer’s withdrawal has its decision instead).

string
Allowed values: run-cancelled run-ended
escalatedFrom

The approval this one was escalated from.

string format: uuid
escalatedTo

The approval this one was escalated to.

string format: uuid
waitpointResolved
required

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).

boolean
runStatus
string
Allowed values: pending running suspended completed failed cancelled
resume
One of:
object
kind
required
string
Allowed value: ok
Example
{
"kind": "terminal",
"approval": {
"requiredRole": "standard",
"status": "pending",
"decision": {
"decision": "approve",
"reviewerRoleAtDecision": "standard"
},
"withdrawnBecause": "run-cancelled"
},
"decision": {
"decision": "approve",
"reviewerRoleAtDecision": "standard"
},
"nextApproval": {
"requiredRole": "standard",
"status": "pending",
"decision": {
"decision": "approve",
"reviewerRoleAtDecision": "standard"
},
"withdrawnBecause": "run-cancelled"
},
"runStatus": "pending",
"resume": {
"kind": "ok"
}
}

Malformed request body.

Media typeapplication/json
object
error
required
object
code
required

Stable machine-readable discriminant. Values match domain error codes (see docs/API-ROUTE-CONVENTIONS.md §4.3).

string
message
required
string
details

Optional, kind-specific.

object
key
additional properties
any
requestId
required

Server-assigned request id; also echoed via X-Request-Id header.

string
Examplegenerated
{
"error": {
"code": "example",
"message": "example",
"details": {},
"requestId": "example"
}
}

Missing / malformed / expired / revoked bearer token.

Media typeapplication/json
object
error
required
object
code
required

Stable machine-readable discriminant. Values match domain error codes (see docs/API-ROUTE-CONVENTIONS.md §4.3).

string
message
required
string
details

Optional, kind-specific.

object
key
additional properties
any
requestId
required

Server-assigned request id; also echoed via X-Request-Id header.

string
Examplegenerated
{
"error": {
"code": "example",
"message": "example",
"details": {},
"requestId": "example"
}
}

Reviewer role too low, or no reviewer row for this user.

Media typeapplication/json
object
error
required
object
code
required

Stable machine-readable discriminant. Values match domain error codes (see docs/API-ROUTE-CONVENTIONS.md §4.3).

string
message
required
string
details

Optional, kind-specific.

object
key
additional properties
any
requestId
required

Server-assigned request id; also echoed via X-Request-Id header.

string
Examplegenerated
{
"error": {
"code": "example",
"message": "example",
"details": {},
"requestId": "example"
}
}

No approval visible to the caller with that id.

Media typeapplication/json
object
error
required
object
code
required

Stable machine-readable discriminant. Values match domain error codes (see docs/API-ROUTE-CONVENTIONS.md §4.3).

string
message
required
string
details

Optional, kind-specific.

object
key
additional properties
any
requestId
required

Server-assigned request id; also echoed via X-Request-Id header.

string
Examplegenerated
{
"error": {
"code": "example",
"message": "example",
"details": {},
"requestId": "example"
}
}

Idempotency-Key was reused with a different body, or resource-state conflict.

Media typeapplication/json
object
error
required
object
code
required

Stable machine-readable discriminant. Values match domain error codes (see docs/API-ROUTE-CONVENTIONS.md §4.3).

string
message
required
string
details

Optional, kind-specific.

object
key
additional properties
any
requestId
required

Server-assigned request id; also echoed via X-Request-Id header.

string
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).

Media typeapplication/json
object
error
required
object
code
required

Stable machine-readable discriminant. Values match domain error codes (see docs/API-ROUTE-CONVENTIONS.md §4.3).

string
message
required
string
details

Optional, kind-specific.

object
key
additional properties
any
requestId
required

Server-assigned request id; also echoed via X-Request-Id header.

string
Examplegenerated
{
"error": {
"code": "example",
"message": "example",
"details": {},
"requestId": "example"
}
}

Server error (unmapped domain code or framework crash).

Media typeapplication/json
object
error
required
object
code
required

Stable machine-readable discriminant. Values match domain error codes (see docs/API-ROUTE-CONVENTIONS.md §4.3).

string
message
required
string
details

Optional, kind-specific.

object
key
additional properties
any
requestId
required

Server-assigned request id; also echoed via X-Request-Id header.

string
Examplegenerated
{
"error": {
"code": "example",
"message": "example",
"details": {},
"requestId": "example"
}
}

See also