Your agent finds products, opens a checkout over the Universal Commerce Protocol, and asks Walley to pay. Walley issues a Stripe Shared Payment Token for that one order, and you see every purchase in your ledger.
Paste this into Claude, ChatGPT or any agent that can make HTTP requests:
You can shop for me with my Walley wallet. Read https://walley-ten.vercel.app/llms.txt and follow it exactly. Send my Walley API key on every request as "Authorization: Bearer <my key>". Check my balance first, show me the merchant, items and total, and only pay after I say yes. Use your name as agent_name.
Get the key from Connect an agent on your dashboard. Walley runs in Stripe test mode, so no real money moves. Add test money with card 4242 4242 4242 4242.
Every Walley account has its own wallet and ledger. People sign in at /login. Agents send an API key on every request:
Authorization: Bearer wk_test_…There are two ways to get one:
curl -X POST https://walley-ten.vercel.app/api/agents/signup \
-H 'Content-Type: application/json' \
-d '{ "agent_name": "Ava (Claude)" }'201 Created
{
"account": { "id": "acct_…", "name": "Ava (Claude)", "kind": "agent" },
"api_key": "wk_test_…", // shown once: store it
"sign_in_link": "https://walley-ten.vercel.app/api/auth/link?token=wl_…",
"sign_in_link_expires_at": "…" // one use, 7 days
}Just trying it out? The public demo key wk_test_demo_scout_public opens a shared test wallet that tops itself back up. Without a valid key, wallet endpoints return 401.
Get a key
POST /api/agents/signup
Or use a key your person created on the dashboard. Send it on every call.
Check the balance
GET /api/wallet
summary.available is what the agent may spend, in cents.
Find products
GET /api/catalog?q=coffee
Each product has a merchant_id, an id and a price in cents.
Open a UCP checkout
POST /api/ucp/{merchant_id}/checkout-sessions
Nothing is charged. You get a checkout id and the total.
Ask the person
Show the merchant, items and total. Pay only after a clear yes.
Pay with Walley
POST /api/wallet/pay
Walley holds the funds, issues an SPT capped at the total, and the merchant charges it.
The purchase then shows up in GET /api/wallet and on the dashboard, with the agent's name, its reason, the SPT and a link to the Stripe payment.
Base URL https://walley-ten.vercel.app. All amounts are integers in US cents.
curl -X POST https://walley-ten.vercel.app/api/wallet/pay \
-H "Authorization: Bearer $WALLEY_KEY" \
-H 'Content-Type: application/json' \
-d '{
"merchant_id": "night-owl-coffee",
"checkout_id": "cs_ucp_0123456789abcdef0123",
"agent_name": "Ava (Claude)",
"reason": "User asked for cold brew for the office"
}'Paid
200 OK
{
"status": "completed",
"total_cents": 1400,
"order": { "id": "ord_…", "payment_intent_id": "pi_…" },
"shared_payment_token": "spt_…",
"payment_intent": "pi_…"
}Declined: nothing was charged
402 Payment Required
{
"status": "declined",
"message": "Insufficient wallet balance",
"total_cents": 3000,
"available_cents": 400,
"shortfall_cents": 2600,
"affordable_items": [],
"suggested_topup_dollars": 26
}On a decline, don't retry. Tell the person why, offer the affordable_items, or ask them to add money.
Balance hold
Funds are held before any token exists, so an agent can't overspend.
One token per order
Each SPT is capped at the exact total and expires in 15 minutes.
Per-order limit
No single agent order can go over $500.
Everything is logged
Declined attempts show as Blocked, with the agent's name and reason.
B=https://walley-ten.vercel.app
K="Authorization: Bearer wk_test_demo_scout_public" # public demo wallet; use your own key
curl -s -H "$K" "$B/api/wallet" | jq .summary
curl -s "$B/api/catalog?q=cold%20brew" | jq '.products[0]'
CID=$(curl -s -X POST "$B/api/ucp/night-owl-coffee/checkout-sessions" \
-H 'Content-Type: application/json' \
-d '{"line_items":[{"id":"NOC-COLD","quantity":1}]}' | jq -r .id)
curl -s -X POST "$B/api/wallet/pay" -H "$K" -H 'Content-Type: application/json' \
-d "{\"merchant_id\":\"night-owl-coffee\",\"checkout_id\":\"$CID\",\"agent_name\":\"curl demo\",\"reason\":\"testing Walley\"}"