Billing API reference

Updated

22 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 top-up session funds the live wallet with whole US dollars, 10 to 1000 per session.
  • Auto top-up takes a threshold, an amount and a daily cap, and the card is saved at the first payment.
  • The CSV of a usage export is read from a signed URL that takes no API key.

Operations

How is money represented in the billing group?

As integers. Every amount is in micro-units of a US dollar, in fields that end in _micro. One dollar is 1000000. No field is a decimal number, so a client never rounds. The one exception in a request is amount_usd on a top-up session, which takes whole dollars.

The wallet is prepaid. GET /v1/balance returns two figures for the environment of the credential. available_micro is what a new send can use. held_micro is what queued and active faxes have reserved and not yet captured or released.

How do I fund the wallet?

POST /v1/topup-sessions opens a hosted Checkout page and returns its url. The amount is whole US dollars, 10 to 1000 per session, and it funds the live wallet. A person pays on that page. GET /v1/topup-sessions/{topup_session_id} reads the session with its status, and the list returns sessions newest first.

Auto top-up repeats that without a person. POST /v1/auto-topups takes three amounts. threshold_micro is the available balance below which a top-up starts. amount_micro is how much each one adds. daily_cap_micro is the most that can be added in one UTC day. The card is saved at the first payment, and the answer carries a setup_url for it. DELETE /v1/auto-topups/{auto_topup_id} turns it off.

What is a budget?

A budget is a spending cap. POST /v1/budgets creates a daily or monthly cap for the organization, a project or an agent. The answer shows limit_micro, spent_micro, remaining_micro and resets_at. PATCH /v1/budgets/{budget_id} changes the limit or the status. GET /v1/budgets lists the caps of the environment.

A budget is not a delegated policy. A policy decides whether a send needs a person. A budget stops spending once the cap is reached, whoever allowed the send.

Where are invoices, the ledger and the subscription?

GET /v1/ledger returns the wallet's transactions, newest first, a page at a time. GET /v1/invoices returns the payment provider's invoices and receipts with hosted links, and one invoice can be read by id.

POST /v1/billing-portal-sessions opens the customer portal for cards, invoices and the subscription. GET /v1/subscriptions returns subscriptions and the workspace entitlement. POST /v1/subscriptions/checkout opens a hosted Checkout for the Agent workspace subscription.

GET /v1/billing-settings and its PATCH hold the billing email and the low-balance threshold.

How do I read and export usage?

GET /v1/usage returns rollups between from and to. group_by chooses the grouping, by day, direction, destination or project, and project_id narrows it to one project. The answer has the items and the totals.

POST /v1/usage-exports writes the same data as CSV. Without dates it covers the last 30 days to today. The answer has a signed url. GET /v1/usage-exports/{export_id} returns a fresh link when the first has expired. The content route itself takes the signature in the address and no API key.

Which scopes and errors belong to billing?

Reads need billing:read. Everything that moves money or changes a setting needs billing:write. An agent key is never issued billing:write, so an agent cannot fund the wallet or raise its own cap.

Three statuses appear here more than elsewhere. 402 answers a call the wallet or the payment cannot cover. 409 answers a change that the state forbids. 503 answers while the payment provider is not available.

Each operation in detail

GET /v1/auto-topups

Auto top-up settings

Credential: an API key or a signed-in session. Scope: billing:read.

Responses

GET /v1/auto-topups responses
StatusMeaning
200Successful Response
401No 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.
403The 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.
429rate_limited. Retry-After and the RateLimit-* headers say when to try again.

Response fields

GET /v1/auto-topups response fields
FieldTypeRequiredDescription
itemsarray of object AutoTopupyes

Example

curl https://api.faxforagents.com/v1/auto-topups \
  -H "Authorization: Bearer ffa_test_..."

POST /v1/auto-topups

Opt in to auto top-up (threshold, amount, daily cap); the card is saved at the first payment

Credential: an API key or a signed-in session. Scope: billing:write.

