Quickstart
Want to shop with an AI agent? Follow the customer-facing Claude Code guide for our verified setup. The same MCP endpoint is available to Codex, OpenCode, Hermes Agent, OpenClaw, and other compatible clients. The rest of this page is an implementation reference for integration developers.
The Store exposes multiple interfaces on a single deployment:
- SSH (port 2222) — Human TUI experience
- HTTP (port 3000) — REST API, ACP, UCP, and webhooks
- MCP (port 8080) — Model Context Protocol server for LLM tool use
All prices are in cents (integer). $9.99 = 999.
Browse products (no auth required)
curl https://storeapi.globalringai.com/api/v1/products
Filter by category or search
# By category
curl "https://storeapi.globalringai.com/api/v1/products?category=Software"
# By keyword
curl "https://storeapi.globalringai.com/api/v1/products?q=keycap"
# In-stock only
curl "https://storeapi.globalringai.com/api/v1/products?in_stock=true"
Authenticated development access
Production API keys are issued by The Store operator with a fixed role, exact scopes, budget, and expiration. Public self-service key creation is not available. The local --gen-api-key command is an operator-only development utility and is not a customer onboarding path.
Authentication
Pass your API key via the Authorization header:
Authorization: Bearer ${THESTORE_BUYER_TOKEN}
Scopes
| Scope | Grants |
cart:read | Get cart contents |
cart:write | Create sessions, add/update/remove items |
checkout:write | Create checkouts, ACP/UCP sessions |
orders:read | List and view orders |
Budget Controls
API keys can have spending limits. Budget is checked at checkout and incremented when payment completes (via webhook for Stripe, immediately for SPT).
| Field | Description |
budget_limit | Max spend in cents per period (null = unlimited) |
budget_spent | Running total of completed transactions |
budget_period | daily, weekly, monthly, or lifetime |
categories | Optional category restrictions (empty = unrestricted) |
Error Format
All endpoints return errors in a standard envelope:
{
"error": {
"code": "not_found",
"message": "Product not found"
}
}
| HTTP | Code | Meaning |
| 400 | invalid_request | Bad JSON, missing fields, invalid state |
| 401 | unauthorized | Missing/invalid API key or signature |
| 403 | forbidden | Missing scope, wrong owner, or budget exceeded |
| 404 | not_found | Resource not found |
| 405 | method_not_allowed | Wrong HTTP method |
| 409 | out_of_stock | Insufficient inventory |
| 500 | internal_error | Server error |
REST API
Session-based shopping for HTTP clients. Base path: /api/v1
Quickstart: Place an Order
# 1. Browse products (no auth)
curl https://storeapi.globalringai.com/api/v1/products
# 2. Create a session
curl -X POST -H "Authorization: Bearer tsk_..." \
https://storeapi.globalringai.com/api/v1/sessions
# 3. Add to cart (use session_id from step 2 and copy a product id/tspn from step 1)
curl -X POST -H "Authorization: Bearer ***" \
-H "Content-Type: application/json" \
-d '{"product_id": "TSPN-...", "quantity": 1}' \
https://storeapi.globalringai.com/api/v1/sessions/{session_id}/cart/items
# 4. Checkout
curl -X POST -H "Authorization: Bearer tsk_..." \
-H "Content-Type: application/json" \
-d '{"email": "buyer@example.com"}' \
https://storeapi.globalringai.com/api/v1/sessions/{session_id}/checkout
# Response includes checkout_url — open in browser to pay
Catalog (Public)
| Method | Endpoint | Description |
| GET | /api/v1/products | List products. Query params: category, q, in_stock |
| GET | /api/v1/products/{id} | Get product details |
Sessions & Cart
| Method | Endpoint | Scope | Description |
| POST | /api/v1/sessions | cart:write | Create shopping session |
| GET | /api/v1/sessions/{id}/cart | cart:read | Get cart contents |
| POST | /api/v1/sessions/{id}/cart/items | cart:write | Add item. Body: {"product_id", "quantity"} |
| PUT | /api/v1/sessions/{id}/cart/items/{pid} | cart:write | Update quantity. Body: {"quantity"} |
| DEL | /api/v1/sessions/{id}/cart/items/{pid} | cart:write | Remove item |
Checkout & Orders
| Method | Endpoint | Scope | Description |
| POST | /api/v1/sessions/{id}/checkout | checkout:write | Initiate checkout. Body: {"email", "name", "shipping_address"} (all optional) |
| GET | /api/v1/account | any | Get API key info, budget, scopes |
| GET | /api/v1/orders | orders:read | List orders (most recent 50) |
| GET | /api/v1/orders/{id} | orders:read | Get order details |
Response Shapes
Success responses are wrapped in {"data": {...}}. Key shapes:
// Product
{"id", "tspn", "name", "type", "price", "price_currency", "price_formatted",
"description", "category", "stock", "stock_status", "in_stock"}
// Cart
{"session_id", "items": [{"product_id", "name", "price", "price_currency",
"price_formatted", "quantity", "subtotal"}],
"total", "price_currency", "total_formatted", "item_count"}
// Checkout
{"order_id", "checkout_url", "total", "total_formatted"}
// Order
{"order_id", "email", "total", "price_currency", "total_formatted", "status",
"items": [{"product_id", "name", "price", "price_currency",
"price_formatted", "quantity", "subtotal", "subtotal_formatted"}],
"created_at"}
Agent Commerce Protocol (ACP)
Single-session checkout for AI agents with line items, fulfillment, and budget tracking. Base path: /acp/v1
Quickstart: Agent Checkout with Stripe
# 1. Create checkout session
curl -X POST -H "Authorization: Bearer ***" \
-H "Content-Type: application/json" \
-d '{
"line_items": [{"product_id": "PRODUCT_ID", "quantity": 2}],
"customer_email": "agent@example.com"
}' \
https://storeapi.globalringai.com/acp/v1/checkout_sessions
# 2. After reviewing the authoritative quote, complete without a token
curl -X POST -H "Authorization: Bearer ***" \
-H "Content-Type: application/json" \
-d '{}' \
https://storeapi.globalringai.com/acp/v1/checkout_sessions/{id}/complete
# Response: status "awaiting_payment", checkout_url for Stripe
# Payment confirmed asynchronously via webhook
Endpoints
| Method | Endpoint | Description |
| POST | /acp/v1/checkout_sessions | Create session with line items |
| GET | /acp/v1/checkout_sessions/{id} | Get session state |
| POST | /acp/v1/checkout_sessions/{id} | Update (items, address, shipping, customer) |
| POST | /acp/v1/checkout_sessions/{id}/complete | Create Stripe Checkout or consume a separately issued approval |
| POST | /acp/v1/checkout_sessions/{id}/cancel | Cancel session |
All endpoints require checkout:write scope.
Session Lifecycle
┌──────────────────┐
Digital items │ ready_for_payment │ Physical items
──────────────►│ │◄────────────────
└────────┬─────────┘ (after address
│ provided)
┌──────────────┼──────────────┐
│ │ │
signed approval no token cancel
│ │ │
▼ ▼ ▼
completed awaiting_payment canceled
│
webhook confirms
│
▼
completed
Physical goods start as not_ready_for_payment until a fulfillment address is provided via update.
Create Request
{
"line_items": [ // required, at least 1
{"product_id": "...", "quantity": 1}
],
"customer_email": "...", // optional
"customer_name": "...", // optional
"currency": "usd" // optional, default "usd"
}
Update Request
{
"line_items": [...], // optional, replaces items
"fulfillment_address": { // optional, for physical goods
"name": "...", "line1": "...", "line2": "...",
"city": "...", "state": "...", "zip": "...", "country": "..."
},
"selected_fulfillment": "express", // optional: "standard" ($5) or "express" ($15)
"customer_email": "...", // optional
"customer_name": "..." // optional
}
Session Response
{
"id": "uuid",
"status": "ready_for_payment",
"line_items": [{"product_id", "name", "description",
"quantity", "unit_price", "currency"}],
"fulfillment_address": null | {...},
"fulfillment_options": [
{"id": "standard", "label": "Standard Shipping (5-7 days)", "cost": 500, "currency": "usd"},
{"id": "express", "label": "Express Shipping (2-3 days)", "cost": 1500, "currency": "usd"}
],
"selected_fulfillment": null | "standard" | "express",
"customer_email": "...",
"customer_name": "...",
"totals": {"subtotal": 999, "tax": 0, "shipping": 0, "total": 999, "currency": "usd"},
"order_id": null,
"checkout_url": null,
"created_at": "2026-...",
"expires_at": "2026-..." // 1 hour from creation
}
Payment authorization
Ordinary user-present checkout omits payment_token and returns secure Stripe Checkout. Delegated completion requires a real, short-lived authorization issued through The Store's separately authenticated approval flow and bound to the exact current checkout snapshot. Example token strings are intentionally not published because they would not be valid authorizations.
Optional: HMAC Signature
If ACP_HMAC_SECRET is configured, all requests must include:
Signature: hex(HMAC-SHA256(request_body, secret))
Unified Commerce Protocol (UCP)
Standardized checkout with service discovery. Base path: /ucp/v1
Quickstart: Discover and Checkout
# 1. Discover capabilities
curl https://storeapi.globalringai.com/.well-known/ucp
# 2. Browse the canonical catalog and copy the selected variant's id/tspn
curl -H "Authorization: Bearer ***" \
"https://storeapi.globalringai.com/api/v1/products?in_stock=true"
# 3. Create session using that canonical variant identifier
curl -X POST -H "Authorization: Bearer ***" \
-H "Content-Type: application/json" \
-d '{
"line_items": [{"product_id": "TSPN-...", "quantity": 1}],
"customer_email": "agent@example.com"
}' \
https://storeapi.globalringai.com/ucp/v1/checkout-sessions
# 4. Add shipping (physical good)
curl -X PUT -H "Authorization: Bearer tsk_..." \
-H "Content-Type: application/json" \
-d '{
"fulfillment_address": {"line1": "123 Main St", "city": "Portland", "state": "OR", "zip_code": "97201", "country": "US"},
"selected_fulfillment": "standard"
}' \
https://storeapi.globalringai.com/ucp/v1/checkout-sessions/{id}
# 5. After reviewing the quote, create secure Stripe Checkout
curl -X POST -H "Authorization: Bearer ***" \
-H "Content-Type: application/json" \
-d '{}' \
https://storeapi.globalringai.com/ucp/v1/checkout-sessions/{id}/complete
Discovery Manifest
GET /.well-known/ucp
{
"version": "1.0",
"name": "The Store",
"description": "A cyberpunk e-commerce store...",
"services": [{"type": "checkout", "base_url": "/ucp/v1/checkout-sessions"}],
"capabilities": [
"checkout.create", "checkout.update",
"checkout.complete", "checkout.cancel",
"fulfillment.address", "fulfillment.options"
]
}
Endpoints
| Method | Endpoint | Description |
| GET | /.well-known/ucp | Discovery manifest (no auth) |
| POST | /ucp/v1/checkout-sessions | Create session |
| GET | /ucp/v1/checkout-sessions/{id} | Get session state |
| PUT | /ucp/v1/checkout-sessions/{id} | Update session |
| POST | /ucp/v1/checkout-sessions/{id}/complete | Finalize (SPT or Stripe) |
| POST | /ucp/v1/checkout-sessions/{id}/cancel | Cancel session |
Key Differences from ACP
| Aspect | ACP | UCP |
| Base path | /acp/v1/checkout_sessions | /ucp/v1/checkout-sessions |
| Update method | POST | PUT |
| Address zip field | zip | zip_code |
| Money format | Flat: "subtotal": 999 | Nested: "subtotal": {"amount": 999, "currency": "usd"} |
| Status names | ready_for_payment | ready_for_complete |
| HMAC header | Signature | Request-Signature |
| Discovery | None | /.well-known/ucp |
UCP Status Mapping
| Internal | UCP Status |
not_ready_for_payment | incomplete |
ready_for_payment | ready_for_complete |
awaiting_payment | requires_escalation |
completed | completed |
canceled | incomplete |
Model Context Protocol (MCP)
Native LLM tool integration via JSON-RPC 2.0 over authenticated Streamable HTTP.
Invite-only beta MCP client setup
Claude Code is the currently verified client. Invited buyers using Claude should follow the complete Shop with Claude guide. The verified configuration command is:
claude mcp add --scope user --transport http thestore \
https://storemcp.globalringai.com/ \
--header 'Authorization: Bearer ${THESTORE_BUYER_TOKEN}'
The environment-variable reference is stored literally. Launch Claude with the variable loaded from your protected credential file; never paste the raw value into this command or into Claude chat.
Codex, OpenCode, Hermes Agent, OpenClaw, and other MCP-compatible clients can connect to https://storemcp.globalringai.com/ with the same issued bearer credential. Use the client’s documented mechanism for an authenticated Streamable HTTP MCP server, and keep the raw credential in a protected file or process environment rather than pasting it into chat or source control.
The invite-only beta requires its issued buyer token at the MCP transport boundary. Missing or incorrect credentials receive 401 Unauthorized. Public OAuth and browser consent are not implemented yet.
Configuration
| Env Var | Required | Description |
Authorization request header | Yes | Caller-specific buyer bearer; the MCP server forwards the same identity to The Store |
THESTORE_API_URL | No | Store API base URL (default: http://localhost:3000) |
MCP_PORT | No | Listen port (default: 8080) |
Advanced tool reference (19)
Ordinary shoppers should not need these names. The MCP server instructs the connected agent to search, compare, collect only missing delivery information, present an authoritative quote, wait for explicit confirmation, open Stripe Checkout, and report verified order status.
| Category | Tool | Input |
| Catalog | search_products | category?, query? |
get_product | product_id |
| Shopping | create_session | (none) |
add_to_cart | session_id, product_id, quantity? |
view_cart | session_id |
checkout | session_id, email?, name?, shipping_address? |
get_order | order_id |
get_account | (none) |
list_orders | (none) |
| ACP | acp_create_session | line_items, email?, name?, currency? |
acp_get_session | session_id |
acp_update_session | session_id, line_items?, customer_email?, customer_name? |
acp_complete_session | session_id, payment_token? |
acp_cancel_session | session_id |
| UCP | ucp_create_session | line_items, email?, name?, currency? |
ucp_get_session | session_id |
ucp_update_session | session_id, line_items?, customer_email?, customer_name? |
ucp_complete_session | session_id, payment_token? |
ucp_cancel_session | session_id |
Resources
| URI | Type | Description |
thestore://catalog | Static | Full product catalog as Markdown |
thestore://products/{id} | Template | Single product details as JSON |
Prompts
| Name | Args | Description |
shopping_assistant | task? | Pre-built shopping assistant with inventory context and all tool references |
Trusted Agent Protocol (TAP)
Optional RFC 9421 HTTP message signatures for cryptographic request authentication. TAP is additive — requests without TAP headers pass through normally. Invalid signatures get 401.
Quickstart: Sign a Request
# 1. Place your Ed25519 public key PEM in the TAP keys directory:
# $TAP_KEYS_DIR/my-agent.pem
# 2. Enable TAP on the server:
# TAP_ENABLED=true TAP_KEYS_DIR=/app/tap-keys
# 3. Sign your request with these headers:
Signature-Input: sig1=("@method" "@target-uri" "content-type");\
created=1709000000;keyid="my-agent";alg="ed25519";\
nonce="unique-value-123"
Signature: sig1=:base64-ed25519-signature:
Signature Construction
Build the canonical signature base, then sign with Ed25519:
# Signature base (one line per component + params):
"@method": POST
"@target-uri": https://storeapi.globalringai.com/api/v1/orders
"content-type": application/json
"@signature-params": ("@method" "@target-uri" "content-type");\
created=1709000000;keyid="my-agent";alg="ed25519";nonce="abc123"
Signable Components
| Component | Value |
@method | HTTP method (GET, POST, etc.) |
@target-uri | Full URI with scheme and host |
@path | Path component only |
@authority | Host header |
@scheme | http or https |
@request-target | Path + query string |
| Any header name | Header value (e.g. "content-type") |
Validation Rules
- Timestamp skew: ±8 minutes
- Nonce replay: Rejected if seen within 16-minute window
- Algorithm:
ed25519 only
- Key format: PEM-encoded Ed25519 public keys, filename = key ID
Configuration
| Env Var | Description |
TAP_ENABLED | true to enable TAP middleware |
TAP_KEYS_DIR | Directory of {keyid}.pem files |
Identity Injection
After successful verification, a TAPIdentity is injected into the request context with KeyID, Tag, Algorithm, and Verified=true. Handlers can use this for additional authorization decisions.
x402 Payment Protocol
x402 checkout settlement is not available in this release. User-present purchases use secure Stripe Checkout. The Store will not advertise or accept x402 order payment until settlement is bound atomically to an authoritative quote and resulting order.
Webhooks
| Method | Endpoint | Events |
| POST |
/webhook/stripe |
checkout.session.completed, checkout.session.expired |
Paid checkout.session.completed
Finalization occurs only when Stripe reports payment_status=paid and the signed amount and currency match the immutable local order.
- Order status:
pending → paid
- Product stock decremented
- API key
budget_spent incremented
- Linked ACP/UCP session:
awaiting_payment → completed
- Real-time event published to connected TUI sessions
checkout.session.expired
- Order status:
pending → expired
- No stock or budget changes
- Event published to TUI sessions
Protocol Comparison
| Feature |
REST |
ACP |
UCP |
MCP |
TAP |
| Purpose | Shopping | Agent checkout | Unified checkout | LLM tools | Request signing |
| Auth | API Key | API Key + HMAC? | API Key + HMAC? | API Key | Ed25519 sig |
| Payment | Stripe | Stripe / separate approval | Stripe / separate approval | via ACP/UCP | N/A |
| Fulfillment | No | Yes | Yes | via ACP/UCP | N/A |
| Budget | At checkout | Yes | Yes | Yes | N/A |
| Discovery | No | No | .well-known | Tool list | N/A |