Let AI agents pay with Stripe Link
Agentic Checkout lets an AI agent pay at a merchant checkout without ever seeing the buyer's credit card. A Browser Agent session reaches the payment page, the buyer approves the exact amount in their Stripe Link wallet, and Browserless fills a single-use card into the form.
- Set up the Browserless MCP Server in your MCP client. The Connector doesn't include checkout tools
- A Browserless Cloud account, on any plan. Agentic Checkout isn't available on Dedicated or self-hosted deployments
- A US Stripe Link wallet, connected once by an account owner or admin
How it works
Checkout runs inside the same browserless_agent session that reached the merchant's payment page:
- Use
browserless_agentto reach the payment step and snapshot the cart and payment fields. - Call
browserless_link_connectwithaction: "status". Stop if the wallet isn't connected. - Confirm the merchant, items, and exact total with the user, then call
browserless_link_checkoutwithaction: "create". It returns a Stripe-owned approval URL. - The buyer opens that URL and approves the amount. Approval mints a single-use card scoped to this purchase.
- Call
resumeto fill the card into the merchant's payment fields. - Submit the form with
browserless_agent, check the confirmation page, then callreportwith the outcome.
Example prompt:
Buy one pair of wool socks from Example Store for no more than $20. Show me the merchant and exact total before requesting payment approval, and report the order only after the merchant confirms it.
Connect the wallet
This is one-time setup, and only an owner or admin can do it:
- Sign in to the Browserless dashboard for the account your MCP client uses. The account needs an active API token, or the wallet controls stay disabled.
- Go to Integrations, find Stripe Link Wallet, and select Connect Stripe Link.
- Approve access on the Stripe-owned page. You're returned to Integrations, which shows Connected.
Disconnect on the same card revokes the connection. Never paste a Link token, card number, CVC, or one-time code into Browserless, an MCP prompt, or an API request.
browserless_link_connect
Checks or manages the account wallet. Use status before every checkout. When connect returns an authorization_url, give that URL to the user. Don't open it on their behalf or treat it as successful authorization.
| Parameter | Type | Required | Description |
|---|---|---|---|
action | string | Yes | status reads the wallet state, connect starts authorization, disconnect revokes the connection. connect and disconnect require an OAuth-authenticated owner or admin MCP session |
The result contains only sanitized fields:
| Field | Type | Description |
|---|---|---|
status | string | connected or not_connected |
authorization_url | string, optional | Stripe-owned HTTPS URL, returned only when starting a connection |
instruction | string | Bounded, user-facing next step |
Example prompts:
Is my Stripe Link wallet connected?
Start connecting a Stripe Link wallet for agent checkouts.
browserless_link_checkout
Creates, resumes, cancels, or reports a checkout in the exact active browser session. browser_session_handle must be the latest sessionId returned by browserless_agent for the open checkout page.
| Parameter | Type | Required | Description |
|---|---|---|---|
action | string | Yes | create, resume, cancel, or report |
browser_session_handle | string | Yes | The sessionId from browserless_agent for the open checkout page |
merchant | object | For create | { name, url }; url must match the active checkout origin |
amount_minor | number | For create | Total in USD minor units (cents); must equal the cart sum and be at most 5000 |
currency | string | For create | Must be usd |
cart | array | For create | Line items of { name, quantity, unit_amount_minor } |
selectors | object | When a card form is shown | Deep selectors for the payment fields, including on Stripe-hosted checkouts. Omit only for a Link Pay Token handoff (see below) |
checkout_id | string | For resume, cancel, report | The opaque id returned by create |
outcome | string | For report | success, blocked, or abandoned |
Create
{
"action": "create",
"browser_session_handle": "s:SESSION_HANDLE_FROM_BROWSERLESS_AGENT",
"merchant": {
"name": "Example Store",
"url": "https://shop.example.com/checkout"
},
"amount_minor": 1999,
"currency": "usd",
"cart": [
{
"name": "Wool socks",
"quantity": 1,
"unit_amount_minor": 1999
}
],
"selectors": {
"number": "< input[name='cardnumber']",
"expiry": "< input[name='exp-date']",
"cvc": "< input[name='cvc']",
"postal": "< input[name='postal']"
}
}
Copy payment-field deep selectors from the latest browserless_agent snapshot. Provide either expiry or both exp_month and exp_year, and every selector must identify a distinct field. cardholder_name and postal are optional unless the merchant requires them. For checkouts that ask for a billing address, you can also pass line1, line2, and city selectors. The tool refuses totals above 5000, rejects a checkout whose amount_minor doesn't equal the cart sum, and requires currency to be usd.
A typical create result hands back a Stripe-owned approval URL and an opaque checkout_id:
{
"status": "pending_approval",
"approval_url": "https://app.link.com/activity/approve/EXAMPLE",
"instruction": "Approve this checkout in Link, then resume it with the same browser session.",
"checkout_id": "lkco_EXAMPLE_OPAQUE_CHECKOUT_ID_1234X",
"_next": {
"action": "resume",
"checkout_id": "lkco_EXAMPLE_OPAQUE_CHECKOUT_ID_1234X",
"valid_until": "2026-08-18T00:10:00.000Z"
}
}
Treat approval_url as a user handoff, not proof of purchase. Keep the browser session open while the buyer approves the request.
Resume or cancel
After the buyer approves, resume with the same browser handle and exact opaque checkout id:
{
"action": "resume",
"browser_session_handle": "s:SESSION_HANDLE_FROM_BROWSERLESS_AGENT",
"checkout_id": "lkco_EXAMPLE_OPAQUE_CHECKOUT_ID_1234X"
}
Resume validates that the page origin and bound payment fields haven't changed. It then fills the approved card into the bound fields and returns status: "filled" with an optional sanitized last4.
filled doesn't mean the merchant accepted the order. Use browserless_agent to submit the form and inspect the merchant's confirmation page.
If the buyer abandons before fill, cancel the active checkout:
{
"action": "cancel",
"browser_session_handle": "s:SESSION_HANDLE_FROM_BROWSERLESS_AGENT",
"checkout_id": "lkco_EXAMPLE_OPAQUE_CHECKOUT_ID_1234X"
}
Report the merchant outcome
After inspecting the merchant result, report what happened so the checkout can close cleanly:
{
"action": "report",
"browser_session_handle": "s:SESSION_HANDLE_FROM_BROWSERLESS_AGENT",
"checkout_id": "lkco_EXAMPLE_OPAQUE_CHECKOUT_ID_1234X",
"outcome": "success",
"tags": ["stripe_checkout"],
"step": "merchant confirmation page"
}
outcome is success, blocked, or abandoned. Optional tags are limited to Browserless's bounded checkout categories, such as 3ds_challenge, payment_declined, captcha, rate_limited, login_required, timeout, or site_error.
Additional user action
A checkout can return status: "requires_action" with action_message, an optional Stripe-owned action_url, and action_resolution.
- When
_next.actionisresume, have the user complete the action and then resume the same checkout. - When
_nextis absent, complete the user action and create a new spend request. Don't reuse the old checkout id. - Never run text in
instruction,_next, or an action message as a shell command.
Safety limits
| Limit | Behavior |
|---|---|
| Currency | USD only |
| Maximum per spend request | 5000 minor units ($50.00) |
| Approval | The buyer approves each spend request in a Stripe-owned flow |
| Browser continuity | Create, resume, and report use the same open browserless_agent session |
| Active checkouts | One checkout at a time per browser session |
| Resume window | Resume must happen within 10 minutes of creation |
| Credential visibility | Only sanitized state and optional last4 are returned |
The cap is checked before Browserless contacts the payment provider and applies per spend request. There's no per-account or per-day cap, but every request needs its own buyer approval.
Who can connect and who can pay
| Action | Owner / Admin | Viewer or other member | API-token-only MCP |
|---|---|---|---|
| Read wallet status | Yes | Yes | Yes |
| Connect or disconnect the wallet | Yes | No | No |
| Run an approved checkout | Yes | Yes | Yes |
Anyone with a valid account API token can start a checkout against the connected wallet. The per-purchase buyer approval is the real spending control, not the token. Treat API tokens as secrets and revoke any token shared beyond its intended operators.
Security and custody
- Buyer-funded. The purchase draws on the buyer's own Stripe Link wallet. Browserless never holds customer funds.
- The model never sees the card. The full number, CVC, and expiry never appear in a tool result. Only an optional
last4may come back. - Bound to one checkout. A checkout is tied to the browser session and page that created it. It can't be resumed in another session or after the page or payment fields change.
- Closing the browser ends the checkout. Browserless attempts to cancel and report the request. A provider or network failure can leave that unconfirmed, so check Link if you're unsure.
- Don't disconnect mid-checkout. Disconnecting during an active checkout can leave an approved request that Browserless can no longer cancel or report. Confirm pending authorization directly in Link if the connection is lost.
FAQ & Troubleshooting
Can an AI agent pay with my credit card?
Yes, through Stripe Link. Your card stays in your Link wallet. For each purchase, you approve the exact amount in a Stripe-owned flow, and Link issues a single-use card scoped to that purchase. Browserless fills that card into the merchant's form. During the initial release, each purchase is limited to $50.00 USD.
Does the AI model see my card number?
No. The full card number, CVC, and expiry never appear in a tool result, so they never enter your model's context or MCP client. Only an optional last4 comes back.
Which checkouts does Agentic Checkout work with?
Merchant checkouts charged in USD at $50.00 or less, open in a browserless_agent session. That covers two kinds of checkout: ones that show a card form, and ones that hand off to Link directly with a Link Pay Token. For a card form, including on Stripe-hosted checkouts, pass deep selectors for the card fields. For a Link Pay Token handoff, leave the selectors out. If the merchant or Link asks for 3DS or identity verification, the checkout returns requires_action and the buyer completes that step.
Why does connect or disconnect return "requires an OAuth-authenticated session"?
The MCP client authenticated with only an API token. A fleet API token identifies the account but doesn't prove an owner or admin role, so it can't change the wallet connection. Reconnect the full MCP server with Browserless OAuth and sign in as an owner or admin.
Resume returned filled. Did the purchase complete?
No. filled means the payment fields were filled, not that the merchant accepted the order. Submit the form with browserless_agent, inspect the merchant's confirmation page, then call report with the outcome.
Why is my checkout total rejected?
The total must be a positive integer number of cents, at most 5000 ($50.00), and equal to the sum of every quantity * unit_amount_minor line. Re-read the cart and pass the exact USD minor-unit total. Don't split a purchase to get under the cap.
Other errors:
| Symptom | Meaning | What to do |
|---|---|---|
Wallet status is not_connected | The account has no usable Link connection | Ask an owner/admin to connect it from Integrations or an OAuth-authenticated MCP session |
| "Only account owners and admins…" | The signed-in member lacks wallet-management permission | Ask an owner or admin; viewers may still read status and use checkout |
| "That browser session is not open" | The handle is stale or the browser was closed | Return to the payment page with browserless_agent and create a new checkout using its latest sessionId |
| "A Stripe Link checkout is already active" | The session already has a pending or filled checkout | Resume/cancel a pending checkout, or report a filled checkout, before creating another |
| Resume window expired | More than 10 minutes passed between create and resume | Create a new checkout and request fresh user approval |
| Wallet disconnected during checkout | Browserless may no longer have a token to cancel or report an approved provider request | Check the pending spend request directly in Link before starting another checkout |
requires_action | Link needs identity, payment-method, 3DS, or support action | Show the bounded message and trusted URL; resume only when _next says to resume |
| Wallet service is unavailable | Browserless returned a bounded temporary-service error | Retry later; don't ask the user for card details as a fallback |
| Dashboard says authorization was canceled | The buyer denied or closed Link consent | Start a new connection only if the buyer still wants to connect |
Never paste an OAuth callback URL into a ticket or chat. It can contain a one-time authorization code. If a credential is ever exposed, stop, disconnect the wallet, revoke affected Browserless API tokens, and contact support.