Parameters

POST /v1/auto-topups parameters
NameInTypeRequiredNotes
Idempotency-KeyheaderstringnoReplay 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

POST /v1/auto-topups request body
FieldTypeRequiredDescription
amount_microintegeryesWhole dollars, 10 to 1000 USD.
daily_cap_microintegeryesNever more than this per UTC day.
threshold_microintegeryesTop up when the available balance drops below this.

Responses

POST /v1/auto-topups responses
StatusMeaning
201Successful Response
401No 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.
402The prepaid balance does not cover the call: insufficient_balance.
403The 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.
404not_found: no such resource for this credential. A resource of another organization answers the same.
409The 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.
422A field failed validation: invalid_request, with one entry per field in error.details, or a code that names the rule.
429rate_limited. Retry-After and the RateLimit-* headers say when to try again.
503Something this call depends on is not available or not set up here, for example billing_unavailable or provider_unavailable. error.retryable says whether to send the same call again.

Response fields

POST /v1/auto-topups response fields
FieldTypeRequiredDescription
amount_microintegeryes
created_atstringyes
daily_cap_microintegeryes
disabled_atstring or nullyes
environmentstring (live, test)yes
idstringyes
last_attempt_atstring or nullyes
payment_method_savedbooleanyes
setup_session_idstring or nullyes
setup_urlstring or nullnoWhere to save the card while status is pending_setup.
statusstring (pending_setup, active, disabled)yes
threshold_microintegeryes
updated_atstringyes

Example

curl https://api.faxforagents.com/v1/auto-topups \
  -X POST \
  -H "Authorization: Bearer ffa_test_..." \
  -H "Content-Type: application/json" \
  -d '{"threshold_micro":0,"amount_micro":10000000,"daily_cap_micro":10000000}'

DELETE /v1/auto-topups/{auto_topup_id}

Turn auto top-up off

Credential: an API key or a signed-in session. Scope: billing:write.

Parameters

DELETE /v1/auto-topups/{auto_topup_id} parameters
NameInTypeRequiredNotes
auto_topup_idpathstringyes
Idempotency-KeyheaderstringnoReplay 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

DELETE /v1/auto-topups/{auto_topup_id} responses
StatusMeaning
200Successful Response
401No 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.
403The 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.
404not_found: no such resource for this credential. A resource of another organization answers the same.
409The 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.
422A field failed validation: invalid_request, with one entry per field in error.details, or a code that names the rule.
429rate_limited. Retry-After and the RateLimit-* headers say when to try again.

Response fields

DELETE /v1/auto-topups/{auto_topup_id} response fields
FieldTypeRequiredDescription
deletedbooleanno
idstringyes

Example

curl https://api.faxforagents.com/v1/auto-topups/AUTO_TOPUP_ID \
  -X DELETE \
  -H "Authorization: Bearer ffa_test_..."

GET /v1/balance

Available and held balance

Credential: an API key or a signed-in session. Scope: billing:read.

Responses

GET /v1/balance responses
StatusMeaning
200Successful Response
401No 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.
403The 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.
429rate_limited. Retry-After and the RateLimit-* headers say when to try again.

Response fields

GET /v1/balance response fields
FieldTypeRequiredDescription
available_microintegeryes
currencystringyes
environmentstring (live, test)yes
held_microintegeryes
top_up_urlstring or nullnoThe dashboard page where a person adds funds to the wallet. A key cannot top up.

Example

curl https://api.faxforagents.com/v1/balance \
  -H "Authorization: Bearer ffa_test_..."

POST /v1/billing-portal-sessions

Open the Stripe customer portal (cards, invoices, the subscription)

Credential: an API key or a signed-in session. Scope: billing:write.

Parameters

POST /v1/billing-portal-sessions parameters
NameInTypeRequiredNotes
Idempotency-KeyheaderstringnoReplay 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

