GET /api/approvals/{id}/status
Most callers should use
canopy.getApprovalStatus()orcanopy.waitForApproval()instead. This page is for direct wire-protocol callers.
Returns the current state of an approval request. You get an approval_request_id from POST /api/sign when a payment exceeds the agent's approval threshold.
The endpoint is scoped to your org's API key. You can't read approval statuses for agents in other orgs.
Base URL: https://trycanopy.ai
Request
GET /api/approvals/{id}/status
Authorization: Bearer <apiKey>Path parameters
| Param | Type | Description |
|---|---|---|
id | string | UUID of the approval request (the approval_request_id from /api/sign) |
200 — status snapshot
{
"status": "pending",
"decided_at": null,
"expires_at": "2026-04-28T11:00:00Z",
"transaction_id": "550e8400-..."
}After a decision:
{
"status": "approved",
"decided_at": "2026-04-28T10:32:11Z",
"expires_at": "2026-04-28T11:00:00Z",
"transaction_id": "550e8400-..."
}| Field | Type | Description |
|---|---|---|
status | string | "pending", "approved", "denied", or "expired" |
decided_at | string | null | ISO 8601 timestamp; null while pending |
expires_at | string | ISO 8601 timestamp the approval window expires |
transaction_id | string | UUID of the associated transaction |
404 — not found
Approval ID doesn't exist, or it belongs to an agent in a different org. The body has no detail to avoid leaking cross-org information.
Example
curl --request GET \
--url "https://trycanopy.ai/api/approvals/550e8400-.../status" \
--header "Authorization: Bearer ak_live_xxxxxxxxxxxxxxxx"If you'd rather block until a decision arrives instead of polling, use
canopy.waitForApproval(approvalId)(TS) orcanopy.wait_for_approval(approval_id)(Py). Both poll this endpoint internally and throwCanopyApprovalTimeoutErrorif the timeout elapses (default 5 minutes).