Skip to main content
For a card payment, the checkout stops at the payment step and asks your app for an order intent that covers the amount. Your app sends the ID of an order intent that the user approved before, or creates a new one that the user approves now. The card number never goes to your app, your agent, or the model. When the merchant takes payment through Klarna, the payment request has a link instead, where your user pays with their own Klarna account. See Pay With Klarna. To pay with a different method that the merchant accepts, such as Shop Pay, write the method in the task, or let the checkout ask the user.

Prerequisites

  • Checkout integration — complete the quickstart, so that your app can start a checkout, follow it, and send answers.
  • Saved card — to pay with an order intent, save the user’s card and register it.
  • One user — use the same production project and the same user for the checkout and its order intent.

Choose the Method in the Task

Write the user’s payment method in the task when you start the checkout. Be specific, so that the checkout does not have to guess which option to select.
The task chooses the method. It does not approve a charge. Answer a payment request only when the checkout asks for it.

Pay With an Order Intent

1

Detect the payment request

The checkout moves to awaiting_input and shows the request in both places where you can watch a checkout:
  • requiredAction.request when you read the checkout
  • an input_request message part when you list or stream messages
Dispatch on interaction.kind === "payment", then on interaction.method. Answer with an order intent only when method is "card". For "klarna", see Pay With Klarna. A card request contains safe charge metadata, not card details, an iframe URL, or an order intent ID.An open payment message part looks like this:
  • method: "card" requests a card credential.
  • Other method values, such as "klarna", do not request a card credential. Do not answer them with an order intent.
  • amount.value is a decimal string and amount.currency is an ISO 4217 code. kind: "exact" is the requested payable total; kind: "maximum" is the checkout’s spending cap.
  • merchant identifies where the credential will be used. Copy its url, name, and countryCode unchanged when you create the order intent.
2

Create the order intent

If the user already approved an order intent that covers this payment, you can reuse it instead of creating a new one. See List Order Intents. Skip this step, but still check its rails in the next step before you send its ID. The order intent must be active, in the same currency, with amount.available at least the payment amount, and with no merchant or the same merchant.Create the order intent in your app, where the user is signed in, with a production client-side key that has order-intents.create and order-intents.read scopes. Send the JWT of the same user who owns the saved card and the checkout.Use the exact amount from the payment request, set a short expiration, and copy interaction.merchant into the order intent. This makes the merchant available to payment rails that need it before credential minting. If you omit it, Agent Checkouts supplies the same merchant when it requests the credential.
YOUR_PAYMENT_METHOD_ID is the ID returned when you save and register the user’s card. For the complete request and response, see Approve an Order Intent.
3

Complete verification when required

Read orderIntent.rails and look for an active rail whose credentialFormats includes "card". For a reused order intent, read it first with Get Order Intent. The top-level order-intent status does not tell you whether a card credential is ready.If no card rail is active, follow Verify the Selected Rail for pending_verification, or Ask for the CVC Again for pending_cvc_recollection. Fetch the order intent again after that step and confirm that a card-capable rail is active. If none can become active, ask the user for a different card.
A card with no network rail. Agent Checkouts uses the encrypted card. The card stays inside the Crossmint vault, and you do not need encrypted card access. Your reads of the order intent can show no active card rail for this card: send the orderIntentId anyway. If the checkout answers rail_unavailable, ask the user to enter the CVC again, then answer the new payment request. See Card Rails and PCI Compliance.
Approve an Order Intent shows the verification component. Card setup and verification are separate from submitting the checkout response.
4

Submit the order intent ID

Send one input_response part that references the request’s requestId. Do not send card numbers, expiration dates, or security codes.
You can instead send action: "alternative" with text such as "Pay with Shop Pay instead", or action: "decline" to refuse the charge. See Send Agent Checkout Message for the complete schema.Answer before the request’s expiresAt. If it expires, watch the checkout for a new request and answer its new requestId.
Never put card details in the task, a buyer profile, form answers, or a text message. Raw card details are not accepted.
5

Keep following the checkout

The accepted answer resumes the checkout. Keep streaming messages or reading the checkout until it ends, asks another question, or stops.If the merchant total changes or the authorization cannot be used, the agent sends a new payment request. Answer the new requestId; do not reuse a response from an earlier request.

Pay With Klarna

Some merchants take payment through Klarna. Then the payment request has method: "klarna", and an authorizationUrl that opens a page where your user pays with their own Klarna account:
  • Show authorizationUrl to your user without changes, for example as a link or in a new tab. Do not change it or join it to another origin.
  • Do not create an order intent, and do not send an input_response. The checkout continues after your user pays. Follow the checkout for the result.
  • amount is the exact total. merchant has only url.
Anyone who has authorizationUrl can open the payment page. Give it only to your user. Do not log it, or put it in analytics, traces, or error reports.

Pay With Other Methods

Other methods, such as Shop Pay, work through the checkout’s questions. You can write the method in the task, for example Pay with Shop Pay, or let the checkout ask:
  1. The checkout asks how to pay. When the merchant offers several methods, the checkout sends a form question with the methods as choices. Your app or your agent shows them to the user.
  2. The user chooses a method. Send the choice in a form response, for example Shop Pay.
  3. The checkout signs in to the method. Shop Pay sends a one-time code to the user, and the checkout sends a form question for it. Collect the code with CrossmintProtectedInput. See Answer Questions.
  4. The checkout submits the payment. It uses the payment method that the user saved in Shop Pay, with Shop Pay’s own protections.
If the merchant does not accept the method, the checkout asks what to do. Send an alternative, for example Pay by card instead.

Handle Payment Problems

When the checkout accepts the ID, the merchant has not accepted the card yet. Follow the checkout for the outcome, another request, or the final result. Use the same production project and user for the checkout, the saved card, and the order intent. Your application sends identifiers instead of raw card data. Protected collection does not guarantee that values applied to merchant inputs are absent from later browser observations or recordings. For web, native, messaging, and server integrations, see Connect Your User Channel.

Next Steps

Approve an Order Intent

Create the order intent and verify its rail

Card Rails and PCI

How the payment step keeps card data out of your app

Send a Message

Review the payment response schema