SidClaw

Approval Endpoints

List, inspect, approve, and deny pending approval requests for flagged agent operations.

Approval Endpoints

When the policy engine returns approval_required, an approval request is created and placed in the approval queue. Human reviewers use these endpoints (or the dashboard) to inspect the request context and make a decision.

Endpoint Summary

MethodPathDescriptionAuth
GET/api/v1/approvalsList approval requestsAny
GET/api/v1/approvals/countGet count of approvals by statusAny
GET/api/v1/approvals/:idGet approval detail with contextAny
GET/api/v1/approvals/:id/statusLightweight status pollAny
POST/api/v1/approvals/:id/approveApprove a requestReviewer, Admin
POST/api/v1/approvals/:id/denyDeny a requestReviewer, Admin

GET /api/v1/approvals

List approval requests with optional filters and pagination.

Auth: API key with approvals:read scope, or any authenticated session.

Query Parameters

ParameterTypeDescription
statusstringFilter by status: pending, approved, denied, expired
agent_idstringFilter by agent UUID
limitintegerItems per page (default: 20, max: 100)
offsetintegerNumber of items to skip (default: 0)

Response

Status: 200 OK

{
  "data": [
    {
      "id": "770e8400-...",
      "trace_id": "550e8400-...",
      "agent_id": "550e8400-...",
      "requested_operation": "send_email",
      "target_integration": "gmail",
      "resource_scope": "external-recipients",
      "data_classification": "confidential",
      "risk_classification": "high",
      "authority_model": "delegated",
      "delegated_from": "Alice Johnson",
      "policy_effect": "approval_required",
      "flag_reason": "Confidential data access requires human approval",
      "status": "pending",
      "context_snapshot": { "recipient": "[email protected]" },
      "expires_at": "2026-03-22T10:00:00.000Z",
      "requested_at": "2026-03-21T10:00:00.000Z",
      "decided_at": null,
      "approver_name": null,
      "decision_note": null
    }
  ],
  "pagination": {
    "total": 5,
    "limit": 20,
    "offset": 0
  }
}

Example

curl "http://localhost:4000/api/v1/approvals?status=pending&limit=10" \
  -H "Authorization: Bearer sk_live_abc123"

GET /api/v1/approvals/count

Get a count of approval requests, optionally filtered by status. Useful for badge counts in the dashboard.

Auth: API key with approvals:read scope, or any authenticated session.

Query Parameters

ParameterTypeDescription
statusstringFilter by status (e.g., pending)

Response

Status: 200 OK

{
  "count": 3
}

Example

curl "http://localhost:4000/api/v1/approvals/count?status=pending" \
  -H "Authorization: Bearer sk_live_abc123"

GET /api/v1/approvals/:id

Get full detail of a single approval request, including the context snapshot provided during evaluation.

Auth: API key with approvals:read scope, or any authenticated session.

Path Parameters

ParameterTypeDescription
idstringApproval request UUID

Response

Status: 200 OK

Returns the full approval request object with related agent and trace information.

Example

curl http://localhost:4000/api/v1/approvals/770e8400-e29b-41d4-a716-446655440002 \
  -H "Authorization: Bearer sk_live_abc123"

Error Codes

StatusErrorDescription
404not_foundApproval request does not exist

GET /api/v1/approvals/:id/status

Lightweight endpoint for polling approval status. Returns only the fields needed to determine the current state. This is the recommended endpoint for SDK polling loops.

Auth: API key with approvals:read scope, or any authenticated session.

Path Parameters

ParameterTypeDescription
idstringApproval request UUID

Response

Status: 200 OK

{
  "id": "770e8400-e29b-41d4-a716-446655440002",
  "status": "approved",
  "decided_at": "2026-03-21T10:30:00.000Z",
  "approver_name": "Bob Smith",
  "decision_note": "Approved -- recipient is a known partner."
}
FieldTypeDescription
idstringApproval request UUID
statusstringOne of: pending, approved, denied, expired
decided_atstring | nullISO 8601 timestamp of the decision
approver_namestring | nullName of the reviewer who decided
decision_notestring | nullOptional note from the reviewer

Example

curl http://localhost:4000/api/v1/approvals/770e8400-e29b-41d4-a716-446655440002/status \
  -H "Authorization: Bearer sk_live_abc123"

Error Codes

StatusErrorDescription
404not_foundApproval request does not exist

POST /api/v1/approvals/:id/approve

Approve a pending approval request. This updates the trace, creates audit events, and allows the agent to proceed.

Auth: API key with admin scope, or session with reviewer or admin role.

Path Parameters

ParameterTypeDescription
idstringApproval request UUID

Request Body

FieldTypeRequiredDescription
approver_namestringYesName of the person approving
decision_notestringNoOptional note explaining the decision

Response

Status: 200 OK

Returns the updated approval request with status: "approved", decided_at, approver_name, and decision_note populated.

Side Effects

  • Updates the approval request status to approved.
  • Creates audit events on the associated trace (approval_granted, operation_allowed, trace_closed).
  • Updates the trace final_outcome to completed_with_approval.
  • Dispatches a webhook with event type approval.approved.

Example

curl -X POST http://localhost:4000/api/v1/approvals/770e8400-e29b-41d4-a716-446655440002/approve \
  -H "Authorization: Bearer sk_live_abc123" \
  -H "Content-Type: application/json" \
  -d '{
    "approver_name": "Bob Smith",
    "decision_note": "Approved -- recipient is a known partner."
  }'

Error Codes

StatusErrorDescription
400validation_errorMissing approver_name
403forbiddenReviewer or admin role/scope required
404not_foundApproval request does not exist
409conflictApproval is not in pending status

POST /api/v1/approvals/:id/deny

Deny a pending approval request. The agent operation is blocked.

Auth: API key with admin scope, or session with reviewer or admin role.

Path Parameters

ParameterTypeDescription
idstringApproval request UUID

Request Body

FieldTypeRequiredDescription
approver_namestringYesName of the person denying
decision_notestringNoOptional note explaining the denial reason

Response

Status: 200 OK

Returns the updated approval request with status: "denied".

Side Effects

  • Updates the approval request status to denied.
  • Creates audit events on the associated trace (approval_denied, operation_denied, trace_closed).
  • Updates the trace final_outcome to denied.
  • Dispatches a webhook with event type approval.denied.

Example

curl -X POST http://localhost:4000/api/v1/approvals/770e8400-e29b-41d4-a716-446655440002/deny \
  -H "Authorization: Bearer sk_live_abc123" \
  -H "Content-Type: application/json" \
  -d '{
    "approver_name": "Bob Smith",
    "decision_note": "Denied -- this recipient is not on the approved list."
  }'

Error Codes

StatusErrorDescription
400validation_errorMissing approver_name
403forbiddenReviewer or admin role/scope required
404not_foundApproval request does not exist
409conflictApproval is not in pending status

Approval Expiry

Approval requests have an expires_at timestamp. A background job runs periodically to expire overdue approvals, setting their status to expired and closing the associated trace with outcome expired. Expired approvals cannot be approved or denied.