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.
Permissions
agentic:allowance:create
Request
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
| Header | Required | Description |
|---|---|---|
BT-API-KEY | Yes | Private application key |
BT-IDEMPOTENCY-KEY | No | Opts into durable retry handling. Without it, every request is a new create operation. See Idempotency |
Request Parameters
| Attribute | Required | Type | Description |
|---|---|---|---|
payment_method_id | Yes | string | Non-empty. The payment method must have at least one enabled rail, or the request returns 400 NO_ACTIVE_RAILS |
amount | Yes | object | The total this mandate permits. See amount object |
merchant | Yes | object | The merchant this mandate is scoped to. See merchant object |
description | Yes | string | 1 to 10,000 characters. Customer-facing prompt describing what the allowance permits |
expires_at | Yes | string | ISO 8601 date-time strictly in the future |
metadata | No | object | Customer-owned JSON, at most 32 KiB when JSON-encoded. See metadata |
agent_id | No | string | Non-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
| Attribute | Required | Type | Description |
|---|---|---|---|
value | Yes | string | Major-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 |
currency | Yes | string | Current 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
| Attribute | Required | Type | Description |
|---|---|---|---|
name | Yes | string | 1 to 200 characters. Shown to the cardholder during network verification |
url | Yes | string | Absolute http or https URL, at most 2,048 characters |
country_code | Yes | string | ISO 3166-1 alpha-2 code. Lowercase is normalized to uppercase |
category_code | No | string | Exactly four digits. Merchant category code used for network authentication. Mastercard defaults to 5399 when omitted; Visa forwards it only when supplied |
acquirer_bin | No | string | Exactly 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.
{
"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
Permissions
agentic:allowance:get
Request
curl 'https://api.basistheory.com/agentic/allowances?payment_method_id=pm_h2Kd91mAqLwX&status=all' \
-H 'BT-API-KEY: <PRIVATE_API_KEY>'
Query Parameters
| Parameter | Required | Type | Default | Description |
|---|---|---|---|---|
size | No | integer | 20 | 1 through 100. Out of range returns 400 |
start | No | string | — | Opaque cursor from the previous response's pagination.next |
payment_method_id | No | string | — | Return only allowances backed by one payment method. An unknown ID returns 404 PAYMENT_METHOD_NOT_FOUND |
status | No | string | active | active, cancelled, expired, or all |
Response
Returns a paginated list of allowance objects.
Get an Allowance
Permissions
agentic:allowance:get
Request
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.
Permissions
agentic:allowance:update
Request
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.
| Attribute | Required | Type | Description |
|---|---|---|---|
amount | No | object | Same validation as on create. Rejected once any capacity has been spent, including capacity consumed by an indeterminate mint outcome |
description | No | string | 1 to 10,000 characters |
expires_at | No | string | ISO 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.
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.
Permissions
agentic:allowance:create
Request
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
| Attribute | Required | Type | Description |
|---|---|---|---|
allowance_id | Yes | string | ID of the allowance |
rail | Yes | string | agentic-token or spt |
provider | Yes | string | vic, 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.
Permissions
agentic:allowance:get
Request
curl 'https://api.basistheory.com/agentic/allowances/alw_Xw92mKvB3dQz/errors' \
-H 'BT-API-KEY: <PRIVATE_API_KEY>'
Query Parameters
| Parameter | Required | Type | Default | Description |
|---|---|---|---|---|
size | No | integer | 20 | 1 through 100 |
start | No | string | — | Opaque cursor from the previous response's pagination.next |
Response
Returns a paginated list of provider error objects.
Cancel an Allowance
Permissions
agentic:allowance:delete
Request
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
| Attribute | Type | Description |
|---|---|---|
id | string | Prefixed with alw_ |
payment_method_id | string | The payment method backing this allowance |
status | string | active, cancelled, or expired. See allowance status versus rail status |
amount | object | The total this mandate permits |
amount_spent | object | Capacity consumed by committed credential mints and by indeterminate provider outcomes. Spent capacity is never voided or released |
amount_reserved | object | Held 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_available | object | amount minus amount_spent minus amount_reserved |
credentials_count | integer | Credential records committed for this allowance, even when the mint response was lost. Excludes indeterminate outcomes that produced no record |
merchant | object | The merchant object |
description | string | Customer-facing prompt |
expires_at | string | ISO 8601 timestamp |
metadata | object | Present when supplied. Returned unchanged |
rails | array | One allowance rail per rail on the mandate |
agent_id | string | Present when supplied. Informational, not an authorization grant |
created_at | string | ISO 8601 timestamp |
updated_at | string | ISO 8601 timestamp. Changes only for externally observable state; intermediate verification steps do not move it |
Allowance Rail Object
| Attribute | Type | Description |
|---|---|---|
rail | string | agentic-token or spt |
provider | string | vic, agentpay, or stripe |
status | string | active, pending_verification, or error |
credential_formats | array | Formats this rail and provider accept when minting. Some subset of card, network-token, identifier, and mpp |
error | object | Present only when status is error. Contains a stable machine-readable code drawn from the rail error codes |
provider_ids | object | Provider-native reference identifiers for the mandate, all string values. Informational for support and correlation |
Rail Statuses
| Status | Meaning |
|---|---|
active | Credentials can be minted from this rail now |
pending_verification | The cardholder must complete verification before minting. Minting returns 400 RAIL_NOT_ACTIVE |
error | Provider 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.
| Field | Values | Describes |
|---|---|---|
Allowance status | active, cancelled, expired | The mandate. active means neither cancelled nor past expires_at. cancelled follows a DELETE. expired is derived from expires_at |
Rail status | active, pending_verification, error | One way of spending that mandate |
Always read the rail you intend to verify or mint from, not the allowance's top-level status.