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.