SuperAPI AI Directory

agent-checkouts

Agents & models

View repository

Updated 10-15 20:29

About this skill

Crossmint Agent Checkouts

Buy any product from a URL through Crossmint's Agent Checkouts API, authorized by a single server-side API key (no user JWT). You store the key once; then create a buyer profile, create a checkout, and drive it to completion by answering the checkout's user-action prompts.

All API details live in reference/agent-checkouts-api.md. All calls go through scripts/checkout.mjs (Node.js 18+, no dependencies).

⚠️ Real money. Agent Checkouts run in production against real merchants. A successful checkout places a real, paid order. Always set a maxCost. Submitting a user action executes immediately — there is no separate confirmation step afterward. Once you checkout-respond to the action that completes the purchase, payment is charged and the order is placed. Get the user's approval of the total before that call, not after.

The command wrapper

node scripts/checkout.mjs <command> [...]

Run from the skill directory. Every command prints JSON. The key is read from $CROSSMINT_API_KEY if set, otherwise from the stored file (~/.crossmint/agent-checkouts.json, mode 0600). The host (production vs staging) is chosen automatically from the key prefix.

Step 0 — Ensure an API key is configured

Before anything else, check:

node scripts/checkout.mjs key-status
  • If configured: true, continue.
  • If configured: false, ask the user for their Crossmint server-side API key (starts with sk_production_...), then store it:
node scripts/checkout.mjs set-key sk_production_XXXXXXXX

Store the key only when the user provides it. To rotate/remove: set-key again, or clear-key. Never print the full key back — key-status shows a masked preview.

Step 1 — Ensure a buyer profile

A buyer profile holds the reusable name / contact / shipping address so you don't re-enter it each purchase.

  • If the user already has a buyerProfileId, use it (verify with profile-get <id>).
  • Otherwise offer to create one. Gather: first & last name, email, and full shipping address. Then:
node scripts/checkout.mjs profile-create '{
  "label": "Home",
  "name":    { "first": "Ada", "last": "Lovelace" },
  "contact": { "email": "ada@example.com" },
  "shipping": {
    "addressLines": ["1 Market St"],
    "locality": "San Francisco",
    "administrativeAreaCode": "US-CA",
    "postalCode": "94105",
    "countryCode": "US"
  }
}'

Capture the returned id — that's the buyerProfileId. (administrativeAreaCode is country-prefixed ISO 3166-2, e.g. US-CA; countryCode is ISO 3166-1 alpha-2.) You can also pass a file: profile-create @profile.json.

Step 2 — Create the checkout

Collect the purchase intent from the user and encode it in --request. The --request string is where you steer everything the merchant page will ask about. Resolve shipping method and payment method up front and put them in --request — every checkout needs both, and specifying them here keeps the run from stalling on an avoidable user action later. Cover, when relevant:

  • Variant / options — size, color, style, model, edition.
  • Quantity.
  • Shipping method — always include one. Ask the user, or fall back to a sensible default and state it: use "cheapest shipping" unless they need it fast (then "fastest shipping") or named a carrier/tier.
  • Payment method — always include one. Ask, or default to "pay by card" and say so. Name the method only — do not put card numbers here; if the merchant needs card details they come later as a user action.
  • Billing preference — default to "bill to the shipping address" unless the user gives a separate billing address.

If the user hasn't specified these, don't block — apply the defaults above ("cheapest shipping, pay by card, bill to shipping address"), tell the user the defaults you used, and proceed. Only ask first when the choice clearly matters (e.g. they mentioned a deadline, or multiple cards/addresses are in play).

Shopify example — buy a specific variant, cheapest shipping, card, billing same as shipping, capped at $60:

node scripts/checkout.mjs checkout-create \
  --url "https://merchant.example/products/classic-tee" \
  --request "Buy 1 of the Medium in Black. Use the cheapest shipping method. Pay by card. Bill to the same address as shipping." \
  --buyer-profile "<buyerProfileId>" \
  --max-cost "60.00" --currency "USD"