POST /v1/billing-portal-sessions responses
StatusMeaning
201Successful Response
401No 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.
402The prepaid balance does not cover the call: insufficient_balance.
403The 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.
404not_found: no such resource for this credential. A resource of another organization answers the same.
409The 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.
422A field failed validation: invalid_request, with one entry per field in error.details, or a code that names the rule.
429rate_limited. Retry-After and the RateLimit-* headers say when to try again.
503Something this call depends on is not available or not set up here, for example billing_unavailable or provider_unavailable. error.retryable says whether to send the same call again.

Response fields

POST /v1/billing-portal-sessions response fields
FieldTypeRequiredDescription
expires_atstringyes
urlstringyes

Example

curl https://api.faxforagents.com/v1/billing-portal-sessions \
  -X POST \
  -H "Authorization: Bearer ffa_test_..."

GET /v1/billing-settings

Billing settings of the organization

Credential: an API key or a signed-in session. Scope: billing:read.

Responses

GET /v1/billing-settings responses
StatusMeaning
200Successful Response
401No 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.
403The 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.
404not_found: no such resource for this credential. A resource of another organization answers the same.
429rate_limited. Retry-After and the RateLimit-* headers say when to try again.

Response fields

GET /v1/billing-settings response fields
FieldTypeRequiredDescription
billing_emailstring or nullyes
disputedbooleanyes
low_balance_activebooleanyes
low_balance_threshold_microintegeryes
org_idstringyes
stripe_customerbooleanyes
workspacebooleanyes

Example

curl https://api.faxforagents.com/v1/billing-settings \
  -H "Authorization: Bearer ffa_test_..."

PATCH /v1/billing-settings

Change the billing email or the low-balance threshold

Credential: an API key or a signed-in session. Scope: billing:write.

Parameters

PATCH /v1/billing-settings parameters
NameInTypeRequiredNotes
Idempotency-KeyheaderstringnoReplay 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

PATCH /v1/billing-settings request body
FieldTypeRequiredDescription
billing_emailstring (email) or nullno
low_balance_threshold_microinteger or nullno

Responses

PATCH /v1/billing-settings responses
StatusMeaning
200Successful Response
401No 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.
403The 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.
404not_found: no such resource for this credential. A resource of another organization answers the same.
409The 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.
422A field failed validation: invalid_request, with one entry per field in error.details, or a code that names the rule.
429rate_limited. Retry-After and the RateLimit-* headers say when to try again.

Response fields

PATCH /v1/billing-settings response fields
FieldTypeRequiredDescription
billing_emailstring or nullyes
disputedbooleanyes
low_balance_activebooleanyes
low_balance_threshold_microintegeryes
org_idstringyes
stripe_customerbooleanyes
workspacebooleanyes

Example

curl https://api.faxforagents.com/v1/billing-settings \
  -X PATCH \
  -H "Authorization: Bearer ffa_test_..." \
  -H "Content-Type: application/json" \
  -d '{}'

GET /v1/budgets

Spending caps of this environment

Credential: an API key or a signed-in session. Scope: billing:read.

Responses

GET /v1/budgets responses
StatusMeaning
200Successful Response
401No 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.
403The 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.
429rate_limited. Retry-After and the RateLimit-* headers say when to try again.

Response fields

GET /v1/budgets response fields
FieldTypeRequiredDescription
itemsarray of object Budgetyes

Example

curl https://api.faxforagents.com/v1/budgets \
  -H "Authorization: Bearer ffa_test_..."

POST /v1/budgets

Create a daily or monthly cap for the organization, a project or an agent

Credential: an API key or a signed-in session. Scope: billing:write.

Parameters

POST /v1/budgets parameters
NameInTypeRequiredNotes
Idempotency-KeyheaderstringnoReplay 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

POST /v1/budgets request body
FieldTypeRequiredDescription
agent_idstring or nullno
limit_microintegeryes
periodstring (daily, monthly)yes
project_idstring or nullno
scopestring (organization, project, agent)no

