{"openapi":"3.1.0","info":{"title":"Fast Shop API","version":"1.4.0","description":"Order physical products from Walmart via AI agents using x402 payments.\n\nOrderable retailers: Walmart. Home Depot is currently search/product-details only.\n\nWorkflow: `GET /search` (free) -> `GET /products/{product_id}` (free, details + offers) -> `POST /quote` (free) -> `POST /orders` (x402, returns 202) -> `GET /orders/:id` (track) -> `POST /orders/:id/cancel` (if pending).\n\nx402 payment: requests returning 402 require USDC payment. Use `x402Pay` from `@fastxyz/x402-client` to handle automatically.\n\nAuth: wallet signature (Ed25519) for `GET /orders`, `GET /orders/:id`, `POST /orders/:id/cancel`. Format: `Authorization: Bearer base64(address:timestamp).base64(signature)`.\n\nRate limits: 60 req/min. Max 10 active orders per wallet.\n\nFull guide with code examples: `GET /skill.md`."},"servers":[{"url":"/","description":"Current server"}],"components":{"schemas":{"SearchResponse":{"type":"object","properties":{"results":{"type":"array","items":{"$ref":"#/components/schemas/SearchResult"}}},"required":["results"]},"SearchResult":{"type":"object","properties":{"product_id":{"type":"string","description":"Retailer product ID (e.g. Walmart item ID)"},"title":{"type":"string"},"url":{"type":"string","description":"Direct product URL, ready for POST /quote"},"price":{"type":"number","nullable":true,"description":"Product price in cents"},"retailer":{"type":"string","description":"Retailer identifier"},"image":{"type":"string","nullable":true,"description":"Product image URL"},"num_reviews":{"type":"number","nullable":true,"description":"Number of customer reviews"},"stars":{"type":"number","nullable":true,"description":"Star rating (may be null for some retailers)"},"fresh":{"type":"boolean","description":"Grocery/fresh item flag"}},"required":["product_id","title","url","price","retailer","image","num_reviews","stars"],"additionalProperties":{"nullable":true}},"Error":{"type":"object","properties":{"error":{"type":"string"},"detail":{"type":"string"}},"required":["error"]},"ProductDetails":{"type":"object","properties":{},"additionalProperties":{"nullable":true}},"QuoteResponse":{"type":"object","properties":{"quote_id":{"type":"string","format":"uuid"},"product_total_cents":{"type":"integer","example":1828,"description":"Sum of product prices from search results"},"max_price_cents":{"type":"integer","example":2828,"description":"Budget including shipping/tax buffer (calculated automatically)"},"order_fee_cents":{"type":"integer","example":100,"description":"$1 order processing fee"},"total_cents":{"type":"integer","example":2928,"description":"Total payment: max_price + order fee"},"price_usdc":{"type":"string","example":"29.28"},"fast_address":{"type":"string","example":"fast1..."},"network":{"type":"string","example":"fast-testnet"},"expires_at":{"type":"string","format":"date-time"},"note":{"type":"string","example":"Product: $18.28. Shipping/tax buffer added automatically. $1 order fee. Unused budget refunded after placement."}},"required":["quote_id","product_total_cents","max_price_cents","order_fee_cents","total_cents","price_usdc","fast_address","network","expires_at","note"]},"CreateQuoteRequest":{"type":"object","properties":{"products":{"type":"array","items":{"allOf":[{"$ref":"#/components/schemas/Product"},{"type":"object","properties":{"price_cents":{"type":"integer","minimum":100,"example":1828,"description":"Product price in cents from search results (required, minimum $1)"}},"required":["price_cents"]}]},"minItems":1},"shipping_address":{"$ref":"#/components/schemas/Address"}},"required":["products","shipping_address"]},"Product":{"type":"object","properties":{"url":{"type":"string","format":"uri","example":"https://www.walmart.com/ip/Matcha-Green-Tea-Powder/5236782001"},"quantity":{"type":"integer","minimum":1,"maximum":100,"default":1},"price_cents":{"type":"integer","minimum":100,"example":1828,"description":"Product price in cents from search results (minimum $1)"},"variant":{"type":"array","items":{"type":"object","properties":{"label":{"type":"string"},"value":{"type":"string"}},"required":["label","value"]}}},"required":["url"]},"Address":{"type":"object","properties":{"first_name":{"type":"string"},"last_name":{"type":"string"},"address_line1":{"type":"string"},"address_line2":{"type":"string"},"city":{"type":"string"},"state":{"type":"string","minLength":2,"maxLength":2,"example":"NY","description":"2-letter US state code"},"postal_code":{"type":"string"},"phone_number":{"type":"string","pattern":"^\\d{10}$","example":"2125551234"},"country":{"type":"string","enum":["US"],"default":"US","description":"Only US shipping is supported"}},"required":["first_name","last_name","address_line1","city","state","postal_code","phone_number"]},"QueuedOrderResponse":{"type":"object","properties":{"order_id":{"type":"string","format":"uuid"},"status":{"type":"string","enum":["pending"]}},"required":["order_id","status"]},"PaymentRequired":{"type":"object","properties":{"error":{"type":"string"},"accepts":{"type":"array","items":{"type":"object","properties":{"scheme":{"type":"string"},"network":{"type":"string"},"maxAmountRequired":{"type":"string"},"payTo":{"type":"string"},"asset":{"type":"string"},"resource":{"type":"string"},"description":{"type":"string"},"mimeType":{"type":"string"},"maxTimeoutSeconds":{"type":"number"}},"required":["scheme","network","maxAmountRequired","payTo","asset","resource","description","mimeType","maxTimeoutSeconds"]}},"payer":{"type":"string"}},"required":["error","accepts"]},"CreateOrderRequest":{"type":"object","properties":{"quote_id":{"type":"string","format":"uuid"}},"required":["quote_id"]},"OrderDetail":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"quote_id":{"type":"string","format":"uuid"},"fulfillment_id":{"type":"string","nullable":true},"status":{"type":"string","enum":["pending","processing","placed","failed","cancelled","submission_unknown"]},"max_price_cents":{"type":"integer"},"actual_total_cents":{"type":"integer","nullable":true},"price_components":{"type":"object","nullable":true,"properties":{"subtotal":{"type":"integer"},"shipping":{"type":"integer"},"tax":{"type":"integer"},"total":{"type":"integer"}},"required":["subtotal","shipping","tax","total"],"description":"Actual price breakdown from retailer (available after order is placed)"},"payer_address":{"type":"string","nullable":true},"payment_nonce":{"type":"integer","nullable":true},"tracking_numbers":{"type":"array","nullable":true,"items":{"$ref":"#/components/schemas/TrackingNumber"}},"fulfillment_items":{"type":"array","nullable":true,"items":{"$ref":"#/components/schemas/OrderItem"}},"fulfillment_status":{"type":"string","nullable":true},"products":{"type":"array","nullable":true,"items":{"$ref":"#/components/schemas/Product"}},"shipping_address":{"allOf":[{"$ref":"#/components/schemas/Address"},{"nullable":true}]},"error_type":{"type":"string","nullable":true},"error_message":{"type":"string","nullable":true},"refund_status":{"type":"string","nullable":true,"enum":["pending","sent","failed",null],"description":"Refund status: pending (claimed), sent (on-chain), failed (will retry)"},"refund_nonce":{"type":"integer","nullable":true},"refund_amount_usdc":{"type":"string","nullable":true},"created_at":{"type":"string"},"updated_at":{"type":"string"}},"required":["id","quote_id","fulfillment_id","status","max_price_cents","actual_total_cents","payer_address","tracking_numbers","error_type","error_message","created_at","updated_at"]},"TrackingNumber":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"carrier":{"type":"string","example":"ups"},"tracking_number":{"type":"string","example":"1Z999AA10123456784"},"tracking_url":{"type":"string","nullable":true,"example":"https://www.ups.com/track?tracknum=1Z999AA10123456784"},"created_at":{"type":"string","format":"date-time"}},"required":["id","carrier","tracking_number","tracking_url","created_at"]},"OrderItem":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"url":{"type":"string"},"quantity":{"type":"integer"},"variant":{"type":"array","nullable":true,"items":{"type":"object","properties":{"label":{"type":"string"},"value":{"type":"string"}},"required":["label","value"]}},"status":{"type":"string","enum":["pending","processing","ordered","shipped","delivered","cancelled","failed"]},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"}},"required":["id","url","quantity","status","created_at","updated_at"]},"OrderListResponse":{"type":"object","properties":{"orders":{"type":"array","items":{"$ref":"#/components/schemas/OrderDetail"}}},"required":["orders"]},"CancelOrderResponse":{"type":"object","properties":{"order_id":{"type":"string"},"status":{"type":"string","enum":["cancelled"]},"refund_status":{"type":"string"}},"required":["order_id","status","refund_status"]},"WebhookEvent":{"type":"object","properties":{"event":{"type":"string","enum":["order.started","order.placed","order.failed","order.tracking_received"],"example":"order.placed"},"order_id":{"type":"string"},"data":{"type":"object","properties":{"price_components":{"type":"object","properties":{"subtotal":{"type":"number"},"shipping":{"type":"number"},"tax":{"type":"number"},"total":{"type":"number"}},"required":["total"],"additionalProperties":{"nullable":true}},"tracking_numbers":{"type":"array","items":{"type":"object","properties":{"carrier":{"type":"string"},"tracking_number":{"type":"string"}},"required":["carrier","tracking_number"]}},"items":{"type":"array","items":{"nullable":true}},"error_type":{"type":"string"},"error":{"type":"string"}}}},"required":["event","order_id"]},"HealthResponse":{"type":"object","properties":{"status":{"type":"string","example":"ok"}},"required":["status"]}},"parameters":{}},"paths":{"/search":{"get":{"tags":["Search"],"summary":"Search products on a retailer (free)","description":"Search for products on supported retailers. Walmart results can be used for POST /quote; Home Depot is currently search/product-details only. Free, no payment or wallet required. Returns structured product data with prices in cents and direct product URLs. Rate limit: 60 requests/minute.","parameters":[{"schema":{"type":"string","example":"airpods"},"required":true,"name":"q","in":"query"},{"schema":{"type":"string","enum":["amazon","walmart","homedepot"],"example":"walmart","description":"Retailer to search"},"required":true,"description":"Retailer to search","name":"retailer","in":"query"},{"schema":{"type":"string","example":"10","description":"Max results to return (default 10, max 20)"},"required":false,"description":"Max results to return (default 10, max 20)","name":"max_results","in":"query"}],"responses":{"200":{"description":"Product search results","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SearchResponse"}}}},"400":{"description":"Missing or invalid query parameters","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"502":{"description":"Search failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/products/{product_id}":{"get":{"tags":["Products"],"summary":"Get product details and offers (free)","description":"Get full product details and seller offers for a product. Returns description, images, features, and all seller offers with prime/shipping/pricing info. Use the product_id from search results. Free, no payment required. Rate limit: 60 requests/minute.","parameters":[{"schema":{"type":"string","example":"5236782001","description":"Retailer product ID (e.g. Walmart item ID)"},"required":true,"description":"Retailer product ID (e.g. Walmart item ID)","name":"product_id","in":"path"},{"schema":{"type":"string","enum":["amazon","walmart","homedepot"],"example":"walmart","description":"Retailer identifier"},"required":true,"description":"Retailer identifier","name":"retailer","in":"query"}],"responses":{"200":{"description":"Product details with offers","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProductDetails"}}}},"400":{"description":"Missing or invalid parameters","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"502":{"description":"Failed to fetch product data","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/quote":{"post":{"tags":["Orders"],"summary":"Get a price quote","description":"Create a price quote for a Walmart order. Provide products with price_cents from search results. A retailer-aware shipping/tax buffer is added automatically, plus a $1 order fee. The response shows product_total_cents, max_price_cents (with buffer), and total_cents. Any unused budget is refunded automatically in USDC after the order ships. Quotes expire after 10 minutes. Only US shipping addresses are supported.","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateQuoteRequest"}}}},"responses":{"201":{"description":"Quote created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/QuoteResponse"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/orders":{"post":{"tags":["Orders"],"summary":"Place an order (x402 payment required)","description":"Place an order using the x402 payment protocol. Use `x402Pay({ url, method: \"POST\", body, wallet })` from `@fastxyz/x402-client` to handle payment automatically -- it detects the 402, pays the quote amount, and retries with the certificate. Do NOT manually construct the X-PAYMENT header. See GET /skill.md for full setup and working code. After the order is placed, any unused budget is refunded automatically. The $1 order fee is non-refundable on placed orders. If an order fails, you receive a full refund including the order fee. Order lifecycle: pending -> processing -> placed (success) or failed (refunded) or cancelled (user cancelled, fully refunded). If submission is uncertain (202), poll GET /orders/:id to resolve. Rate limit: 60 requests/minute.","parameters":[{"schema":{"type":"string","description":"x402 payment certificate (base64-encoded)"},"required":false,"description":"x402 payment certificate (base64-encoded)","name":"x-payment","in":"header"}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateOrderRequest"}}}},"responses":{"202":{"description":"Order accepted and queued for processing. Poll GET /orders/:id for status updates.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/QueuedOrderResponse"}}}},"400":{"description":"Invalid request or malformed X-PAYMENT header","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"Payment required — send Fast USDC and include the certificate","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PaymentRequired"}}}},"404":{"description":"Quote not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Quote already used — returns existing order_id","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"410":{"description":"Quote expired — create a new quote","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Too many active orders or daily spend limit reached","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"502":{"description":"Order placement failed — payment is refunded automatically","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"get":{"tags":["Orders"],"summary":"List your orders","description":"Returns all orders for the authenticated wallet address.\n\nRequires wallet signature authentication via the Authorization header.\n\n**Format:** `Authorization: Bearer <base64(address:timestamp)>.<base64(signature)>`\n\nWhere:\n- `address`: your Fast wallet address (`fast1...`)\n- `timestamp`: current unix timestamp in seconds\n- `signature`: Ed25519 signature of `address:timestamp` using your wallet key\n\nTokens expire after 60 seconds.\n\n**Example using @fastxyz/sdk:**\n\n```ts\nimport { FastWallet, FastProvider } from '@fastxyz/sdk';\n\nconst provider = new FastProvider({ network: 'mainnet' });\nconst wallet = await FastWallet.fromPrivateKey(privateKey, provider);\n\nconst timestamp = Math.floor(Date.now() / 1000).toString();\nconst message = `${wallet.address}:${timestamp}`;\nconst { signature } = await wallet.sign({ message });\n\nconst payload = Buffer.from(message).toString('base64');\nconst sig = Buffer.from(signature, 'hex').toString('base64');\nconst token = `${payload}.${sig}`;\n\nconst response = await fetch(`${baseUrl}/orders`, {\n  headers: { 'Authorization': `Bearer ${token}` },\n});\n```\n\nReplace `baseUrl` with the server URL where you discovered this API.","parameters":[{"schema":{"type":"string","example":"20","description":"Max results per page (default 50, max 200)"},"required":false,"description":"Max results per page (default 50, max 200)","name":"limit","in":"query"},{"schema":{"type":"string","example":"0","description":"Number of results to skip"},"required":false,"description":"Number of results to skip","name":"offset","in":"query"},{"schema":{"type":"string","example":"Bearer ZmFzdDFhYmMuLi46MTcxMjM0NTY3OA==.c2lnbmF0dXJl","description":"Bearer token: base64(address:timestamp).base64(signature)"},"required":false,"description":"Bearer token: base64(address:timestamp).base64(signature)","name":"authorization","in":"header"}],"responses":{"200":{"description":"Order list","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrderListResponse"}}}},"401":{"description":"Missing or invalid wallet signature","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/orders/{id}":{"get":{"tags":["Orders"],"summary":"Get order status","description":"Returns the current status of an order, including tracking numbers and refund info. If an order is already placed but tracking has not been stored yet, the server refreshes it from the fulfillment provider on demand. Only the wallet that placed the order can view it.\n\nRequires wallet signature authentication via the Authorization header.\n\n**Format:** `Authorization: Bearer <base64(address:timestamp)>.<base64(signature)>`\n\n**Example using @fastxyz/sdk:**\n\n```ts\nconst timestamp = Math.floor(Date.now() / 1000).toString();\nconst message = `${wallet.address}:${timestamp}`;\nconst { signature } = await wallet.sign({ message });\n\nconst payload = Buffer.from(message).toString('base64');\nconst sig = Buffer.from(signature, 'hex').toString('base64');\nconst token = `${payload}.${sig}`;\n\nconst response = await fetch(`${baseUrl}/orders/${orderId}`, {\n  headers: { 'Authorization': `Bearer ${token}` },\n});\n```\n\nReplace `baseUrl` with the server URL where you discovered this API.","parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"id","in":"path"},{"schema":{"type":"string","example":"Bearer ZmFzdDFhYmMuLi46MTcxMjM0NTY3OA==.c2lnbmF0dXJl","description":"Bearer token: base64(address:timestamp).base64(signature)"},"required":false,"description":"Bearer token: base64(address:timestamp).base64(signature)","name":"authorization","in":"header"}],"responses":{"200":{"description":"Order details","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrderDetail"}}}},"401":{"description":"Missing or invalid wallet signature","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Order not found or not owned by authenticated wallet","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/orders/{id}/view":{"get":{"tags":["Orders"],"summary":"View shareable order details page","description":"Returns a read-only HTML page for this order that can be opened in a browser or shared as a link. It shows products, shipping address, order status, tracking links, actual price breakdown, and refund information. Anyone with the link can view it, so treat the URL as a secret.","parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"Shareable order details page","content":{"text/html":{"schema":{"type":"string","example":"<html>...</html>"}}}},"404":{"description":"Order not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/orders/{id}/cancel":{"post":{"tags":["Orders"],"summary":"Cancel a pending order","description":"Cancel a pending order that has not yet been submitted to the retailer. Only works while the order is in pending status (still in the processing queue). Returns a full refund including the order fee. Only the wallet that placed the order can cancel it.","parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"id","in":"path"},{"schema":{"type":"string","description":"Bearer token: base64(address:timestamp).base64(signature)"},"required":true,"description":"Bearer token: base64(address:timestamp).base64(signature)","name":"authorization","in":"header"}],"responses":{"200":{"description":"Order cancelled and refund initiated","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CancelOrderResponse"}}}},"401":{"description":"Authentication failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Not authorized to cancel this order","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Order not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Order cannot be cancelled — already submitted or not pending","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/webhook/fulfillment":{"post":{"tags":["Internal"],"summary":"Order fulfillment webhook","description":"Receives order status events from the fulfillment provider. Not intended for direct API consumers.","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookEvent"}}}},"responses":{"200":{"description":"Acknowledged"}}}},"/health":{"get":{"tags":["System"],"summary":"Health check","responses":{"200":{"description":"Healthy","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HealthResponse"}}}}}}}}}