Fax quotes API reference
Updated
2 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.
- A quote prices one exact document, identified by its sha256, to one destination.
- A cover sheet on a quote counts as a page and is billed as one.
- The price of a quote is the same at every quality level, from standard to ultra.
Operations
POST /v1/fax-quotesPrice an exact document to one destinationGET /v1/fax-quotes/{quote_id}Read a quote
Why does a send start with a quote?
Because the quote is what gets approved and what gets charged. POST /v1/fax-quotes takes a document and a destination and answers with the price before anything is sent. The send in the faxes group then names the quote and nothing else about the fax. Whatever the quote fixed is what goes out.
A quote costs nothing and sends nothing. An agent can quote, show the amount to a person and stop there.
What goes into a quote?
Two required fields. document_id names the document and to is the destination in E.164, for example +12025550123.
The optional fields shape the fax. from is a number you own. Leave it out and the fax goes out from the shared pool. cover adds a cover sheet with to_name, from_name, subject and message. sender_name is the name that identifies the sender, and the carrier gets it as the caller name for its header line. delete_after_send deletes the document and the transmitted copy the moment the fax ends in delivered, partial or failed.
quality sets the resolution. The schema lists four words. standard is the fax standard's 204 by 98 dpi. fine is 204 by 196 and the default. superfine and ultra are finer still. The send guide has the measurement behind the last two and which one suits small print.
What does the answer fix?
The route and its label, document_pages, cover_pages and billable_pages, the amount in amount_micro with the currency, and per_page_micro. price_version names the rate table the price came from. document_sha256 is the hash of the document at the moment of the quote.
Two fields tell an agent what comes next. authorization_required is true when a live send of this quote needs a person's approval, because no policy allows it. warnings lists the service's warnings for this quote.
A destination outside the published routes is refused. The quote does not exist then, and neither can a send.
How long is a quote good for?
Until expires_at. GET /v1/fax-quotes/{quote_id} reads a quote again, and expired says whether its time has passed. An expired quote cannot be sent. Quote again, and if a person had approved the old one, ask again too: an approval is bound to its quote and expires with it. The limits page has the life of a quote as a value.
A quote is used once. After a send, consumed_by_job_id names the fax that used it. A second send needs a second quote, even for the same document and number.
What can change between the quote and the send?
Nothing that matters. The document is immutable, so the hash on the quote is the hash that is sent. The price comes from the quote, not from the rate table of a later minute.
That is the reason the API splits one action in two. The approval request in the approvals group copies the quote. A person who approves sees the same pages, number and amount that the send will use.
Which scope does a quote need?
fax:quote, for the create and the read. The default API key carries it. A key that may quote and may not send lets an agent prepare a fax and leave the sending to someone else.
Each operation in detail
POST /v1/fax-quotes
Price an exact document to one destination
Credential: an API key or a signed-in session. Scope: fax:quote.
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 |
|---|---|---|---|
cover | object or null | no | Cover sheet fields: to_name, from_name, subject, message. Counts as a page. |
delete_after_send | boolean | no | Delete the document and the transmitted copy the moment the fax ends in delivered, partial or failed. The job, its receipt and the carrier evidence stay; they hold no document content. A fax that ends unknown keeps the document until a reconcile settles it. Default: keep the document for the retention period. |
document_id | string | yes | |
from | string or null | no | A number you own; omit for the shared pool. |
quality | string (standard, fine, superfine, ultra) | no | Fax resolution. standard is the fax standard's 204 by 98 dpi, fine (the default) 204 by 196, superfine 204 by 392. ultra asks the carrier for its darkest text processing at the same superfine resolution and takes longer to process: measured 2026-11-09, a page sent at ultra and one at superfine both arrived as 1728 by 4112 pixels, 204 by 391 dpi. The price does not change. The job echoes the level. |
sender_name | string or null | no | The name that identifies the sender. The carrier gets it as the caller name for its header line. A fax without a cover sheet prints it in one line at the top of page one. The line also gives the sending number and the time in UTC. Letters, digits, spaces and - _ ~ ! . + only, at most 128 characters. Omit to use the organization's name. |
to | string | yes | Destination in E.164, for example +12025550123. |
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 |
|---|---|---|---|
amount_micro | integer | yes | |
authorization_required | boolean | yes | |
billable_pages | integer | yes | |
consumed_by_job_id | string or null | yes | |
cover | object or null | yes | |
cover_pages | integer | yes | |
created_at | string | yes | |
currency | string | yes | |
delete_after_send | boolean | no | |
document_id | string | yes | |
document_pages | integer | yes | |
document_sha256 | string | yes | |
environment | string (live, test) | yes | |
expired | boolean | yes | |
expires_at | string | yes | |
from | string or null | no | |
id | string | yes | |
per_page_micro | integer | no | |
price_version | string | yes | |
quality | string | no | |
route | string | yes | |
route_label | string | no | |
sender_name | string or null | no | |
to | string | yes | |
warnings | array of object | yes |
Example
curl https://api.faxforagents.com/v1/fax-quotes \
-X POST \
-H "Authorization: Bearer ffa_test_..." \
-H "Content-Type: application/json" \
-d '{"document_id":"document_example","to":"+15550000001"}'
GET /v1/fax-quotes/{quote_id}
Read a quote
Credential: an API key or a signed-in session. Scope: fax:quote.
Parameters
| Name | In | Type | Required | Notes |
|---|---|---|---|---|
quote_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 |
|---|---|---|---|
amount_micro | integer | yes | |
authorization_required | boolean | yes | |
billable_pages | integer | yes | |
consumed_by_job_id | string or null | yes | |
cover | object or null | yes | |
cover_pages | integer | yes | |
created_at | string | yes | |
currency | string | yes | |
delete_after_send | boolean | no | |
document_id | string | yes | |
document_pages | integer | yes | |
document_sha256 | string | yes | |
environment | string (live, test) | yes | |
expired | boolean | yes | |
expires_at | string | yes | |
from | string or null | no | |
id | string | yes | |
per_page_micro | integer | no | |
price_version | string | yes | |
quality | string | no | |
route | string | yes | |
route_label | string | no | |
sender_name | string or null | no | |
to | string | yes | |
warnings | array of object | yes |
Example
curl https://api.faxforagents.com/v1/fax-quotes/QUOTE_ID \
-H "Authorization: Bearer ffa_test_..."