Responses

POST /v1/budgets responses
StatusMeaning
201Successful Response
401No 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.
403The 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.
404not_found: no such resource for this credential. A resource of another organization answers the same.
409The 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.
422A field failed validation: invalid_request, with one entry per field in error.details, or a code that names the rule.
429rate_limited. Retry-After and the RateLimit-* headers say when to try again.

Response fields

POST /v1/budgets response fields
FieldTypeRequiredDescription
agent_idstring or nullyes
created_atstringyes
environmentstring (live, test)yes
idstringyes
limit_microintegeryes
periodstring (daily, monthly)yes
project_idstring or nullyes
remaining_microintegeryes
resets_atstringyes
scopestring (organization, project, agent)yes
spent_microintegeryes
statusstring (active, disabled)yes
updated_atstringyes

Example

curl https://api.faxforagents.com/v1/budgets \
  -X POST \
  -H "Authorization: Bearer ffa_test_..." \
  -H "Content-Type: application/json" \
  -d '{"period":"daily","limit_micro":0}'

PATCH /v1/budgets/{budget_id}

Change a cap's limit or status

Credential: an API key or a signed-in session. Scope: billing:write.

Parameters

PATCH /v1/budgets/{budget_id} parameters
NameInTypeRequiredNotes
budget_idpathstringyes
Idempotency-KeyheaderstringnoReplay 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

PATCH /v1/budgets/{budget_id} request body
FieldTypeRequiredDescription
limit_microinteger or nullno
statusstring (active, disabled) or nullno

Responses

PATCH /v1/budgets/{budget_id} responses
StatusMeaning
200Successful Response
401No 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.
403The 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.
404not_found: no such resource for this credential. A resource of another organization answers the same.
409The 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.
422A field failed validation: invalid_request, with one entry per field in error.details, or a code that names the rule.
429rate_limited. Retry-After and the RateLimit-* headers say when to try again.

Response fields

PATCH /v1/budgets/{budget_id} response fields
FieldTypeRequiredDescription
agent_idstring or nullyes
created_atstringyes
environmentstring (live, test)yes
idstringyes
limit_microintegeryes
periodstring (daily, monthly)yes
project_idstring or nullyes
remaining_microintegeryes
resets_atstringyes
scopestring (organization, project, agent)yes
spent_microintegeryes
statusstring (active, disabled)yes
updated_atstringyes

Example

curl https://api.faxforagents.com/v1/budgets/BUDGET_ID \
  -X PATCH \
  -H "Authorization: Bearer ffa_test_..." \
  -H "Content-Type: application/json" \
  -d '{}'

GET /v1/invoices

Stripe invoices and receipts (hosted links)

Credential: an API key or a signed-in session. Scope: billing:read.

Parameters

GET /v1/invoices parameters
NameInTypeRequiredNotes
cursorquerystring or nullno
limitqueryintegerno Default 20.

Responses

GET /v1/invoices responses
StatusMeaning
200Successful Response
401No 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.
403The 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.
404not_found: no such resource for this credential. A resource of another organization answers the same.
422A field failed validation: invalid_request, with one entry per field in error.details, or a code that names the rule.
429rate_limited. Retry-After and the RateLimit-* headers say when to try again.
503Something this call depends on is not available or not set up here, for example billing_unavailable or provider_unavailable. error.retryable says whether to send the same call again.

Response fields

GET /v1/invoices response fields
FieldTypeRequiredDescription
itemsarray of object Invoiceyes
next_cursorstring or nullno

Example

curl https://api.faxforagents.com/v1/invoices \
  -H "Authorization: Bearer ffa_test_..."

GET /v1/invoices/{invoice_id}

One Stripe invoice

Credential: an API key or a signed-in session. Scope: billing:read.

Parameters

GET /v1/invoices/{invoice_id} parameters
NameInTypeRequiredNotes
invoice_idpathstringyes

Responses

