Docs
Firmly Agentic Commerce
Set theme to dark (⇧+D)

Select Card

POST https://api.firmly.work/api/v1/wallets/agentic-pay/select-card

​​ Overview

The Select Card endpoint starts a payment flow from a stored card. It takes the virtual_card_id from a prior enrollment and returns the same shape as /enroll — a flow_token whose status is already enrolled, so verification is skipped — plus verification_methods. The existing handshake, intent, and order completion chain is reused unchanged.

Destinations persist card_art and masked from the initial /enroll response for the saved-card UI. /select-card does not re-fetch card metadata.

​​ Authentication

  • x-firmly-authorization (string, required) — API token for authentication

​​ Request Body

  • network (string, required) — Card network: "visa", "mastercard", or "discover"

  • virtual_card_id (string, required) — The virtual_card_id returned from the original /enroll response

  • consumer (object) — Cardholder information. Required for Visa (email is mandatory for device binding — omitting it returns a 400). Optional for Mastercard. Fields:

    • email (string) — Cardholder email address (required for Visa)
    • country_code (string) — ISO country code (e.g., "US")

​​ Response

Returns the same shape as /enroll.

  • flow_token (string) — Encrypted state token for subsequent calls (status: enrolled).

  • virtual_card_id (string) — Same virtual_card_id passed in the request.

  • verification_methods (array) — Available verification methods. Visa returns an embed_iframe_handshake (capture a secure_token before calling /intent). Mastercard and Discover return an empty array — proceed directly to /intent.

  • card_art (null) — Always null on /select-card. Use the card_art persisted from the original /enroll response.

  • masked (null) — Always null on /select-card. Use the masked details persisted from the original /enroll response.

​​ Code Examples


curl --request POST \
--url https://api.firmly.work/api/v1/wallets/agentic-pay/select-card \
--header 'Content-Type: application/json' \
--header 'x-firmly-authorization: YOUR_API_TOKEN' \
--data '{
"network": "visa",
"virtual_card_id": "cf90be5c86363de702ed19beec46e102",
"consumer": {
"email": "jane@example.com",
"country_code": "US"
}
}'

const response = await fetch('https://api.firmly.work/api/v1/wallets/agentic-pay/select-card', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'x-firmly-authorization': 'YOUR_API_TOKEN'
},
body: JSON.stringify({
network: 'visa',
virtual_card_id: 'cf90be5c86363de702ed19beec46e102',
consumer: {
email: 'jane@example.com',
country_code: 'US'
}
})
});
const { flow_token, verification_methods } = await response.json();
// Continue with handshake → /intent → /intent/challenge → /wallet-complete-order

import requests
response = requests.post(
'https://api.firmly.work/api/v1/wallets/agentic-pay/select-card',
headers={
'Content-Type': 'application/json',
'x-firmly-authorization': 'YOUR_API_TOKEN'
},
json={
'network': 'visa',
'virtual_card_id': 'cf90be5c86363de702ed19beec46e102',
'consumer': {
'email': 'jane@example.com',
'country_code': 'US'
}
}
)
data = response.json()
# Continue with handshake → /intent → /intent/challenge → /wallet-complete-order
print(data['flow_token'])
print(data['verification_methods'])

​​ Response Example


{
"flow_token": "<encrypted-jwe-token>",
"virtual_card_id": "cf90be5c86363de702ed19beec46e102",
"verification_methods": [
{
"id": "VISA_IFRAME_HANDSHAKE",
"type": "embed_iframe_handshake",
"attributes": {
"uri": "https://sbx.vts.auth.visa.com/vts-auth/authenticate?apiKey=...",
"next_steps": [
"Load this iframe in the cardholder browser",
"Capture sessionContext.secureToken from postMessage",
"Send to /intent as secure_token"
]
}
}
]
}

​​ Error Responses

Error Code Status Description
BadRequest 400 network or virtual_card_id missing, or consumer.email missing for a Visa card.
PaymentMethodNotAvailable 409 Stored-card payment is not supported or not enabled for this network.
400 - Missing Required Fields

{
"code": 400,
"error": "BadRequest",
"description": "network and virtual_card_id required"
}
400 - Missing Email (Visa)

{
"code": 400,
"error": "BadRequest",
"description": "consumer.email is required for Visa stored-card selection"
}
409 - Network Not Available

{
"code": 409,
"error": "PaymentMethodNotAvailable",
"description": "Stored-card payment not supported for this network"
}