Skip to main content

Allowances

An allowance is a spending mandate backed by one payment method: an amount, a merchant, a customer-facing description, and an expiration. Its balance decreases as credentials are minted from it.

Create an Allowance

Creates the allowance and initializes an allowance rail for every enabled rail on the payment method, in parallel. Card-network rails may create provider-side allowance state; the Stripe spt rail is active from creation and creates its token only when a credential is minted.

POST
https://api.basistheory.com/agentic/allowances
Copy

Permissions

agentic:allowance:create

Request

Create an Allowance
curl 'https://api.basistheory.com/agentic/allowances' \
-X 'POST' \
-H 'BT-API-KEY: <PRIVATE_API_KEY>' \
-H 'BT-IDEMPOTENCY-KEY: allowance-office-supplies-v1' \
-H 'Content-Type: application/json' \
--data '{
"payment_method_id": "pm_h2Kd91mAqLwX",
"amount": { "value": "100.00", "currency": "USD" },
"merchant": {
"name": "Acme Store",
"url": "https://acme.example.com",
"country_code": "US",
"category_code": "5732",
"acquirer_bin": "545301"
},
"description": "Buy approved office supplies from Acme Store",
"expires_at": "2030-07-08T00:00:00.000Z",
"metadata": { "order_ref": "po-1138" }
}'

Headers

HeaderRequiredDescription
BT-API-KEYYesPrivate application key
BT-IDEMPOTENCY-KEYNoOpts into durable retry handling. Without it, every request is a new create operation. See Idempotency

Request Parameters

AttributeRequiredTypeDescription
payment_method_idYesstringNon-empty. The payment method must have at least one enabled rail, or the request returns 400 NO_ACTIVE_RAILS
amountYesobjectThe total this mandate permits. See amount object
merchantYesobjectThe merchant this mandate is scoped to. See merchant object
descriptionYesstring1 to 10,000 characters. Customer-facing prompt describing what the allowance permits
expires_atYesstringISO 8601 date-time strictly in the future
metadataNoobjectCustomer-owned JSON, at most 32 KiB when JSON-encoded. See metadata
agent_idNostringNon-empty. Optional attribution to an agent owned by the tenant; an unknown ID returns 404 AGENT_NOT_FOUND. Informational only: API key permissions remain the authorization boundary

Unknown properties, including fields from the deprecated Instructions API such as recurring, are rejected with 400 VALIDATION_ERROR.

Amount Object

AttributeRequiredTypeDescription
valueYesstringMajor-unit decimal string matching ^\d+(\.\d{1,4})?$. Must be greater than zero. Precision cannot exceed the currency's ISO 4217 minor unit, so USD permits two decimals, JPY none, KWD three, and CLF four. Values that exceed the supported range after conversion to minor units are rejected
currencyYesstringCurrent ISO 4217 alphabetic code with a defined minor unit, such as USD. Lowercase is normalized to uppercase

Responses canonicalize amounts to the currency's precision, so a submitted "10" in USD returns as "10.00". Balances and credential amounts use the same representation.

Merchant Object

AttributeRequiredTypeDescription
nameYesstring1 to 200 characters. Shown to the cardholder during network verification
urlYesstringAbsolute http or https URL, at most 2,048 characters
country_codeYesstringISO 3166-1 alpha-2 code. Lowercase is normalized to uppercase
category_codeNostringExactly four digits. Merchant category code used for network authentication. Mastercard defaults to 5399 when omitted; Visa forwards it only when supplied
acquirer_binNostringExactly six digits. Used for Mastercard authentication. Defaults to 545301 when omitted

The merchant cannot be changed after creation.

Metadata

Customer-owned JSON, stored and returned unchanged. It is never interpreted and never sent to a provider. Do not place sensitive values in it.

Response

Returns an allowance object with 201, including when a rail failed at its provider.

Response
{
"id": "alw_Xw92mKvB3dQz",
"payment_method_id": "pm_h2Kd91mAqLwX",
"status": "active",
"amount": { "value": "100.00", "currency": "USD" },
"amount_spent": { "value": "0.00", "currency": "USD" },
"amount_reserved": { "value": "0.00", "currency": "USD" },
"amount_available": { "value": "100.00", "currency": "USD" },
"credentials_count": 0,
"merchant": {
"name": "Acme Store",
"url": "https://acme.example.com",
"country_code": "US",
"category_code": "5732",
"acquirer_bin": "545301"
},
"description": "Buy approved office supplies from Acme Store",
"metadata": { "order_ref": "po-1138" },
"expires_at": "2030-07-08T00:00:00.000Z",
"rails": [
{
"rail": "agentic-token",
"provider": "vic",
"status": "pending_verification",
"credential_formats": ["card", "network-token", "mpp"],
"provider_ids": { "instruction_id": "vic_ins_4f8a" }
},
{
"rail": "spt",
"provider": "stripe",
"status": "active",
"credential_formats": ["identifier", "mpp"]
}
],
"created_at": "2030-07-06T17:31:00.000Z",
"updated_at": "2030-07-06T17:31:00.000Z"
}