GET /v1/invoices/{invoice_id} responses
StatusMeaning
200Successful Response
401No 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.
403The 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.
404not_found: no such resource for this credential. A resource of another organization answers the same.
422A field failed validation: invalid_request, with one entry per field in error.details, or a code that names the rule.
429rate_limited. Retry-After and the RateLimit-* headers say when to try again.
503Something this call depends on is not available or not set up here, for example billing_unavailable or provider_unavailable. error.retryable says whether to send the same call again.

Response fields

GET /v1/invoices/{invoice_id} response fields
FieldTypeRequiredDescription
amount_due_microintegeryes
amount_paid_microintegeryes
created_atstring or nullyes
currencystringyes
hosted_invoice_urlstring or nullyes
idstringyes
invoice_pdfstring or nullyes
numberstring or nullyes
statusstring or nullyes
subscription_idstring or nullyes

Example

curl https://api.faxforagents.com/v1/invoices/INVOICE_ID \
  -H "Authorization: Bearer ffa_test_..."

GET /v1/ledger

Wallet transactions, newest first

Credential: an API key or a signed-in session. Scope: billing:read.

Parameters

GET /v1/ledger parameters
NameInTypeRequiredNotes
cursorquerystring or nullno
limitqueryintegerno Default 50.

Responses

GET /v1/ledger responses
StatusMeaning
200Successful Response
401No 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.
403The 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.
422A field failed validation: invalid_request, with one entry per field in error.details, or a code that names the rule.
429rate_limited. Retry-After and the RateLimit-* headers say when to try again.

Response fields

GET /v1/ledger response fields
FieldTypeRequiredDescription
itemsarray of object LedgerEntryyes
next_cursorstring or nullno

Example

curl https://api.faxforagents.com/v1/ledger \
  -H "Authorization: Bearer ffa_test_..."

GET /v1/subscriptions

Subscriptions and the workspace entitlement

Credential: an API key or a signed-in session. Scope: billing:read.

Responses

GET /v1/subscriptions responses
StatusMeaning
200Successful Response
401No 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.
403The 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.
404not_found: no such resource for this credential. A resource of another organization answers the same.
429rate_limited. Retry-After and the RateLimit-* headers say when to try again.

Response fields

GET /v1/subscriptions response fields
FieldTypeRequiredDescription
itemsarray of object Subscriptionyes
next_cursorstring or nullno
workspacebooleanyes

Example

curl https://api.faxforagents.com/v1/subscriptions \
  -H "Authorization: Bearer ffa_test_..."

POST /v1/subscriptions/checkout

Open a hosted Checkout for the Agent workspace subscription

Credential: an API key or a signed-in session. Scope: billing:write.

Parameters

POST /v1/subscriptions/checkout parameters
NameInTypeRequiredNotes
Idempotency-KeyheaderstringnoReplay 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

POST /v1/subscriptions/checkout responses
StatusMeaning
201Successful Response
401No 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.
402The prepaid balance does not cover the call: insufficient_balance.
403The 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.
404not_found: no such resource for this credential. A resource of another organization answers the same.
409The 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.
422A field failed validation: invalid_request, with one entry per field in error.details, or a code that names the rule.
429rate_limited. Retry-After and the RateLimit-* headers say when to try again.
503Something this call depends on is not available or not set up here, for example billing_unavailable or provider_unavailable. error.retryable says whether to send the same call again.

Response fields

POST /v1/subscriptions/checkout response fields
FieldTypeRequiredDescription
productstringyes
stripe_session_idstringyes
urlstringyes

Example

curl https://api.faxforagents.com/v1/subscriptions/checkout \
  -X POST \
  -H "Authorization: Bearer ffa_test_..."

GET /v1/topup-sessions

Top-up sessions, newest first

Credential: an API key or a signed-in session. Scope: billing:read.

Parameters

GET /v1/topup-sessions parameters
NameInTypeRequiredNotes
cursorquerystring or nullno
limitqueryintegerno Default 50.

