Skip to main content

Allowance Verification

Verification is how a customer approves one allowance rail with its provider. One endpoint drives every step of every provider's ceremony: you send an action, receive a state, and continue until the state is active. Most integrations drive it with the Web Agentic SDK or by following Own the Browser Verification Flow.

Verify an Allowance Rail

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

Permissions

agentic:allowance:verify

Available to public and private applications.

Request

Start Verification
curl 'https://api.basistheory.com/agentic/allowances/alw_Xw92mKvB3dQz/verify' \
-X 'POST' \
-H 'BT-API-KEY: <PUBLIC_API_KEY>' \
-H 'Content-Type: application/json' \
--data '{
"rail": "agentic-token",
"provider": "vic",
"action": "start",
"display_name": "Example Agent",
"device_context": {
"language_code": "en-US",
"time_zone": "America/New_York",
"platform_type": "WEB"
}
}'

Headers

HeaderRequiredDescription
BT-API-KEYYesPublic or private application key with agentic:allowance:verify. Use a public key in browser code; never ship a private key to the browser

Request Parameters

AttributeRequiredTypeDescription
allowance_idYesstringID of the allowance whose rail is being verified
railYesstringThe rail to verify. Only agentic-token has a verification ceremony
providerYesstringvic or agentpay for agentic-token, stripe for spt. Must match the rail on the allowance
actionNostringDefaults to start. See actions

Each action accepts only its own additional fields; unknown properties or fields from a different action return 400 VALIDATION_ERROR. The spt rail has no verification ceremony and its allowance rails are active from creation, so rail: "spt" returns 400 VERIFICATION_NOT_REQUIRED.

Actions

actionProviderAdditional fieldsTypical response
startvic, agentpaydisplay_name, device_contextVisa returns passkey_session; Mastercard returns redirect
submit_sessionvicsession_contextpasskey when the device is bound, otherwise select_otp_method
select_otp_methodvicmethod_idotp
submit_otpvicotp_codepasskey with a REGISTER context
submit_passkeyvicassurance_datastatus: "active"
completeagentpaystatus: "active", or verification_required while Mastercard is still processing

Visa exposes no polling action; each returned next_action must be performed.

start

AttributeRequiredTypeDescription
display_nameNostring1 to 60 characters. Defaults to Agent. The application or agent name the customer sees on provider-hosted screens, such as "Add Allowance to Example Agent". Sent once on start and retained for the rest of the ceremony
device_contextNoobjectBrowser and device data the provider uses for risk assessment. See device context

For Mastercard, display_name is sent as the requestor name and presentation name, and the allowance's merchant.name is used as the merchant name.

Device Context Object

Only language_code and time_zone are validated; every other property is forwarded to Visa unchanged. The object is retained server-side and reused on submit_session.

AttributeRequiredTypeDescription
language_codeNostringBCP 47 language tag, canonicalized on input, so EN-us becomes en-US. Underscore locales such as en_US are rejected
time_zoneNostringIANA time zone identifier, such as America/New_York

Fields Visa expects, forwarded as sent: screen_height, screen_width, user_agent_string, java_script_enabled, client_device_id, client_reference_id, platform_type (WEB, MOBILE, or NATIVE), color_depth, accept_header, and ip_address. Send ip_address as IPv4 only; Visa rejects IPv6 and Basis Theory does not rewrite the value.

submit_session

AttributeRequiredTypeDescription
session_contextYesobjectExact object containing only secure_token
session_context.secure_tokenYesstringNon-empty. The secure session token returned by Visa's hosted iframe after a passkey_session action

The device context and display name sent on start are not resent.

select_otp_method

AttributeRequiredTypeDescription
method_idYesstringNon-empty. The id of a method from the select_otp_method next action

submit_otp

AttributeRequiredTypeDescription
otp_codeYesstringNon-empty. The code the cardholder received

submit_passkey

AttributeRequiredTypeDescription
assurance_dataYesobjectThe result of Visa's passkey ceremony. Basis Theory validates it with Visa before activating the rail

Visa returns this data in camelCase and the API expects snake_case:

assurance_data
{
"identifier": "0198f2a1",
"dfp_session_id": "8c1d4e77",
"fido_assertion_data": {
"code": "eyJhbGciOiJFUzI1NiJ9"
}
}

complete

Takes no additional fields. Retrieves Mastercard's managed-authentication result server to server and activates the rail only when Mastercard confirms it.

complete is the only way to finish a Mastercard ceremony. The mastercard_verification_complete browser message signals that the hosted ceremony returned, not its result; call complete even when the message is lost.

Response

Returns 200 with a verification envelope. Continue until status is active.

Response
{
"status": "verification_required",
"rail": "agentic-token",
"provider": "vic",
"next_action": {
"type": "passkey_session",
"embed": {
"iframe_url": "https://auth.example-visa.com/embed",
"api_key": "<VISA_PUBLISHABLE_KEY>",
"client_app_id": "<VISA_CLIENT_APP_ID>"
}
}
}
AttributeTypeDescription
statusstringverification_required or active
railstringThe rail that was verified
providerstringThe provider that was verified
next_actionobjectPresent when the provider requires a browser or customer action. See next actions

A rail that is already active returns its verification envelope without contacting the provider:

{
"status": "active",
"rail": "agentic-token",
"provider": "vic"
}