409 CREATE_OUTCOME_UNKNOWN means the create may have committed and the supplied key is terminal. See recovery.

Errors: 400 VALIDATION_ERROR, 400 NO_ACTIVE_RAILS, 400 PAYMENT_METHOD_DELETED, 404 PAYMENT_METHOD_NOT_FOUND, 404 AGENT_NOT_FOUND, 409 IDEMPOTENCY_CONFLICT, 409 IDEMPOTENCY_IN_PROGRESS, 409 CREATE_OUTCOME_UNKNOWN, 409 PAYMENT_METHOD_DELETE_IN_PROGRESS.

This operation can also return 409 PAYMENT_METHOD_OPERATION_IN_PROGRESS or 409 PAYMENT_METHOD_DELETE_INCOMPLETE; see Operations in Progress.

List Allowances

GET
https://api.basistheory.com/agentic/allowances
Copy

Permissions

agentic:allowance:get

Request

List Allowances
curl 'https://api.basistheory.com/agentic/allowances?payment_method_id=pm_h2Kd91mAqLwX&status=all' \
-H 'BT-API-KEY: <PRIVATE_API_KEY>'

Query Parameters

ParameterRequiredTypeDefaultDescription
sizeNointeger201 through 100. Out of range returns 400
startNostringOpaque cursor from the previous response's pagination.next
payment_method_idNostringReturn only allowances backed by one payment method. An unknown ID returns 404 PAYMENT_METHOD_NOT_FOUND
statusNostringactiveactive, cancelled, expired, or all

Response

Returns a paginated list of allowance objects.

Get an Allowance

GET
https://api.basistheory.com/agentic/allowances/{allowance_id}
Copy

Permissions

agentic:allowance:get

Request

Get an Allowance
curl 'https://api.basistheory.com/agentic/allowances/alw_Xw92mKvB3dQz' \
-H 'BT-API-KEY: <PRIVATE_API_KEY>'

Response

Returns an allowance object with live balances, or 404 ALLOWANCE_NOT_FOUND.

Update an Allowance

Propagates the change to any rail that maintains provider-side allowance state, then commits the same values locally. Credential minting is blocked while the update is in progress.

PATCH
https://api.basistheory.com/agentic/allowances/{allowance_id}
Copy

Permissions

agentic:allowance:update

Request

Update an Allowance
curl 'https://api.basistheory.com/agentic/allowances/alw_Xw92mKvB3dQz' \
-X 'PATCH' \
-H 'BT-API-KEY: <PRIVATE_API_KEY>' \
-H 'Content-Type: application/json' \
--data '{
"amount": { "value": "125.00", "currency": "USD" },
"description": "Buy approved office supplies and paper from Acme Store",
"expires_at": "2030-07-09T00:00:00.000Z"
}'

Request Parameters

At least one of the three is required. Sending {} returns 400 VALIDATION_ERROR without contacting any provider; sending no body at all returns 400 INVALID_BODY. Every other field, including merchant and metadata, is immutable and rejected.

AttributeRequiredTypeDescription
amountNoobjectSame validation as on create. Rejected once any capacity has been spent, including capacity consumed by an indeterminate mint outcome
descriptionNostring1 to 10,000 characters
expires_atNostringISO 8601 date-time strictly in the future

Response

Returns the updated allowance object with 200.

A PATCH whose effective values already match the allowance, compared by value rather than by formatting, returns the existing resource without contacting providers and without changing updated_at.

If provider propagation fails, the allowance is left unchanged and the provider error is returned.

Expiration is terminal. After expires_at passes, a PATCH returns 400 ALLOWANCE_EXPIRED; extending the timestamp cannot revive the allowance or provider-side state. Create a new allowance instead.

Errors: 400 VALIDATION_ERROR, 400 ALLOWANCE_EXPIRED, 400 ALLOWANCE_CANCELLED, 404 ALLOWANCE_NOT_FOUND, 409 ALLOWANCE_UPDATE_IN_PROGRESS, 409 ALLOWANCE_VERIFICATION_IN_PROGRESS, 409 ALLOWANCE_DELETE_IN_PROGRESS, 409 ALLOWANCE_CREDENTIAL_IN_PROGRESS, 422 PROVIDER_ALLOWANCE_UPDATE_FAILED.

Retry an Allowance Rail

Re-runs provider setup for one failed allowance rail.

POST
https://api.basistheory.com/agentic/allowances/{allowance_id}/rails/retry
Copy

Permissions

agentic:allowance:create

Request

Retry an Allowance Rail
curl 'https://api.basistheory.com/agentic/allowances/alw_Xw92mKvB3dQz/rails/retry' \
-X 'POST' \
-H 'BT-API-KEY: <PRIVATE_API_KEY>' \
-H 'Content-Type: application/json' \
--data '{
"rail": "agentic-token",
"provider": "vic"
}'