Responses

GET /v1/topup-sessions responses
StatusMeaning
200Successful Response
401No 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.
403The 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.
422A field failed validation: invalid_request, with one entry per field in error.details, or a code that names the rule.
429rate_limited. Retry-After and the RateLimit-* headers say when to try again.

Response fields

GET /v1/topup-sessions response fields
FieldTypeRequiredDescription
itemsarray of object TopupSessionyes
next_cursorstring or nullno

Example

curl https://api.faxforagents.com/v1/topup-sessions \
  -H "Authorization: Bearer ffa_test_..."

POST /v1/topup-sessions

Open a hosted Checkout to fund the live wallet (10 to 1000 USD)

Credential: an API key or a signed-in session. Scope: billing:write.

Parameters

POST /v1/topup-sessions parameters
NameInTypeRequiredNotes
Idempotency-KeyheaderstringnoReplay 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

POST /v1/topup-sessions request body
FieldTypeRequiredDescription
amount_usdintegeryesWhole US dollars, 10 to 1000 per session.

Responses

POST /v1/topup-sessions responses
StatusMeaning
201Successful Response
401No 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.
402The prepaid balance does not cover the call: insufficient_balance.
403The 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.
404not_found: no such resource for this credential. A resource of another organization answers the same.
409The 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.
422A field failed validation: invalid_request, with one entry per field in error.details, or a code that names the rule.
429rate_limited. Retry-After and the RateLimit-* headers say when to try again.
503Something this call depends on is not available or not set up here, for example billing_unavailable or provider_unavailable. error.retryable says whether to send the same call again.

Response fields

POST /v1/topup-sessions response fields
FieldTypeRequiredDescription
amount_microintegeryes
auto_topup_idstring or nullyes
completed_atstring or nullyes
created_atstringyes
currencystringyes
environmentstring (live, test)yes
errorstring or nullyes
expires_atstring or nullyes
idstringyes
kindstring (manual, auto, setup)yes
statusstring (open, completed, expired, canceled, failed)yes
stripe_payment_intent_idstring or nullyes
stripe_session_idstring or nullyes
urlstring or nullnoThe hosted Checkout page while the session is open.

Example

curl https://api.faxforagents.com/v1/topup-sessions \
  -X POST \
  -H "Authorization: Bearer ffa_test_..." \
  -H "Content-Type: application/json" \
  -d '{"amount_usd":10}'

GET /v1/topup-sessions/{topup_session_id}

Read a top-up session

Credential: an API key or a signed-in session. Scope: billing:read.

Parameters

GET /v1/topup-sessions/{topup_session_id} parameters
NameInTypeRequiredNotes
topup_session_idpathstringyes

Responses

GET /v1/topup-sessions/{topup_session_id} responses
StatusMeaning
200Successful Response
401No 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.
403The 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.
404not_found: no such resource for this credential. A resource of another organization answers the same.
422A field failed validation: invalid_request, with one entry per field in error.details, or a code that names the rule.
429rate_limited. Retry-After and the RateLimit-* headers say when to try again.

Response fields

GET /v1/topup-sessions/{topup_session_id} response fields
FieldTypeRequiredDescription
amount_microintegeryes
auto_topup_idstring or nullyes
completed_atstring or nullyes
created_atstringyes
currencystringyes
environmentstring (live, test)yes
errorstring or nullyes
expires_atstring or nullyes
idstringyes
kindstring (manual, auto, setup)yes
statusstring (open, completed, expired, canceled, failed)yes
stripe_payment_intent_idstring or nullyes
stripe_session_idstring or nullyes
urlstring or nullnoThe hosted Checkout page while the session is open.

Example

curl https://api.faxforagents.com/v1/topup-sessions/TOPUP_SESSION_ID \
  -H "Authorization: Bearer ffa_test_..."

GET /v1/usage

Usage rollups by day, direction, destination and project

