> ## Documentation Index
> Fetch the complete documentation index at: https://docs.crossmint.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Authorize Payments

> Answer payment requests with order intents for the buyer's saved card

Agent Checkouts can use any payment method the merchant accepts. Tell the agent which method to use in the run's `task`. If the agent needs a card credential, it pauses and sends a typed payment request for your application to authorize.

Your agent runtime can run on a server and communicate through any user channel, including a website, native app, messaging app, or voice assistant. The user only needs a secure application surface when they must authorize or verify the card.

## Prerequisites

* **Agent Checkout integration**: Complete the [Agent Checkouts quickstart](/agents/agent-checkouts-quickstart) so your application can start a run, observe it, and send messages.
* **Agent Card setup**: To use an Agent Card, [save the user's card](/agents/payment-methods/cards/save-card), [register it](/agents/payment-methods/cards/register-card), and be ready to [create an order intent](/agents/payment-methods/cards/create-agent-card).
* **Consistent user identity**: Use the same Crossmint project, environment, and user identity for the checkout run and its order intent.

## Choose the Method in the Task

Describe the user's preferred method when you start the run. Be specific enough that the agent does not have to infer which option to select.

| Method | Example task | What else to provide |
| - | - | - |
| Crossmint Agent Card | `Buy one in black and pay by card.` | Authorize the typed payment request with an order intent. |
| Card saved at the merchant | `Buy one in black using my saved Visa ending in 4242.` | Start the run with the user's [`browser.profileId`](/agents/checkouts/merchant-sessions). |
| Local or alternative method | `Buy one in black and pay with Shop Pay.` | Answer any instructions the merchant presents. If the method is unavailable, steer the run to another method. |

<Note>The task selects the method. It does not authorize a charge. Only answer a typed payment request when the agent is ready to pay.</Note>

## Authorize an Agent Card

<Steps>
  <Step title="Detect the payment request">
    The run moves to `awaiting_input` and exposes the request in both places you can observe a run:

    * `requiredAction.request` when you read the run
    * an `input_request` message part when you list or stream messages

    Dispatch on `interaction.kind === "payment"`. The request contains safe charge metadata, not card details, an iframe URL, or an order intent ID.

    An open payment message part looks like this:

    ```json theme={null}
    {
        "type": "input_request",
        "status": "open",
        "requestId": "req_123",
        "question": "Authorize a card payment of 42.50 USD at shop.example.com.",
        "expiresAt": "2026-10-02T15:30:00.000Z",
        "interaction": {
            "kind": "payment",
            "purpose": "checkout_payment",
            "method": "card",
            "amount": { "kind": "exact", "value": "42.50", "currency": "USD" },
            "merchant": {
                "url": "https://shop.example.com",
                "name": "Example Shop",
                "countryCode": "US"
            }
        }
    }
    ```

    * `method: "card"` requests a card credential.
    * `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 run's cost ceiling.
    * `merchant` identifies where the credential will be used. Copy its `url`, `name`, and `countryCode` unchanged when you create the order intent.
  </Step>

  <Step title="Create the order intent">
    Create the order intent in your authenticated application with a production client-side key that has `order-intents.create` and `order-intents.read` scopes. Send the JWT for the same user who owns the saved card and the checkout run.

    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.

    ```typescript theme={null}
    // Uses an open payment request from the checkout run.
    const runId = "YOUR_RUN_ID";
    const apiKey = "YOUR_CLIENT_API_KEY";
    const jwt = "YOUR_USER_JWT";
    const checkoutHeaders = { "X-API-KEY": apiKey, Authorization: `Bearer ${jwt}` };
    const runResponse = await fetch(
        `https://www.crossmint.com/api/unstable/agent-checkouts/${runId}`,
        { headers: checkoutHeaders }
    );
    if (!runResponse.ok) {
        throw new Error(`Could not read checkout: ${runResponse.status}`);
    }
    const run = await runResponse.json();
    if (run.status !== "awaiting_input" || run.requiredAction.request.interaction.kind !== "payment") {
        throw new Error("Checkout does not have an open payment request");
    }
    const action = run.requiredAction;
    const paymentRequest = action.request;
    const expiresAt = new Date(Date.now() + 2 * 60 * 60 * 1_000).toISOString();

    const response = await fetch("https://www.crossmint.com/api/unstable/order-intents", {
        method: "POST",
        headers: {
            "Content-Type": "application/json",
            "X-API-KEY": apiKey,
            Authorization: `Bearer ${jwt}`,
        },
        body: JSON.stringify({
            paymentMethodId: "YOUR_PAYMENT_METHOD_ID",
            amount: {
                value: paymentRequest.interaction.amount.value,
                currency: paymentRequest.interaction.amount.currency,
            },
            description: `Agent Checkout at ${paymentRequest.interaction.merchant.name}`,
            merchant: paymentRequest.interaction.merchant,
            expiresAt,
        }),
    });

    if (!response.ok) {
        throw new Error(`Could not create order intent: ${response.status}`);
    }

    let orderIntent = await response.json();
    ```

    `YOUR_PAYMENT_METHOD_ID` is the ID returned when you [save](/agents/payment-methods/cards/save-card) and [register](/agents/payment-methods/cards/register-card) the user's card. For the complete request and response, see [Create an Agent Card](/agents/payment-methods/cards/create-agent-card#create-the-order-intent).
  </Step>

  <Step title="Complete verification when required">
    Read `orderIntent.rails` and look for an `active` rail whose `credentialFormats` includes `"card"`. 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](/agents/payment-methods/cards/create-agent-card#verify-the-selected-rail) for `pending_verification`, or [Recollect the CVC](/agents/payment-methods/cards/recollect-cvc) 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 buyer for another card.

    The [Agent Card guide](/agents/payment-methods/cards/create-agent-card#verify-the-selected-rail) shows the verification component. Card setup and verification are separate from submitting the checkout response.
  </Step>

  <Step title="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.

    <Snippet file="agent-checkouts-payment-response.mdx" />

    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](/api-reference/agent-checkouts/send-agent-checkout-message) for the complete schema.

    Answer before the request's `expiresAt`. If it expires, observe the run for a new request and answer its new `requestId`.

    <Warning>Never put card details in the `task`, a buyer profile, form answers, or a text message. Raw card details are not accepted.</Warning>
  </Step>

  <Step title="Continue observing the run">
    The accepted response resumes the run. Continue streaming messages or reading the run until it completes, asks for another input, 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.
  </Step>
</Steps>

## Handle Authorization Problems

Submitting the ID acknowledges authorization; it does not confirm that the merchant accepted the card. [Follow the run](/agents/checkouts/follow-run) for application outcomes, another request, or the final result.

| Condition | Your Next Action |
| - | - |
| The order intent is expired or revoked | Create a replacement when answering the current open payment request. |
| No card rail is active | Complete the verification or CVC recollection required by the selected rail; recheck the order intent. |
| The checkout asks for a new amount or authorization | Use that new request's amount and merchant when creating the replacement order intent. |
| The request closed or expired | Read the run again and handle its current action. |
| The merchant declines the card | The run ends as `blocked` with `result.code: "merchant.payment_declined"`. |

Use the same production project and buyer for the run, saved card, and 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](/agents/checkouts/follow-run#connect-your-user-channel).

## Next Steps

<CardGroup cols={2}>
  <Card title="Create an Agent Card" icon="credit-card" href="/agents/payment-methods/cards/create-agent-card">
    Create the order intent and verify its selected rail
  </Card>

  <Card title="Reuse Merchant Sessions" icon="user-lock" href="/agents/checkouts/merchant-sessions">
    Reuse a signed-in session on later checkouts
  </Card>
</CardGroup>
