CitationBenchTalk to Sales
API referenceAgent

Agent approval API — inspect, approve, and reject paused agent invocations

REST and MCP endpoints for the CitationBench agent approval queue. List pending approvals, approve (optionally with edits), reject (optionally with rerun config), or comment without deciding.

The endpoints for inspecting, approving, and rejecting paused agent invocations. The conceptual model — when agents pause, how to set policy, how eval gates relate — lives in Approval Workflows and Eval Gates.

Endpoints

MethodPathPurpose
GET/v1/agent/approvalsList pending approvals
GET/v1/agent/approvals/{approvalId}Get one
POST/v1/agent/invocations/{id}/approveApprove (optionally with edits)
POST/v1/agent/invocations/{id}/rejectReject (optionally with rerun config)
POST/v1/agent/approvals/{approvalId}/commentAdd a comment without deciding

GET /v1/agent/approvals

List pending approvals across the workspace (or, for agency master keys, across the whole agency).

curl -G "https://api.citationbench.com/v1/agent/approvals" \
  -H "Authorization: Bearer sk_live_***" \
  --data-urlencode "scope=workspace" \
  --data-urlencode "skill=link_building.serp_outreach"
ParamNotes
scopeworkspace (default), agency (master keys only)
skillFilter by skill slug
routedToFilter by approver user / channel
raisedAfter / raisedBeforeISO timestamps
tagFilter by invocation tag
limit, cursorPagination

Response

{
  "data": [
    {
      "approvalId": "appr_01HVZ...",
      "invocationId": "inv_01HVZ...",
      "agentId": "agt_01HVZ...",
      "skill": "link_building.serp_outreach",
      "step": "send_outreach_email",
      "preview": {
        "to": "marina@engineering-blog.com",
        "subject": "Section 7 of your PM tools roundup",
        "body": "Hi Marina, ...",
        "scheduledAt": "2026-05-25T09:00:00-04:00"
      },
      "reason": "Workspace policy: outreach_send=require_approval",
      "routedTo": ["raymond@acme.com"],
      "raisedAt": "2026-05-24T08:14:32Z",
      "timeoutAt": "2026-05-31T08:14:32Z",
      "comments": []
    }
  ],
  "nextCursor": null,
  "total": 14
}

GET /v1/agent/approvals/{approvalId}

Returns the same single record plus the full invocation context (tree, prior steps, files written so far).

curl https://api.citationbench.com/v1/agent/approvals/appr_*** \
  -H "Authorization: Bearer sk_live_***"

POST /v1/agent/invocations/{id}/approve

curl -X POST https://api.citationbench.com/v1/agent/invocations/inv_***/approve \
  -H "Authorization: Bearer sk_live_***" \
  -H "Content-Type: application/json" \
  -d '{
    "approvalId": "appr_***",
    "note":       "Looks good, ship it."
  }'

With edits

curl -X POST https://api.citationbench.com/v1/agent/invocations/inv_***/approve \
  -d '{
    "approvalId": "appr_***",
    "edits": {
      "subject": "Quick thought on your PM roundup",
      "body":    "Hi Marina, loved your roundup. Quick note on section 7 ..."
    },
    "note": "Softened opener"
  }'

The edits object is shape-validated against the preview. Any field you can edit is also shown in the preview's editableFields.

Trust hint

curl -X POST .../v1/agent/invocations/inv_***/approve \
  -d '{
    "approvalId":     "appr_***",
    "trustHenceforth":"contact"
  }'

trustHenceforth values:

  • contact — future actions toward the same contact auto-approve
  • account — future actions toward the same partner domain auto-approve
  • step — future invocations of the same skill step auto-approve (for this workspace)
  • none — no trust hint (default)

Response

{
  "approvalId": "appr_***",
  "decision": "APPROVED",
  "decidedAt": "2026-05-24T09:02:18Z",
  "approver": "raymond@acme.com",
  "edited": true,
  "trustGranted": null,
  "invocation": {
    "invocationId": "inv_***",
    "status": "RUNNING",
    "resumeAt": "2026-05-24T09:02:18Z"
  }
}

POST /v1/agent/invocations/{id}/reject

Reject + skip the step

curl -X POST .../v1/agent/invocations/inv_***/reject \
  -d '{
    "approvalId": "appr_***",
    "skipStep":   true,
    "note":       "Wrong contact — please skip"
  }'

If skipStep: true, the skill may continue past the rejected step. Otherwise, the invocation transitions to FAILED.

Reject + rerun the step with different config

curl -X POST .../v1/agent/invocations/inv_***/reject \
  -d '{
    "approvalId": "appr_***",
    "rerun": {
      "step":   "drafts",
      "config": { "tone": "more skeptical" }
    },
    "note": "Re-draft with a more skeptical tone"
  }'

Response

{
  "approvalId": "appr_***",
  "decision": "REJECTED",
  "decidedAt": "2026-05-24T09:02:18Z",
  "approver": "raymond@acme.com",
  "invocation": {
    "invocationId": "inv_***",
    "status": "RUNNING",
    "rerunStep": "drafts"
  }
}

POST /v1/agent/approvals/{approvalId}/comment

Add a comment without making a decision (useful for routing back to a colleague or stalling for context).

curl -X POST .../v1/agent/approvals/appr_***/comment \
  -d '{
    "author":  "raymond@acme.com",
    "comment": "@marketing — does the offer in section 3 still hold?"
  }'

Comments append to the approval's comments array. They don't change the invocation's state.


MCP

> What's in my approval queue?

Claude calls agent.approval.list.

> Show me the first one.

Claude calls agent.approval.get and renders the preview.

> Approve it.

Claude calls agent.approval.approve.

> Reject it and tell the agent to rewrite the email with a more skeptical tone.

Claude calls agent.approval.reject with the rerun directive.


Errors

StatusCodeCause
404approval_not_found
409already_decidedApproval was already approved / rejected (race condition)
410approval_timed_outApproval timed out before action; the invocation was cancelled
422invalid_editsedits payload doesn't match the preview's editableFields
422invalid_rerun_steprerun.step doesn't exist on the skill

Cost

ActionCredits
All approval actionsfree

(The invocation continues to bill once it resumes.)

Common patterns

1. Slack-button approval

Wire agent.invocation.awaiting_approval webhook to a small Slack bot. It posts the preview with Approve / Reject buttons. Button clicks POST back to /v1/agent/invocations/{id}/approve or /reject.

2. Client-portal approval

Webhook target is a small service in your client portal. The client sees the preview in their familiar UI, clicks approve, your service POSTs to the API.

3. Bulk approval

For SERP outreach campaigns and similar bulk drafts, use the campaign-level bulk endpoints (Link Building · serp outreach § approve drafts) rather than approving N invocations individually.

4. Approval audit

curl -G .../v1/agent/approvals \
  --data-urlencode "scope=agency" \
  --data-urlencode "raisedAfter=2026-05-01T00:00:00Z" \
  --data-urlencode "include=decisions"

Returns approvals with their decision history — useful for monthly client review.

On this page