Approvals API reference
Updated
7 operations of the Fax for Agents API, from the OpenAPI document version 1.20.0, snapshot of 2026-11-13. The base URL is https://api.faxforagents.com/v1. This is one group of the full reference.
- Creating an approval request grants nothing until a person approves it.
- Approving needs approval:decide from a fresh session or an independent API credential.
- Only an approval that nobody has used yet can be revoked.
Operations
GET /v1/approval-requestsApproval requests, pending firstPOST /v1/approval-requestsAsk a human to approve a quoted send, or ask for help (grants nothing)GET /v1/approval-requests/{approval_id}Read one requestPOST /v1/approval-requests/{approval_id}/approveApprove the bound quote (approval:decide, fresh session or independent API credential)POST /v1/approval-requests/{approval_id}/rejectReject with a reasonPOST /v1/approvals/{approval_id}/revokeRevoke an approval nobody has used yetGET /v1/integration-reviews/{org_id}/{environment}/{operation_id}/{binding_id}Get Integration Review
What is an approval request?
An approval request asks a person to say yes to one send. The agent names a quote, and the server copies what the quote fixes into the request. That is the document and its hash, the destination, the sender and the amount. The answer returns that copy under bound. The request expires with the quote.
The summary of the create operation ends with "grants nothing". A pending request cannot send a fax. Only an approved one can, once, for the quote it was made from.
How does an agent ask?
POST /v1/approval-requests with a quote_id opens a request of kind send. It needs approval:request, which agent keys carry. The answer has the id, the status, the kind and who asked.
The same operation opens a request of kind help. The body then carries a message and can name a fax_job_id. The schema says the message is shown as data: a person reads it, and the server never acts on it.
Who can approve or reject?
POST /v1/approval-requests/{approval_id}/approve and /reject need approval:decide. The summary of the approve operation names the two ways to hold it. One is a fresh session, which means a person who signed in or proved it again a short time ago. The other is an independent API credential, which means a different API key from the one that asked. An agent key is never issued the scope.
Both take a reason. Rejecting records why, and the requester can read it. The approvals guide has the codes a later send can be refused with.
How does the agent learn the decision?
GET /v1/approval-requests/{approval_id} returns the request with its status, decided_at, decided_by and the reason. An approved request is what POST /v1/faxes takes as approval_id. After the send, consumed_by_job_id names the fax that used it.
GET /v1/approval-requests lists requests with the pending ones first. It filters by status and pages with cursor and limit. Both reads need approval:read.
Can an approval be taken back?
POST /v1/approvals/{approval_id}/revoke withdraws an approval that nobody has used yet. It needs approval:decide, like the decision itself. After a revoke the agent has to quote and ask again. An approval a fax has consumed cannot be revoked. Cancel the fax in the faxes group when it has not ended.
What is the integration review read?
GET /v1/integration-reviews/{org_id}/{environment}/{operation_id}/{binding_id} returns the approval request that one review binding names, in the same shape as the other reads. It takes a signed-in session only, with approval:read. The organization and the environment in the path have to be the ones the session is looking at. An API key is refused.
What does a send need besides an approval?
Nothing more from this group. A live send needs either an approved request or a delegated policy that allows it. Test keys send in the sandbox without either. The approval is checked again at the send. A changed document, destination, sender or amount no longer matches what was approved, and the send is refused.
Each operation in detail
GET /v1/approval-requests
Approval requests, pending first
Credential: an API key or a signed-in session. Scope: approval:read.
Parameters
| Name | In | Type | Required | Notes |
|---|---|---|---|---|
status | query | string or null | no | |
cursor | query | string or null | no | |
limit | query | integer | no | Default 50. |
Responses
| Status | Meaning |
|---|---|
200 | Successful Response |
401 | No credential, or one that was not accepted: invalid_token for an API key, unauthenticated where a signed-in session is needed. error.details.reason says why a key was refused. |
403 | The credential is valid and is not allowed to do this. scope_missing puts the scope in error.details.scope. Other codes are agent_forbidden and approval_required. A session can also meet csrf_invalid and reauth_required. |
422 | A field failed validation: invalid_request, with one entry per field in error.details, or a code that names the rule. |
429 | rate_limited. Retry-After and the RateLimit-* headers say when to try again. |
Response fields
| Field | Type | Required | Description |
|---|---|---|---|
items | array of object ApprovalRequest | yes | |
next_cursor | string or null | no |
Example
curl https://api.faxforagents.com/v1/approval-requests \
-H "Authorization: Bearer ffa_test_..."
POST /v1/approval-requests
Ask a human to approve a quoted send, or ask for help (grants nothing)
Credential: an API key or a signed-in session. Scope: approval:request.
Parameters
| Name | In | Type | Required | Notes |
|---|---|---|---|---|
Idempotency-Key | header | string | no | Replay the first successful response for the same request within 24 hours. Reusing the idempotency header with a different request returns 409 idempotency_key_conflict. Responses include Idempotent-Replayed: true on replay. |
Request body application/json, required
| Field | Type | Required | Description |
|---|---|---|---|
fax_job_id | string or null | no | |
kind | string (send, help) | no | |
message | string or null | no | What the person should know (kind help). Shown as data. |
quote_id | string or null | no | The quote to bind (kind send). |
Responses
| Status | Meaning |
|---|---|
201 | Successful Response |
401 | No credential, or one that was not accepted: invalid_token for an API key, unauthenticated where a signed-in session is needed. error.details.reason says why a key was refused. |
403 | The credential is valid and is not allowed to do this. scope_missing puts the scope in error.details.scope. Other codes are agent_forbidden and approval_required. A session can also meet csrf_invalid and reauth_required. |
404 | not_found: no such resource for this credential. A resource of another organization answers the same. |
409 | The resource is in a state that refuses the call, or the Idempotency-Key was used with a different request (idempotency_key_conflict). error.code names the state. |
422 | A field failed validation: invalid_request, with one entry per field in error.details, or a code that names the rule. |
429 | rate_limited. Retry-After and the RateLimit-* headers say when to try again. |
Response fields
| Field | Type | Required | Description |
|---|---|---|---|
bound | object | yes | |
consumed_by_job_id | string or null | yes | |
created_at | string | yes | |
decided_at | string or null | yes | |
decided_by | string or null | yes | |
expires_at | string or null | yes | |
id | string | yes | |
kind | string (send, help) | yes | |
message | string or null | yes | |
notified | boolean or null | no | On creation: whether the organization was mailed. false when the request repeats a pending one or the organization's daily cap of request mails is reached; the request is still shown in the dashboard. |
quote_id | string or null | yes | |
reason | string or null | yes | |
requested_by | string | yes | |
status | string (pending, approved, rejected, revoked, expired) | yes |
Example
curl https://api.faxforagents.com/v1/approval-requests \
-X POST \
-H "Authorization: Bearer ffa_test_..." \
-H "Content-Type: application/json" \
-d '{}'
GET /v1/approval-requests/{approval_id}
Read one request
Credential: an API key or a signed-in session. Scope: approval:read.
Parameters
| Name | In | Type | Required | Notes |
|---|---|---|---|---|
approval_id | path | string | yes |
Responses
| Status | Meaning |
|---|---|
200 | Successful Response |
401 | No credential, or one that was not accepted: invalid_token for an API key, unauthenticated where a signed-in session is needed. error.details.reason says why a key was refused. |
403 | The credential is valid and is not allowed to do this. scope_missing puts the scope in error.details.scope. Other codes are agent_forbidden and approval_required. A session can also meet csrf_invalid and reauth_required. |
404 | not_found: no such resource for this credential. A resource of another organization answers the same. |
422 | A field failed validation: invalid_request, with one entry per field in error.details, or a code that names the rule. |
429 | rate_limited. Retry-After and the RateLimit-* headers say when to try again. |
Response fields
| Field | Type | Required | Description |
|---|---|---|---|
bound | object | yes | |
consumed_by_job_id | string or null | yes | |
created_at | string | yes | |
decided_at | string or null | yes | |
decided_by | string or null | yes | |
expires_at | string or null | yes | |
id | string | yes | |
kind | string (send, help) | yes | |
message | string or null | yes | |
notified | boolean or null | no | On creation: whether the organization was mailed. false when the request repeats a pending one or the organization's daily cap of request mails is reached; the request is still shown in the dashboard. |
quote_id | string or null | yes | |
reason | string or null | yes | |
requested_by | string | yes | |
status | string (pending, approved, rejected, revoked, expired) | yes |
Example
curl https://api.faxforagents.com/v1/approval-requests/APPROVAL_ID \
-H "Authorization: Bearer ffa_test_..."
POST /v1/approval-requests/{approval_id}/approve
Approve the bound quote (approval:decide, fresh session or independent API credential)
Credential: an API key or a signed-in session. Scope: approval:decide.
Parameters
| Name | In | Type | Required | Notes |
|---|---|---|---|---|
approval_id | path | string | yes | |
Idempotency-Key | header | string | no | Replay the first successful response for the same request within 24 hours. Reusing the idempotency header with a different request returns 409 idempotency_key_conflict. Responses include Idempotent-Replayed: true on replay. |
Request body application/json, required
| Field | Type | Required | Description |
|---|---|---|---|
reason | string or null | no |
Responses
| Status | Meaning |
|---|---|
200 | Successful Response |
401 | No credential, or one that was not accepted: invalid_token for an API key, unauthenticated where a signed-in session is needed. error.details.reason says why a key was refused. |
403 | The credential is valid and is not allowed to do this. scope_missing puts the scope in error.details.scope. Other codes are agent_forbidden and approval_required. A session can also meet csrf_invalid and reauth_required. |
404 | not_found: no such resource for this credential. A resource of another organization answers the same. |
409 | The resource is in a state that refuses the call, or the Idempotency-Key was used with a different request (idempotency_key_conflict). error.code names the state. |
422 | A field failed validation: invalid_request, with one entry per field in error.details, or a code that names the rule. |
429 | rate_limited. Retry-After and the RateLimit-* headers say when to try again. |
Response fields
| Field | Type | Required | Description |
|---|---|---|---|
bound | object | yes | |
consumed_by_job_id | string or null | yes | |
created_at | string | yes | |
decided_at | string or null | yes | |
decided_by | string or null | yes | |
expires_at | string or null | yes | |
id | string | yes | |
kind | string (send, help) | yes | |
message | string or null | yes | |
notified | boolean or null | no | On creation: whether the organization was mailed. false when the request repeats a pending one or the organization's daily cap of request mails is reached; the request is still shown in the dashboard. |
quote_id | string or null | yes | |
reason | string or null | yes | |
requested_by | string | yes | |
status | string (pending, approved, rejected, revoked, expired) | yes |
Example
curl https://api.faxforagents.com/v1/approval-requests/APPROVAL_ID/approve \
-X POST \
-H "Authorization: Bearer ffa_test_..." \
-H "Content-Type: application/json" \
-d '{}'
POST /v1/approval-requests/{approval_id}/reject
Reject with a reason
Credential: an API key or a signed-in session. Scope: approval:decide.
Parameters
| Name | In | Type | Required | Notes |
|---|---|---|---|---|
approval_id | path | string | yes | |
Idempotency-Key | header | string | no | Replay the first successful response for the same request within 24 hours. Reusing the idempotency header with a different request returns 409 idempotency_key_conflict. Responses include Idempotent-Replayed: true on replay. |
Request body application/json, required
| Field | Type | Required | Description |
|---|---|---|---|
reason | string or null | no |
Responses
| Status | Meaning |
|---|---|
200 | Successful Response |
401 | No credential, or one that was not accepted: invalid_token for an API key, unauthenticated where a signed-in session is needed. error.details.reason says why a key was refused. |
403 | The credential is valid and is not allowed to do this. scope_missing puts the scope in error.details.scope. Other codes are agent_forbidden and approval_required. A session can also meet csrf_invalid and reauth_required. |
404 | not_found: no such resource for this credential. A resource of another organization answers the same. |
409 | The resource is in a state that refuses the call, or the Idempotency-Key was used with a different request (idempotency_key_conflict). error.code names the state. |
422 | A field failed validation: invalid_request, with one entry per field in error.details, or a code that names the rule. |
429 | rate_limited. Retry-After and the RateLimit-* headers say when to try again. |
Response fields
| Field | Type | Required | Description |
|---|---|---|---|
bound | object | yes | |
consumed_by_job_id | string or null | yes | |
created_at | string | yes | |
decided_at | string or null | yes | |
decided_by | string or null | yes | |
expires_at | string or null | yes | |
id | string | yes | |
kind | string (send, help) | yes | |
message | string or null | yes | |
notified | boolean or null | no | On creation: whether the organization was mailed. false when the request repeats a pending one or the organization's daily cap of request mails is reached; the request is still shown in the dashboard. |
quote_id | string or null | yes | |
reason | string or null | yes | |
requested_by | string | yes | |
status | string (pending, approved, rejected, revoked, expired) | yes |
Example
curl https://api.faxforagents.com/v1/approval-requests/APPROVAL_ID/reject \
-X POST \
-H "Authorization: Bearer ffa_test_..." \
-H "Content-Type: application/json" \
-d '{}'
POST /v1/approvals/{approval_id}/revoke
Revoke an approval nobody has used yet
Credential: an API key or a signed-in session. Scope: approval:decide.
Parameters
| Name | In | Type | Required | Notes |
|---|---|---|---|---|
approval_id | path | string | yes | |
Idempotency-Key | header | string | no | Replay the first successful response for the same request within 24 hours. Reusing the idempotency header with a different request returns 409 idempotency_key_conflict. Responses include Idempotent-Replayed: true on replay. |
Request body application/json, required
| Field | Type | Required | Description |
|---|---|---|---|
reason | string or null | no |
Responses
| Status | Meaning |
|---|---|
200 | Successful Response |
401 | No credential, or one that was not accepted: invalid_token for an API key, unauthenticated where a signed-in session is needed. error.details.reason says why a key was refused. |
403 | The credential is valid and is not allowed to do this. scope_missing puts the scope in error.details.scope. Other codes are agent_forbidden and approval_required. A session can also meet csrf_invalid and reauth_required. |
404 | not_found: no such resource for this credential. A resource of another organization answers the same. |
409 | The resource is in a state that refuses the call, or the Idempotency-Key was used with a different request (idempotency_key_conflict). error.code names the state. |
422 | A field failed validation: invalid_request, with one entry per field in error.details, or a code that names the rule. |
429 | rate_limited. Retry-After and the RateLimit-* headers say when to try again. |
Response fields
| Field | Type | Required | Description |
|---|---|---|---|
bound | object | yes | |
consumed_by_job_id | string or null | yes | |
created_at | string | yes | |
decided_at | string or null | yes | |
decided_by | string or null | yes | |
expires_at | string or null | yes | |
id | string | yes | |
kind | string (send, help) | yes | |
message | string or null | yes | |
notified | boolean or null | no | On creation: whether the organization was mailed. false when the request repeats a pending one or the organization's daily cap of request mails is reached; the request is still shown in the dashboard. |
quote_id | string or null | yes | |
reason | string or null | yes | |
requested_by | string | yes | |
status | string (pending, approved, rejected, revoked, expired) | yes |
Example
curl https://api.faxforagents.com/v1/approvals/APPROVAL_ID/revoke \
-X POST \
-H "Authorization: Bearer ffa_test_..." \
-H "Content-Type: application/json" \
-d '{}'
GET /v1/integration-reviews/{org_id}/{environment}/{operation_id}/{binding_id}
Get Integration Review
Credential: a signed-in session. Scope: approval:read.
Parameters
| Name | In | Type | Required | Notes |
|---|---|---|---|---|
org_id | path | string | yes | |
environment | path | string | yes | |
operation_id | path | string | yes | |
binding_id | path | string | yes |
Responses
| Status | Meaning |
|---|---|
200 | Successful Response |
401 | No credential, or one that was not accepted: invalid_token for an API key, unauthenticated where a signed-in session is needed. error.details.reason says why a key was refused. |
403 | The credential is valid and is not allowed to do this. scope_missing puts the scope in error.details.scope. Other codes are agent_forbidden and approval_required. A session can also meet csrf_invalid and reauth_required. |
404 | not_found: no such resource for this credential. A resource of another organization answers the same. |
422 | A field failed validation: invalid_request, with one entry per field in error.details, or a code that names the rule. |
429 | rate_limited. Retry-After and the RateLimit-* headers say when to try again. |
Response fields
| Field | Type | Required | Description |
|---|---|---|---|
bound | object | yes | |
consumed_by_job_id | string or null | yes | |
created_at | string | yes | |
decided_at | string or null | yes | |
decided_by | string or null | yes | |
expires_at | string or null | yes | |
id | string | yes | |
kind | string (send, help) | yes | |
message | string or null | yes | |
notified | boolean or null | no | On creation: whether the organization was mailed. false when the request repeats a pending one or the organization's daily cap of request mails is reached; the request is still shown in the dashboard. |
quote_id | string or null | yes | |
reason | string or null | yes | |
requested_by | string | yes | |
status | string (pending, approved, rejected, revoked, expired) | yes |
Example
curl https://api.faxforagents.com/v1/integration-reviews/ORG_ID/ENVIRONMENT/OPERATION_ID/BINDING_ID