Request Parameters

AttributeRequiredTypeDescription
allowance_idYesstringID of the allowance
railYesstringagentic-token or spt
providerYesstringvic, agentpay, or stripe. Must be valid for the rail

Only an allowance rail whose status is error can be retried, and the matching payment method rail must still be enabled.

Response

Returns the complete updated allowance object with 200.

Errors: 400 VALIDATION_ERROR, 400 RAIL_NOT_FOUND, 400 RAIL_NOT_ACTIVE when the matching payment method rail is not enabled, 400 ALLOWANCE_CANCELLED, 400 ALLOWANCE_EXPIRED, 400 PAYMENT_METHOD_DELETED, 404 ALLOWANCE_NOT_FOUND, 409 when another operation on the payment method or allowance is in progress, 422 PROVIDER_ALLOWANCE_FAILED.

List Allowance Errors

Returns sanitized provider failures for the allowance, retained for 90 days. See Provider Error History for what the history includes.

GET
https://api.basistheory.com/agentic/allowances/{allowance_id}/errors
Copy

Permissions

agentic:allowance:get

Request

List Allowance Errors
curl 'https://api.basistheory.com/agentic/allowances/alw_Xw92mKvB3dQz/errors' \
-H 'BT-API-KEY: <PRIVATE_API_KEY>'

Query Parameters

ParameterRequiredTypeDefaultDescription
sizeNointeger201 through 100
startNostringOpaque cursor from the previous response's pagination.next

Response

Returns a paginated list of provider error objects.

Cancel an Allowance

DELETE
https://api.basistheory.com/agentic/allowances/{allowance_id}
Copy

Permissions

agentic:allowance:delete

Request

Cancel an Allowance
curl 'https://api.basistheory.com/agentic/allowances/alw_Xw92mKvB3dQz' \
-X 'DELETE' \
-H 'BT-API-KEY: <PRIVATE_API_KEY>'

Response

Returns 204 with no body. The allowance's status becomes cancelled, any provider-side mandate associated with its rails is cancelled, and no further credentials can be minted from it. The allowance remains readable and listable.

Cancellation blocks new credential reservations before contacting providers. Repeating a successful delete succeeds without another provider call and without changing updated_at.

Errors: 404 ALLOWANCE_NOT_FOUND, 409 ALLOWANCE_CREDENTIAL_IN_PROGRESS, 409 ALLOWANCE_DELETE_IN_PROGRESS, 409 ALLOWANCE_VERIFICATION_IN_PROGRESS, 409 ALLOWANCE_UPDATE_IN_PROGRESS, 500 PROVIDER_ALLOWANCE_CANCEL_FAILED.

Allowance Object

AttributeTypeDescription
idstringPrefixed with alw_
payment_method_idstringThe payment method backing this allowance
statusstringactive, cancelled, or expired. See allowance status versus rail status
amountobjectThe total this mandate permits
amount_spentobjectCapacity consumed by committed credential mints and by indeterminate provider outcomes. Spent capacity is never voided or released
amount_reservedobjectHeld while one credential mint is in flight; only one mint can reserve at a time, so concurrent mints cannot overspend. A stale reservation is consumed as spent before the next mint, update, cancellation, or verification proceeds
amount_availableobjectamount minus amount_spent minus amount_reserved
credentials_countintegerCredential records committed for this allowance, even when the mint response was lost. Excludes indeterminate outcomes that produced no record
merchantobjectThe merchant object
descriptionstringCustomer-facing prompt
expires_atstringISO 8601 timestamp
metadataobjectPresent when supplied. Returned unchanged
railsarrayOne allowance rail per rail on the mandate
agent_idstringPresent when supplied. Informational, not an authorization grant
created_atstringISO 8601 timestamp
updated_atstringISO 8601 timestamp. Changes only for externally observable state; intermediate verification steps do not move it

Allowance Rail Object

AttributeTypeDescription
railstringagentic-token or spt
providerstringvic, agentpay, or stripe
statusstringactive, pending_verification, or error
credential_formatsarrayFormats this rail and provider accept when minting. Some subset of card, network-token, identifier, and mpp
errorobjectPresent only when status is error. Contains a stable machine-readable code drawn from the rail error codes
provider_idsobjectProvider-native reference identifiers for the mandate, all string values. Informational for support and correlation

Rail Statuses

StatusMeaning
activeCredentials can be minted from this rail now
pending_verificationThe cardholder must complete verification before minting. Minting returns 400 RAIL_NOT_ACTIVE
errorProvider setup failed. error.code carries the reason, and the rail can be retried

Allowance Status versus Rail Status

These describe different things, and an allowance can be active while no rail is usable.

FieldValuesDescribes
Allowance statusactive, cancelled, expiredThe mandate. active means neither cancelled nor past expires_at. cancelled follows a DELETE. expired is derived from expires_at
Rail statusactive, pending_verification, errorOne way of spending that mandate

Always read the rail you intend to verify or mint from, not the allowance's top-level status.