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_idinstead ofchallenge(Discover; Mastercard reusing a fresh enrollment authentication), skip this endpoint and place the order directly - FIDO assertion: The
iframe_resultcontains thefidoBlobandassuranceDatacaptured viapostMessagefrom the authentication iframe - Order placement: Use the returned
flow_tokenandintent_idto 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. Typicallyembed_iframefor FIDO assertion results. -
iframe_result(object) — FIDO assertion result captured from the authentication iframe viapostMessage. Required for theembed_iframechallengetype(the only documented type) — the assertion cannot be verified without it. Properties:fidoBlob(string): FIDO credential assertion blob from the iframeassuranceData(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 orderconsole.log('Intent ID:', intent_id);
import requestsresponse = 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.
Related Endpoints
- Create Intent — Create the payment intent and receive the FIDO challenge
- Wallet Complete Order — Place the order using the
flow_tokenandintent_id