OAuth consent API reference
Updated
5 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.
- Allowing an authorization mints the authorization code and returns where the browser goes next.
- Denying an authorization sends the app an access_denied answer.
- An OAuth access token works on the MCP server only, and the REST API answers it with 401.
Operations
GET /v1/oauth/authorizations/{authorization_id}The pending consent behind a consent URL: the app, the scopes and your organizationsPOST /v1/oauth/authorizations/{authorization_id}/approveAllow: mint the authorization code and return where the browser goes nextPOST /v1/oauth/authorizations/{authorization_id}/denyDeny: send the app an access_denied answerGET /v1/oauth/grantsYour connected apps in this organizationDELETE /v1/oauth/grants/{grant_id}Revoke a connected app
What is this group for?
For the consent screen. When an AI client connects to the MCP server with OAuth, it sends the person to a consent URL. The dashboard reads the pending authorization from this group, shows it, and posts the person's answer. The token endpoints of the OAuth flow are outside /v1 and are not part of this document.
What does the consent screen read?
GET /v1/oauth/authorizations/{authorization_id} returns the pending consent. client is the app that asks, and redirect_host is the host it will return to. The answer also has the scopes_requested, the person's organizations and the default environment. It expires at expires_at. The call takes a signed-in session.
How is the answer given?
POST /v1/oauth/authorizations/{authorization_id}/approve allows. The body names the org_id and the environment the app is connected to. It mints the authorization code and returns redirect_to, the address the browser opens next. auto_send is the consent screen's checkbox, for owners only.
POST /v1/oauth/authorizations/{authorization_id}/deny denies. The app gets an access_denied answer through the same redirect_to.
How are connected apps listed and revoked?
GET /v1/oauth/grants lists the connected apps of the organization. DELETE /v1/oauth/grants/{grant_id} revokes one, and that connection's tokens stop working. Both need key:admin, the scope that also guards API keys.
Revoking an app does not cancel a fax that is already queued. The OAuth guide walks through the screen a person sees.
Does an OAuth token work on this API?
No. An access token from the MCP sign-in works on the MCP server only. The REST API answers it with 401 invalid_token. A script that calls REST uses an API key from the identity group.
Each operation in detail
GET /v1/oauth/authorizations/{authorization_id}
The pending consent behind a consent URL: the app, the scopes and your organizations
Credential: a signed-in session.
Parameters
| Name | In | Type | Required | Notes |
|---|---|---|---|---|
authorization_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. |
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 |
|---|---|---|---|
client | object OAuthConsentClient | yes | |
default_environment | string (live, test) | yes | |
expires_at | string | yes | |
id | string | yes | |
organizations | array of object OAuthConsentOrganization | yes | |
redirect_host | string | yes | |
scopes_requested | array of string | yes |
Example
curl https://api.faxforagents.com/v1/oauth/authorizations/AUTHORIZATION_ID
POST /v1/oauth/authorizations/{authorization_id}/approve
Allow: mint the authorization code and return where the browser goes next
Credential: a signed-in session.
Parameters
| Name | In | Type | Required | Notes |
|---|---|---|---|---|
authorization_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 |
|---|---|---|---|
auto_send | boolean or null | no | The consent screen's checkbox, owners only: false turns the organization's auto-send setting off for this environment, true turns it on with its current limits. Omitted leaves it. |
environment | string (live, test) | no | |
org_id | 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. |
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 |
|---|---|---|---|
redirect_to | string | yes | Where the browser goes next: the client's registered redirect URI. |
Example
curl https://api.faxforagents.com/v1/oauth/authorizations/AUTHORIZATION_ID/approve \
-X POST \
-H "Content-Type: application/json" \
-d '{"org_id":"org_example"}'
POST /v1/oauth/authorizations/{authorization_id}/deny
Deny: send the app an access_denied answer
Credential: a signed-in session.
Parameters
| Name | In | Type | Required | Notes |
|---|---|---|---|---|
authorization_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. |
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 |
|---|---|---|---|
redirect_to | string | yes | Where the browser goes next: the client's registered redirect URI. |
Example
curl https://api.faxforagents.com/v1/oauth/authorizations/AUTHORIZATION_ID/deny \
-X POST
GET /v1/oauth/grants
Your connected apps in this organization
Credential: an API key or a signed-in session. Scope: key:admin.
Parameters
| Name | In | Type | Required | Notes |
|---|---|---|---|---|
cursor | query | string or null | no | |
limit | query | integer | no | Default 100. |
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 |
|---|---|---|---|
items | array of object Grant | yes | |
next_cursor | string or null | no |
Example
curl https://api.faxforagents.com/v1/oauth/grants \
-H "Authorization: Bearer ffa_test_..."
DELETE /v1/oauth/grants/{grant_id}
Revoke a connected app
Credential: an API key or a signed-in session. Scope: key:admin.
Parameters
| Name | In | Type | Required | Notes |
|---|---|---|---|---|
grant_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. |
Responses
| Status | Meaning |
|---|---|
204 | 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. |
Example
curl https://api.faxforagents.com/v1/oauth/grants/GRANT_ID \
-X DELETE \
-H "Authorization: Bearer ffa_test_..."