Guide · AI agents · commerce

How to give your AI agent a checkout tool

Your Claude or GPT agent can decide what to buy. Giving it a tool to actually place the order — safely, without double-charging on a retry — is the part most teams underestimate. Here's what a real checkout tool needs, and how to add one in about 5 minutes.

What a "checkout tool" actually needs

A single "charge a card" function isn't a checkout tool. For an agent to transact, the tool needs four things behind it:

The retry problem (why this is hard)

Agents retry tool calls on timeouts and errors. If your "complete checkout" endpoint isn't idempotent, a network blip after the charge succeeds — but before your agent sees the response — leads the agent to call it again, creating a duplicate order and a duplicate charge. Building this correctly means keys, dedup, and careful edge-case testing on top of Stripe and your own order database.

The fix: tie completion to the checkout session. Completing the same session again returns the same order, no matter how many times the agent retries.

Two ways to build it

Roll your own: wire Stripe PaymentIntents, design an order schema and DB, implement idempotency keys and dedup, add signed webhooks, and write per-model tool schemas. Doable — it's just a project, not an afternoon.

Use OrderCore: four ready-made tools (create_checkout_session, update_checkout_session, create_payment_intent, complete_checkout_session) over REST or an MCP server, with idempotent orders and webhooks built in. Full comparison: OrderCore vs Stripe + a custom backend.

The flow, in code

Create a session for catalog line items, then complete it into an idempotent order:

const BASE = 'https://api.ordercore.ai';
// short-lived public checkout token (the agent/MCP flow)
const { token } = await (await fetch(BASE + '/v1/account/checkout-access-tokens', {
  method: 'POST', headers: { 'X-API-Key': process.env.ORDERCORE_API_KEY } })).json();
const H = { 'Content-Type': 'application/json', 'X-Checkout-Token': token };

const { session_id } = await (await fetch(BASE + '/ucp/public/checkout/sessions', {
  method: 'POST', headers: H,
  body: JSON.stringify({ line_items: [{ item: { id: SKU }, quantity: 1 }], currency: 'USD' }) })).json();

// safe to retry: the same session always resolves to the same order
const order = await (await fetch(BASE + `/ucp/public/checkout/sessions/${session_id}/complete`, {
  method: 'POST', headers: H,
  body: JSON.stringify({ session_id, payment_data: { handler_id: 'card', payment_intent_id: 'pi_...' } }) })).json();

Expose those calls to your model as tools — or point Claude/GPT at the ready-made MCP server. Machine-readable schemas for OpenAI, Claude, Gemini, DeepSeek, and Grok live at /direct-ai/tooling.

See it prove idempotency (no signup)

The runnable demo completes the same session twice and asserts you get one order, not two. It runs offline in mock mode — no key, no signup — so you can judge it in 30 seconds:

Run the 5-minute demo → Full quickstart (JS + curl)

Related