A verification_required response without next_action means the provider is still processing; wait briefly and repeat the action. Only Mastercard's complete responds this way. Every other verification_required response contains the action the client must perform.

Basis Theory confirms every terminal transition with the provider server to server. No value a client sends can activate a rail on its own.

Next Actions

typeContainsWhat the client does
passkey_sessionembedMount Visa's hidden session iframe, create a session, then send its secure token with submit_session
select_otp_methodmethodsPresent the choices and send back method_id
otpmethod, code_expiration_minutes, max_attemptsCollect the code and send back otp_code
passkeypasskey_context, embedFrom a user gesture, open Visa's visible ceremony in a popup and send back assurance_data
redirecturi, uri_type, purpose, expires_atOpen Mastercard's page top-level in a popup or new tab, then call complete

passkey_session

Visa's hidden session-initialization surface. It only establishes the session and returns a secure token; it must not be used for the visible passkey ceremony.

AttributeTypeDescription
embed.iframe_urlstringURL of Visa's hosted authentication page
embed.api_keystringPublishable-class Visa key, served by the API and subject to rotation
embed.client_app_idstringVisa client application identifier

select_otp_method

AttributeTypeDescription
methodsarrayAvailable one-time-code destinations. Each has id, type (sms, email, or otponlinebanking), and value holding a masked destination or the issuer's display label

Visa step-up methods that are not code-based, including app-to-app, customer-service, and outbound-call flows, are not supported and are filtered out of this list. When Visa offers no supported method, the request returns 422 VERIFICATION_NOT_SUPPORTED.

otp

AttributeTypeDescription
methodobjectThe selected method, with id, type, and value
code_expiration_minutesintegerMapped from Visa's response. Defaults to 5 when Visa omits it
max_attemptsintegerMapped from Visa's response. Defaults to 3 when Visa omits it

Both values are display hints; Visa enforces them when it validates the code.

passkey

Visa's visible ceremony. Open it in a popup created synchronously from the cardholder's click to preserve browser user activation and WebAuthn permissions.

AttributeTypeDescription
embedobjectSame fields as passkey_session. The same hosted URL backs both surfaces
passkey_context.endpointstringVisa ceremony endpoint
passkey_context.identifierstringVisa ceremony identifier
passkey_context.payloadstringOpaque Visa ceremony payload. Pass through unmodified
passkey_context.actionstringREGISTER or AUTHENTICATE. Visa chooses; the client must branch on it
passkey_context.platform_typestringPlatform Visa expects, such as WEB
passkey_context.auth_preferences.response_modestringForward exactly as returned
passkey_context.auth_preferences.response_typestringForward exactly as returned

REGISTER and AUTHENTICATE use the same visible popup surface. After a REGISTER ceremony completes, the passkey exists but the mandate is not authenticated: send start again to open a fresh session, which lands in the AUTHENTICATE branch.

Basis Theory requests Visa's popup response preference for both ceremonies; overriding response_mode with a popup-incompatible value causes Visa to reject the ceremony.

redirect

Mastercard's managed-authentication ceremony.

AttributeTypeDescription
uristringHosted ceremony URL
uri_typestringWEB_URI
purposestringThe ceremony this redirect performs. Always present; always transaction_authentication
expires_atstringISO 8601 expiry of the authentication session, when the provider supplies one

Open uri top-level, in a popup or a new tab; Mastercard's page sends X-Frame-Options: DENY and cannot be embedded in an iframe. The managed ceremony creates a passkey when the cardholder does not have one, so there is no separate registration step.

Errors

CodeHTTPMeaning
VALIDATION_ERROR400Unknown property, wrong fields for the action, or an action the provider does not support
VERIFICATION_STATE_INVALID400The action is out of order for the current state. Restart from start
VERIFICATION_NOT_REQUIRED400That rail has no verification ceremony, so there is nothing to verify. Mint from it directly
INVALID_OTP400The code is wrong or expired. Retry the step; the provider enforces the attempt limit
RAIL_NOT_FOUND400That rail and provider pair is not on the allowance
ALLOWANCE_CANCELLED400The allowance was cancelled
ALLOWANCE_EXPIRED400The allowance expiration has passed
PAYMENT_METHOD_DELETED400The backing payment method was deleted
ALLOWANCE_NOT_FOUND404No such allowance in the tenant
ALLOWANCE_VERIFICATION_IN_PROGRESS409Another verification call is running. Retry shortly
ALLOWANCE_UPDATE_IN_PROGRESS, ALLOWANCE_DELETE_IN_PROGRESS, ALLOWANCE_CREDENTIAL_IN_PROGRESS409Another operation holds the allowance. Retry shortly
VERIFICATION_NOT_SUPPORTED422The source cannot complete this ceremony, such as a Mastercard without managed authentication or a Visa card with no supported code method. The spt rail remains available
PROVIDER_VERIFICATION_FAILED422The provider rejected or expired the session, or rejected the passkey assurance data. Restart from start
PROVIDER_NOT_CONFIGURED422Tenant onboarding for this rail is incomplete. Contact us

Because verification takes the payment method's operation slot, it can also return 409 PAYMENT_METHOD_OPERATION_IN_PROGRESS, 409 PAYMENT_METHOD_DELETE_IN_PROGRESS, or 409 PAYMENT_METHOD_DELETE_INCOMPLETE.

See Errors and Recovery for what is safe to retry.