Source: docs/integration/capability-action-approval.md
Capability action approval API
Forgium returns a safe pending_action when a capability would change data or
send an external message. The host application owns the confirmation screen
and any step-up authentication. Forgium supplies only the server-to-server
protocol.
Read the action
curl -fsS "$FORGIUM_AGENT_BASE_URL/v1/actions/$ACTION_ID" \
-H "Authorization: Bearer $FORGIUM_AGENT_API_KEY"
The response contains action_id, summary, status, expires_at, a
sanitized result only after success, and a stable error code when execution
fails. It never contains credentials, raw arguments, or endpoint payloads.
Approve from the host backend
curl -fsS -X POST "$FORGIUM_AGENT_BASE_URL/v1/actions/$ACTION_ID/approve" \
-H "Authorization: Bearer $FORGIUM_AGENT_API_KEY" \
-H "Idempotency-Key: approval-$REQUEST_ID" \
-H "Content-Type: application/json" \
-d '{"approved_by_subject":"opaque-host-user-id"}'
Approval is bound to the immutable capability revision, canonical arguments,
expiry, asserted subject, and one durable upstream idempotency key. The state
transition is compare-and-set:
pending → approved → executing → executed | failed
pending → rejected
A fast result is 200. A slow endpoint returns 202 with status: executing;
poll GET /v1/actions/{actionId}. Repeating the same idempotency key returns
the original response and never invokes the endpoint twice. A different key
cannot approve an action that is no longer pending. Expired actions return
410 ACTION_EXPIRED.
Reject from the host backend
curl -fsS -X POST "$FORGIUM_AGENT_BASE_URL/v1/actions/$ACTION_ID/reject" \
-H "Authorization: Bearer $FORGIUM_AGENT_API_KEY" \
-H "Idempotency-Key: rejection-$REQUEST_ID" \
-H "Content-Type: application/json" \
-d '{"rejected_by_subject":"opaque-host-user-id"}'
Rejection is atomic and never calls the capability endpoint.
Verify the signed invocation
Every endpoint invocation includes Forgium-Context, a compact Ed25519 JWS.
Fetch the public keys from
/.well-known/forgium/capability-context/v1/jwks.json, select kid, and
reject unknown algorithms, key IDs, issuers, audiences, expired claims, reused
jti values, mismatched method or URL, and a body_sha256 that differs from
the raw request body. Allow at most 60 seconds of clock skew. Store the replay
key only until exp.
The host endpoint remains responsible for its own authorization, business
rules, and data protection. A valid Forgium signature proves request integrity
and platform authorization; it does not prove the human's identity.