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

Agentic Pay

Agentic Pay is Firmly’s Network Token Router — an API that enables card enrollment and network token payment authorization. Destinations integrate one abstract API; Firmly handles the network-specific mechanics behind the scenes.

​​ Supported Networks

Visa Iframe handshake and FIDO2 verification
Mastercard Iframe-based authentication and FIDO2 verification
Discover No cardholder-verification step — enroll and intent complete in one call each

The network is automatically detected from the card’s BIN (Bank Identification Number — the leading digits of the card number) — destinations never specify which network to use.

​​ Authentication

All Agentic Pay endpoints accept your API token either in the x-firmly-authorization header (raw token, no prefix) or as a standard Authorization: Bearer <token> header. This is an app-level token, not a browser session token. The Headless SDK sends the same token as Authorization: Bearer — its apiToken config value is that token.

Header Type Required Description
x-firmly-authorization string Yes API token for authentication

​​ Flow Token

Every Agentic Pay response includes a flow_token — a JWE-encrypted (JSON Web Encryption) state token that carries the enrollment or payment context forward. Each subsequent call requires the flow_token from the previous response. This eliminates the need for server-side session storage and ensures stateless, tamper-proof request chaining.

​​ Two Entry Points, One Payment Chain

There are two ways to start a payment. Choose one based on whether the buyer is entering a new card or reusing a saved one — both paths return the same shape and then converge on the identical intent → order chain below.

Path A — New Card (Enroll) POST /enroll with the cardholder’s PAN (Primary Account Number — the full card number). Firmly enrolls the card and returns verification challenges (OTP — one-time password, and FIDO2 — the FIDO Alliance passkey/WebAuthn standard). Persist virtual_card_id, card_art, and masked for returning buyers.
Path B — Saved Card (Select Card) POST /select-card with a stored virtual_card_id — no PAN re-entry. Returns the same shape as /enroll, so the rest of the flow is identical.

Once you have a flow_token from either path, the remainder of the chain is shared:

​​ Payment Intent

POST /intent with the transaction amount. A FIDO2 assertion proves cardholder presence.

​​ Order Completion

Send the flow_token and intent_id to the wallet-complete-order endpoint. Firmly retrieves network token credentials and places the order.

​​ Available Endpoints

Method Path Description
POST /enroll Enroll a card and receive verification methods
POST /select-card Start a payment from a previously-enrolled card (no PAN)
POST /enroll/trigger Trigger a verification challenge (OTP, iframe) for enrollment
POST /enroll/verify Submit the verification response to complete enrollment
POST /intent Create a payment intent for an enrolled card
POST /intent/challenge Complete a payment-level FIDO challenge for the intent
GET /card-art/:token Retrieve the card art image for an enrolled card
GET /iframe-callback Iframe postMessage bridge for browser-based verification flows
POST /cards/delete Revoke an enrolled card on the network

​​ Endpoint Reference

​​ Enrollment

​​ Payment

​​ Browser Helpers

​​ Typical Flow

​​ Start Session

New card: POST /enroll with card details (PAN, expiry, consumer info). Receive flow_token, virtual_card_id, verification_methods, card_art, and masked. Persist virtual_card_id, card_art, and masked for returning buyers.

Saved card: POST /select-card with the stored virtual_card_id and network — no PAN needed. Returns the same shape as /enroll (card_art and masked are null — use persisted values).

​​ Verify Cardholder (New Card)

POST /enroll/trigger with the chosen method_id, then POST /enroll/verify with the cardholder’s response (OTP or FIDO2). May require multiple verify calls. Discover returns an empty verification_methods array from /enroll — the card is enrolled immediately and both calls are skipped. Saved cards skip enrollment verification, but a Visa saved card still returns an embed_iframe_handshake from /select-card whose secure_token must be captured and passed to /intent; Mastercard saved cards proceed straight to /intent.

​​ Create Payment Intent

POST /intent with the flow_token and transaction mandate. Receive either a FIDO2 assertion challenge, or — for Discover, and for Mastercard when a fresh enrollment authentication can be reused — the intent_id directly.

​​ Complete Intent (when a challenge was returned)

POST /intent/challenge with the FIDO2 result. Receive intent_id. Skip this step if /intent already returned intent_id.

​​ Place Order

POST /api/v2/payment/domains/{domain}/wallet-complete-order with flow_token, intent_id, and billing_info. (This is the payment/vault surface at cc.firmly.work, outside the Agentic Pay base URL.)