Troubleshooting
401 on buyer-bound calls (key + bearer)
The API prefers X-API-Key over a bearer, so a crypto prepare/complete or
/account/mcp call that sends both resolves as the platform identity and the
buyer is never loaded. Send the buyer bearer only on those calls.
missing_request_id / missing_ucp_agent
Every Direct UCP shopping call (MCP and REST) needs a Request-Id header and a
UCP-Agent: profile="…" header. The buyer-account surface (/account/mcp) needs
neither. See Direct UCP → transport preamble.
”Tool … requires meta.ucp-agent.profile”
On the MCP transport you must repeat the profile in the body as
meta["ucp-agent"].profile in addition to the UCP-Agent header. The header
clears the transport guard; the body clears the tool layer.
missing_idempotency_key
State-changing REST calls (cart/checkout create/update/cancel, complete)
require an Idempotency-Key header. On MCP, use the body
meta["idempotency-key"] instead.
404 on a checkout call
The REST checkout base path is /s/:slug/checkout-sessions (not /checkouts):
POST /s/:slug/checkout-sessions, then …/:id/complete, …/:id/payment-intent,
…/:id/cancel.
Wrong handler_id / rail not selected
Select a rail by the handler’s inner id — artos.card or artos.crypto — not the
sh.artos.card / sh.artos.crypto registry key from the profile.
”Tool … requires meta[idempotency-key]”
State-changing Direct UCP tools (cart/checkout create/update/cancel,
complete_checkout) require meta["idempotency-key"]. Reusing a key with
different params is rejected — generate a fresh key per logical attempt and reuse
it only to retry the same call.
Validation error on cart/checkout line items
Raw UCP line items are { "item": { "id": "…" }, "quantity": n }, not the
bridge’s flat { id, quantity }. Args are also wrapped under
catalog/cart/checkout.
Catalog price filter returns the wrong range
Bridge search_products price is major units (dollars: max: 100); raw UCP
search_catalog price is minor units (cents: max: 10000). Don’t mix them.
Crypto checkout fails after OAuth
OAuth consent (Connected apps) is not the AP2 spend mandate (Agents). Authorize the agent under My Artos → Agents and set caps. Exceeding a cap fails completion before any order is placed.
payment_selection_required
The store offers more than one rail and none was selected. Read
ucp.payment_handlers, ask the buyer, and retry confirm_purchase /
complete_checkout with payment_method (the handler id) set. No order is placed
on the gated call.
mandate_expired / mandate_scope_mismatch
The AP2 mandate must carry a future exp and bind merchant to the store slug,
over the live re-priced terms. Mint a fresh mandate bound to the current quote.
CIMD redirect_uri is not registered
Add every callback (including http://localhost:8898/oauth/callback) to the
published oauth-client.json redirect_uris and redeploy. CIMD docs are
TTL-cached (~600s) — restart the local API in dev to flush.
invalid_api_key on a fresh database
Seed the platform agent credential (pnpm seed in artos-api creates
ck_artos_agent.…). A fresh DB without the seed 401s store tool calls.
Silent refresh not working
All three must line up: the AS advertises offline_access, the resource returns
401 with WWW-Authenticate: Bearer error="invalid_token", and your client
relays that 401 + header (doesn’t flatten it). The client must have requested
offline_access and stored the rotated refresh token.
No webhooks received
Confirm ucp.webhookUrl / UCP_WEBHOOK_URL is set and HTTPS. A blank URL
disables webhooks silently. Verify signatures before acting; reconcile missed
deliveries by polling get_order / get_my_order.
Native Connector can’t reach localhost
Anthropic’s Connector OAuth runs in the cloud and can’t reach a localhost dev
stack. Use mcp-remote for local dev, and set NODE_EXTRA_CA_CERTS to your
mkcert root CA for dev TLS. See Local development.
Deep reference
AGENT-COMMERCE-FLOW.md in artos-mcp-bridge.