POST /v1/agent/invoke can finish with status: "awaiting_approval".
run_id is the public request id. thread_id is the value you sent, or null. pending_tool_approvals is present only while the run is waiting. Each item includes approval_id, tool_name, summary, arguments, expires_at, and review_url. review_url opens the approval in the dashboard. It is not an email token. denied_tool_calls is present only when a tool was denied, with reason: "policy_deny". The response text also includes [Waiting for approval: …].
A streaming invoke puts the same fields on the final usage event.
Continue the run
An API key call resumes on the server after the decision. Poll the run or use the webhook. Do not send another invoke for that thread. A first-party streaming client sends the samethread_id with decided_tool_approvals:
decided_tool_approvals and reuse the thread, Fetch Hive loads the approvals from that thread.
Decide with an API key
decision is allow_once or deny. always_allow returns 422 with always_allow_requires_dashboard. A second decision returns 409. An expired approval returns 410. An approval outside the API key’s workspace returns 404.
List pending approvals:
status defaults to pending. You can filter with agent_id, run_id, and request_id. Pages use cursor and return at most 50 rows.
Skip approvals for a trusted server
See Invoke an agent fortool_approval. An API key can send auto_approve only after a workspace owner or admin allows that key in Settings → API keys. The permission is not a policy. Destructive actions still ask, Deny rules still block, sub-agents inherit the field, and workflows the agent starts do not.
Webhooks
A webhook-sourced run sendsagent.awaiting_approval when it pauses. The payload includes pending_tool_approvals. After the run continues, agent.completed includes resumed_from_run_id, and data.output_json when the webhook request sent a response_format.