Notes:

  • --url is required; direct_url is the only supported target kind.
  • --buyer-profile prefills name/contact/shipping from Step 1.
  • --max-cost is a hard ceiling — the checkout fails (max_cost_exceeded) rather than overspending. Always set it. Use the user's stated budget, or the expected price plus a small buffer for shipping/tax, and tell the user the cap you used.
  • --merchant-context "..." adds optional navigation hints.
  • Repeat --metadata key=value to tag the checkout.

Capture the returned checkout id.

Step 3 — Poll and answer actions until terminal

Loop:

node scripts/checkout.mjs checkout-get <checkoutId>

React to status:

status what to do
queued, running Wait ~1.5s and poll again.
awaiting_user_action Handle the action (below), then poll again.
succeeded Done. Read receipt (total, merchantOrderId, evidence.confirmationUrl). Report it.
failed Read failure.reason + failure.message. Report it; offer to retry/adjust.
cancelled Report that it was cancelled.

To pace polling from the shell you can sleep between calls, e.g. sleep 2 && node scripts/checkout.mjs checkout-get <id>.

Handling awaiting_user_action

The response contains pendingUserAction with:

  • message — a human description of what's needed.
  • responseSchema — a JSON Schema for the exact values to submit. Read it each time; the fields vary per merchant/step. Never hardcode field names.
  • expiresAt — submit before this or the checkout fails (user_action_expired).

To build the values:

  1. Parse responseSchema (properties, required, enums, types).
  2. Fill every field you can from what you already know — the buyer profile, the user's stated variant/shipping/payment/billing preferences, and the checkout context (e.g. pick the shipping option matching "standard", the variant matching "Medium / Black").
  3. For anything you can't infer (an ambiguous option, a required detail the user never gave, payment/card details, a final-total confirmation), ask the user, then continue.
  4. There is no "confirm the order" action and no undo. Submitting an action runs it immediately — the action that completes the purchase charges payment and places the order the moment you call checkout-respond. So before submitting any action that finalizes the buy, show the user the total (and what you're about to submit) and get explicit approval. Approve before the call — nothing asks for confirmation after it.

Submit (the actionId is pendingUserAction.id):

node scripts/checkout.mjs checkout-respond <checkoutId> <actionId> \
  --values '{ "shippingOption": "standard", "confirm": true }'
  • --values must satisfy responseSchema (respect required fields and enums). Inline JSON or @values.json.
  • actionId goes in the path only, never in the body (the wrapper handles this).
  • Default verb is submit; pass --action cancel to abort that step if the user declines.

After submitting, poll again. Repeat until a terminal status.

Payment / card handling

Assume a usable payment method is available to the checkout (an agent card or a single-use / virtual card supplied when the payment action appears). This skill does not create payment methods. If a user action's responseSchema asks for card details, only ever provide an agent card or a single-use / virtual card number — never a reusable PAN. Ask the user for the specific value if you don't have it.

Cancelling

node scripts/checkout.mjs checkout-cancel <checkoutId>

Command reference

Command Purpose
key-status Show whether a key is configured (masked) and its environment.
set-key <key> Store a sk_... (or ck_...) key locally at 0600.
clear-key Delete the stored key.
profile-create <json|@file> Create a buyer profile → returns id.
profile-get <id> Retrieve a buyer profile.
profile-update <id> <json|@file> Update a buyer profile.
profile-delete <id> Delete a buyer profile.
checkout-create --url ... [--request ...] [--buyer-profile ...] [--max-cost ... --currency ...] [--merchant-context ...] [--metadata k=v] Create a checkout → returns id.
checkout-get <id> Poll a checkout's status.
checkout-respond <checkoutId> <actionId> --values <json|@file> [--action submit|cancel] Answer a pending user action.
checkout-cancel <id> Cancel a checkout.