Confirm a proposed action (the kernel fires it)
const url = 'https://api.aerandil.com/v1/proposed-actions/2489E9AD-2EE2-8E00-8EC9-32D5F69181C0/confirm';const options = { method: 'POST', headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'}, body: '{"applied_params":{},"return_modified":false}'};
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://api.aerandil.com/v1/proposed-actions/2489E9AD-2EE2-8E00-8EC9-32D5F69181C0/confirm \ --header 'Authorization: Bearer <token>' \ --header 'Content-Type: application/json' \ --data '{ "applied_params": {}, "return_modified": false }'Accept a proposed_action and commit its chained target_action. This is the gold-standard human-in-the-loop commit: a confirming principal (staff, a guest surface, or an approval gate) accepts the proposal, and the kernel — not the proposing agent — fires the frozen target_action through the scope-checked action engine (Return-of-Control), then records the confirmation on the proposal (proposal 0030 §5.2).
confirmer_scope (0030 §6). The caller must independently hold actions:{target_action}:apply for the proposal’s target action — the proposal does not launder away authorization. That grant is a dynamic per-proposal scope (it depends on which action the proposal chains), so it is not enumerable as a static security entry here; the engine enforces it when the chained action fires.
Idempotent via Idempotency-Key. The key is derived deterministically from the proposal id, so a crash between firing the action and recording the confirmation replays rather than double-fires; a replay adds idempotent_replay: true.
Authorizations
Section titled “Authorizations”Parameters
Section titled “Parameters”Path Parameters
Section titled “Path Parameters”Object id (UUID v7, server-generated at create time).
Header Parameters
Section titled “Header Parameters”Opaque idempotency token (Stripe-shape). Repeated POSTs with the same key replay the original response within the cache TTL rather than creating a duplicate object.
Request Body
Section titled “Request Body”object
The confirmer’s edit of the proposed parameters; absent → the frozen snapshot fires unchanged.
object
Include the chained action’s modified-objects projection in the response.
Responses
Section titled “Responses”Confirmed. The chained action fired and the proposal is applied. A replay adds idempotent_replay: true.
object
Ref of the primary object the chained action touched, when it produced one.
The chained action’s apply envelope; present only when return_modified is true.
object
Present and true only on an idempotent replay.
Example
{ "decision_status": "applied"}The confirmer lacks the target action’s actions:{target_action}:apply scope.
Structured error wrapper. Every non-2xx response from any Aerandil endpoint serialises to this shape; the HTTP status carries the failure class (4xx/5xx), the body adds a stable code for programmatic dispatch plus a human-readable message.
object
object
Stable, programmatic error code (e.g. unauthorized, forbidden, not_found, invalid_body, invalid_url, precondition_failed, no_secondary_key). Clients dispatch on code, not on the message (which may be localised or contextualised in future versions).
Request-id correlation handle echoed on the request-id response header — support teams correlate without scraping logs.
Human-readable explanation of the failure.
Per-error structured detail. The shape varies by code (e.g. forbidden_action carries {"action": "..."}; precondition_failed carries {"current_version": N}).
Examplegenerated
{ "error": { "code": "example", "instance_id": "example", "message": "example", "parameters": "example" }}No such proposed_action for this tenant, or its target action is not registered.
Structured error wrapper. Every non-2xx response from any Aerandil endpoint serialises to this shape; the HTTP status carries the failure class (4xx/5xx), the body adds a stable code for programmatic dispatch plus a human-readable message.
object
object
Stable, programmatic error code (e.g. unauthorized, forbidden, not_found, invalid_body, invalid_url, precondition_failed, no_secondary_key). Clients dispatch on code, not on the message (which may be localised or contextualised in future versions).
Request-id correlation handle echoed on the request-id response header — support teams correlate without scraping logs.
Human-readable explanation of the failure.
Per-error structured detail. The shape varies by code (e.g. forbidden_action carries {"action": "..."}; precondition_failed carries {"current_version": N}).
Examplegenerated
{ "error": { "code": "example", "instance_id": "example", "message": "example", "parameters": "example" }}not_confirmable — the proposal is in a terminal status or has expired.
Structured error wrapper. Every non-2xx response from any Aerandil endpoint serialises to this shape; the HTTP status carries the failure class (4xx/5xx), the body adds a stable code for programmatic dispatch plus a human-readable message.
object
object
Stable, programmatic error code (e.g. unauthorized, forbidden, not_found, invalid_body, invalid_url, precondition_failed, no_secondary_key). Clients dispatch on code, not on the message (which may be localised or contextualised in future versions).
Request-id correlation handle echoed on the request-id response header — support teams correlate without scraping logs.
Human-readable explanation of the failure.
Per-error structured detail. The shape varies by code (e.g. forbidden_action carries {"action": "..."}; precondition_failed carries {"current_version": N}).
Examplegenerated
{ "error": { "code": "example", "instance_id": "example", "message": "example", "parameters": "example" }}applied_params is present but is not a JSON object.
Structured error wrapper. Every non-2xx response from any Aerandil endpoint serialises to this shape; the HTTP status carries the failure class (4xx/5xx), the body adds a stable code for programmatic dispatch plus a human-readable message.
object
object
Stable, programmatic error code (e.g. unauthorized, forbidden, not_found, invalid_body, invalid_url, precondition_failed, no_secondary_key). Clients dispatch on code, not on the message (which may be localised or contextualised in future versions).
Request-id correlation handle echoed on the request-id response header — support teams correlate without scraping logs.
Human-readable explanation of the failure.
Per-error structured detail. The shape varies by code (e.g. forbidden_action carries {"action": "..."}; precondition_failed carries {"current_version": N}).
Examplegenerated
{ "error": { "code": "example", "instance_id": "example", "message": "example", "parameters": "example" }}