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

Intent Challenge

POST https://api.firmly.work/api/v1/wallets/agentic-pay/intent/challenge

​​ Overview

After the cardholder completes the FIDO assertion in the iframe (rendered from the Create Intent response), submit the result to this endpoint. On success, it returns an intent_id that, together with the flow_token, is used to place the order via the vault.

  • Final step: This is the last call in the agentic pay flow before order placement
  • Only when a challenge was issued: If Create Intent returned intent_id instead of challenge (Discover; Mastercard reusing a fresh enrollment authentication), skip this endpoint and place the order directly
  • FIDO assertion: The iframe_result contains the fidoBlob and assuranceData captured via postMessage from the authentication iframe
  • Order placement: Use the returned flow_token and intent_id to complete the order through the wallet order endpoint

​​ Authentication

  • x-firmly-authorization (string, required) — API token for authenticating the request

​​ Request Body

  • flow_token (string, required) — Flow token from the Create Intent response

  • type (string, required) — Challenge type being submitted. Typically embed_iframe for FIDO assertion results.

  • iframe_result (object) — FIDO assertion result captured from the authentication iframe via postMessage. Required for the embed_iframe challenge type (the only documented type) — the assertion cannot be verified without it. Properties:

    • fidoBlob (string): FIDO credential assertion blob from the iframe
    • assuranceData (string): Assurance data from the iframe

​​ Response

  • flow_token (string) — Final flow token for use in order placement

  • intent_id (string) — Payment intent identifier to pass when completing the order (e.g., "1-5C90F1500800b0be2dc0-e6cf-55d5-54e6-12d8519fad02")

​​ Code Examples


curl --request POST \
--url https://api.firmly.work/api/v1/wallets/agentic-pay/intent/challenge \
--header 'Content-Type: application/json' \
--header 'x-firmly-authorization: YOUR_TOKEN' \
--data '{
"flow_token": "eyJhbGciOiJBMjU2S1ci...",
"type": "embed_iframe",
"iframe_result": {
"fidoBlob": "eyJraWQiOiI0ZDkxZWY5Mi...",
"assuranceData": "dG9rZW5pemVkLWFzc2Vy..."
}
}'

const response = await fetch('https://api.firmly.work/api/v1/wallets/agentic-pay/intent/challenge', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'x-firmly-authorization': 'YOUR_TOKEN'
},
body: JSON.stringify({
flow_token: 'eyJhbGciOiJBMjU2S1ci...',
type: 'embed_iframe',
iframe_result: {
fidoBlob: 'eyJraWQiOiI0ZDkxZWY5Mi...',
assuranceData: 'dG9rZW5pemVkLWFzc2Vy...'
}
})
});
const { flow_token, intent_id } = await response.json();
// Use flow_token and intent_id to place the order
console.log('Intent ID:', intent_id);

import requests
response = requests.post(
'https://api.firmly.work/api/v1/wallets/agentic-pay/intent/challenge',
headers={
'Content-Type': 'application/json',
'x-firmly-authorization': 'YOUR_TOKEN'
},
json={
'flow_token': 'eyJhbGciOiJBMjU2S1ci...',
'type': 'embed_iframe',
'iframe_result': {
'fidoBlob': 'eyJraWQiOiI0ZDkxZWY5Mi...',
'assuranceData': 'dG9rZW5pemVkLWFzc2Vy...'
}
}
)
result = response.json()
print('Intent ID:', result['intent_id'])

​​ Response Example


{
"flow_token": "<encrypted-jwe-token>",
"intent_id": "1-5C90F1500800b0be2dc0-e6cf-55d5-54e6-12d8519fad02"
}

​​ Error Responses

Code Status Description
BadRequest 400 Invalid flow_token format or missing required fields
BadRequest 400 The FIDO assertion was rejected or the cardholder canceled the ceremony (the submitted iframe_result did not verify)
ErrorServiceUnavailable 503 FIDO verification failed or timed out

A declined or user-canceled FIDO assertion returns a 400 BadRequest rather than a success shape — no intent_id is issued. Prompt the cardholder to retry the assertion.