Credential: an API key or a signed-in session. Scope: billing:read.

Parameters

GET /v1/usage parameters
NameInTypeRequiredNotes
fromquerystring or nullno
toquerystring or nullno
group_byquerystringnoComma-separated subset. Default "day,direction,route,project".
project_idquerystring or nullno

Responses

GET /v1/usage responses
StatusMeaning
200Successful Response
401No 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.
403The 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.
422A field failed validation: invalid_request, with one entry per field in error.details, or a code that names the rule.
429rate_limited. Retry-After and the RateLimit-* headers say when to try again.

Response fields

GET /v1/usage response fields
FieldTypeRequiredDescription
currencystringyes
environmentstring (live, test)yes
fromstringyes
group_byarray of stringyes
itemsarray of object UsageItemyes
tostringyes
totalsobjectyes

Example

curl https://api.faxforagents.com/v1/usage \
  -H "Authorization: Bearer ffa_test_..."

POST /v1/usage-exports

Export usage as CSV behind a signed download

Credential: an API key or a signed-in session. Scope: billing:read.

Parameters

POST /v1/usage-exports parameters
NameInTypeRequiredNotes
Idempotency-KeyheaderstringnoReplay 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

POST /v1/usage-exports request body
FieldTypeRequiredDescription
fromstring or nullnoISO date; default 30 days ago.
tostring or nullnoISO date; default today.

Responses

POST /v1/usage-exports responses
StatusMeaning
201Successful Response
401No 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.
403The 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.
409The 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.
422A field failed validation: invalid_request, with one entry per field in error.details, or a code that names the rule.
429rate_limited. Retry-After and the RateLimit-* headers say when to try again.

Response fields

POST /v1/usage-exports response fields
FieldTypeRequiredDescription
content_typestringyes
created_atstringyes
environmentstring (live, test)yes
expires_atstringyes
idstringyes
paramsobjectyes
row_countintegeryes
statusstring (ready, expired)yes
urlstring or nullyes

Example

curl https://api.faxforagents.com/v1/usage-exports \
  -X POST \
  -H "Authorization: Bearer ffa_test_..." \
  -H "Content-Type: application/json" \
  -d '{}'

GET /v1/usage-exports/{export_id}

Read a usage export (fresh link)

Credential: an API key or a signed-in session. Scope: billing:read.

Parameters

GET /v1/usage-exports/{export_id} parameters
NameInTypeRequiredNotes
export_idpathstringyes

Responses

GET /v1/usage-exports/{export_id} responses
StatusMeaning
200Successful Response
401No 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.
403The 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.
404not_found: no such resource for this credential. A resource of another organization answers the same.
422A field failed validation: invalid_request, with one entry per field in error.details, or a code that names the rule.
429rate_limited. Retry-After and the RateLimit-* headers say when to try again.

Response fields

GET /v1/usage-exports/{export_id} response fields
FieldTypeRequiredDescription
content_typestringyes
created_atstringyes
environmentstring (live, test)yes
expires_atstringyes
idstringyes
paramsobjectyes
row_countintegeryes
statusstring (ready, expired)yes
urlstring or nullyes

Example

curl https://api.faxforagents.com/v1/usage-exports/EXPORT_ID \
  -H "Authorization: Bearer ffa_test_..."

GET /v1/usage-exports/{export_id}/content

The CSV behind a signed URL (no API key)

Credential: the signed URL as it was given.

Parameters

GET /v1/usage-exports/{export_id}/content parameters
NameInTypeRequiredNotes
export_idpathstringyes
expquerystring or nullno
sigquerystring or nullno

Responses

GET /v1/usage-exports/{export_id}/content responses
StatusMeaning
200Successful Response
404not_found: no such resource for this credential. A resource of another organization answers the same.
422A field failed validation: invalid_request, with one entry per field in error.details, or a code that names the rule.

Example

curl https://api.faxforagents.com/v1/usage-exports/EXPORT_ID/content