{"openapi":"3.1.0","info":{"title":"Sayer & Stone","version":"1.0.0","description":"Agent-commerce API for Sayer & Stone — lab-grown diamond fine jewelry, made to order.","x-guidance":"Browse the catalog via GET /catalog (free, no auth). Products carry one or more variant axes drawn from `length`, `metal`, and `total_weight` (canonical values like \"7 inches\", \"14K rose gold\", \"5 carats\") plus an `images[]` gallery. When a product has images, ask the buyer once before rendering them whether they want to see photos while browsing, and remember the answer for the session. To purchase, POST /purchase with either `sku` or `product_slug` + `options`, plus quantity, email, and shipping. The first call returns 402 with the payment challenge — pay via Tempo USDC, x402 USDC on Base, Solana MPP, or Stripe SPT. Flat-rate $45 shipping per order. Each piece is made to order; we email your delivery estimate after the order is placed. See /llms.txt for the full flow."},"servers":[{"url":"https://agents.sayerandstone.com"}],"x-service-info":{"categories":["commerce","jewelry","fine-jewelry","lab-grown"],"docs":{"homepage":"https://www.sayerandstone.com","apiReference":"https://agents.sayerandstone.com/.well-known/mpp.json","llms":"https://agents.sayerandstone.com/llms.txt"}},"paths":{"/catalog":{"get":{"summary":"List products with embedded variants","description":"Returns `{ products: [...], agent_instructions: { image_display } }`. The `agent_instructions.image_display` field instructs agents to ask the buyer once per session before rendering any product photo from `images[]`, and to skip the prompt on subsequent products.","responses":{"200":{"description":"Catalog listing (includes agent_instructions.image_display)"}}}},"/catalog/{slug}":{"get":{"summary":"Get a product (with variants) by slug","description":"Returns `{ product: {...}, agent_instructions: { image_display } }`. Same image-display guidance as GET /catalog.","parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Product detail with variants (includes agent_instructions.image_display)"},"404":{"description":"Not found"}}}},"/purchase":{"post":{"summary":"Purchase a jewelry piece via multi-rail payment.","description":"No identity headers required. Each payment rail (Tempo MPP, x402 Base, Solana MPP, Stripe SPT) authenticates via its own native credential. See /llms.txt for the full flow.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","description":"Variant selection: provide `sku` directly OR `product_slug` plus `options`.","required":["quantity","email","shipping"],"properties":{"sku":{"type":"string","description":"Variant SKU from GET /catalog. Exclusive with product_slug+options."},"product_slug":{"type":"string","description":"Parent product slug. Pair with `options`."},"options":{"type":"object","description":"Map of option name to canonical value (e.g. {\"length\":\"7 inches\",\"metal\":\"14K rose gold\"}).","additionalProperties":{"type":"string"}},"quantity":{"type":"integer","minimum":1,"maximum":12},"email":{"type":"string","format":"email"},"order_id":{"type":"string","format":"uuid","description":"Resume a pending order after identity verification"},"gift_note":{"type":"string","maxLength":300,"description":"Optional personal note to print on a card. Plain text only (no HTML/markdown). Newlines (\\n) are preserved. If the buyer is sending as a gift, ASK them first and include an opening + signature in the note text. Omit for non-gift orders.","example":"Happy birthday, Alex!\n\nCheers to many more.\n\n— Jane"},"shipping":{"type":"object","required":["name","address_1","city","state","zip"],"properties":{"name":{"type":"string"},"address_1":{"type":"string"},"address_2":{"type":"string"},"city":{"type":"string"},"state":{"type":"string","minLength":2,"maxLength":2},"zip":{"type":"string"},"country":{"type":"string","default":"US"}}}}}}}},"x-payment-info":{"authMode":"payment","price":{"mode":"dynamic","currency":"USD","min":"50.00","max":"5000.00"},"protocols":[{"mpp":{"method":"tempo","intent":"charge","currency":"0x20c000000000000000000000b9537d11c60e8b50"}},{"x402":{"scheme":"exact","network":"base","asset":"USDC","client":"agentscore-pay pay POST <url> --chain base"}},{"mpp":{"method":"solana","intent":"charge","currency":"EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v","client":"agentscore-pay pay POST <url> --chain solana"}},{"mpp":{"method":"stripe","intent":"charge","currency":"usd"}}],"description":"Variable depending on variant and quantity. The runtime 402 challenge is authoritative for the exact amount."},"responses":{"200":{"description":"Order completed"},"402":{"description":"Payment Required — MPP payment challenge issued. Body includes pricing, accepted methods, concrete rail commands, and critical warnings.","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/AgentScorePaymentRequired"},{"type":"object","description":"Sayer & Stone–specific extensions on top of the standard AgentScore 402 body.","properties":{"how_to_pay":{"type":"object","description":"Rail-specific concrete commands the agent can execute directly.","properties":{"tempo":{"type":"object","properties":{"command":{"type":"string"}}},"x402_base":{"type":"object","properties":{"command":{"type":"string"}}},"solana_mpp":{"type":"object","properties":{"command":{"type":"string"}}}}},"warnings":{"type":"array","items":{"type":"string"},"description":"Critical agent-facing warnings — e.g. do NOT use `tempo wallet transfer` or send USDC manually to the x402 deposit addresses (both bypass the payment handshake)."}}}]}}}}}}},"/orders/{id}":{"get":{"summary":"Retrieve a specific order","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Order detail"},"404":{"description":"Not found"}}}},"/orders/{id}/status":{"get":{"summary":"Lightweight payment status check","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Payment status"}}}}},"components":{"securitySchemes":{"OperatorToken":{"type":"apiKey","in":"header","name":"X-Operator-Token","description":"Operator-token-path identity (opc_...). Works on every payment rail; reusable across AgentScore merchants. If both X-Operator-Token and X-Wallet-Address are sent, this one wins."},"WalletAddress":{"type":"apiKey","in":"header","name":"X-Wallet-Address","description":"Wallet-path identity (0x... or base58). Only works on rails that carry a wallet signature (Tempo MPP, x402 EIP-3009, x402 SPL Token). The wallet you claim MUST sign the payment."},"siwx":{"type":"http","scheme":"bearer","bearerFormat":"SIWX","description":"Sign-In With X wallet authentication. Agent signs a challenge with their wallet (any supported chain) and presents the proof in the Authorization header. Used for identity-gated free endpoints; payment-required endpoints declare x-payment-info instead."}},"schemas":{"AgentScoreDenialReason":{"type":"string","enum":["missing_identity","identity_verification_required","token_expired","invalid_credential","wallet_signer_mismatch","wallet_auth_requires_wallet_signing","wallet_not_trusted","api_error","payment_required"],"description":"Denial code emitted by AgentScore's gate middleware in 403 responses. Every code carries a structured agent_instructions block describing recovery actions (per-code action: missing_identity → probe_identity_then_session, identity_verification_required / token_expired → deliver_verify_url_and_poll, invalid_credential → switch_token_or_restart_session, wallet_signer_mismatch → resign_or_switch_to_operator_token, wallet_auth_requires_wallet_signing → switch_to_operator_token, wallet_not_trusted → contact_support — UNFIXABLE compliance only (sanctions/age/jurisdiction_restricted); fixable reasons re-route to identity_verification_required, payment_required → contact_merchant)."},"AgentScoreDenialBody":{"type":"object","properties":{"error":{"$ref":"#/components/schemas/AgentScoreDenialReason"},"agent_instructions":{"type":"string","description":"JSON-encoded { action, steps, user_message } block. Always present on every denial; agents parse this to learn how to recover (e.g., poll verify_url, switch headers, re-sign)."},"verify_url":{"type":"string","format":"uri","description":"Present for missing_identity / identity_verification_required / token_expired denials. Agent shares this with the user to complete KYC or claim a wallet. Not present on wallet_not_trusted (UNFIXABLE compliance — re-verification won't change the outcome)."},"session_id":{"type":"string"},"poll_url":{"type":"string","format":"uri"},"poll_secret":{"type":"string"},"agent_memory":{"type":"object","description":"Cross-merchant pattern hint emitted on first-encounter denials."}},"required":["error","agent_instructions"]},"AgentScorePaymentRequired":{"type":"object","properties":{"payment_required":{"type":"boolean","enum":[true]},"x402Version":{"type":"integer","enum":[1,2]},"accepts":{"type":"array","items":{"type":"object"},"description":"x402 PaymentRequired.accepts entries."},"accepted_methods":{"type":"array","items":{"type":"object"},"description":"MPP method entries (tempo/charge, x402/exact, stripe/charge, ...)."},"amount_usd":{"type":"string"},"currency":{"type":"string"},"pricing":{"type":"object","properties":{"subtotal":{"type":"string"},"tax":{"type":"string"},"tax_rate":{"type":"number"},"tax_state":{"type":"string"},"total":{"type":"string"}}},"identity_mode":{"type":"string","enum":["wallet","operator_token"]},"required_signer":{"type":"string"},"linked_wallets":{"type":"array","items":{"type":"string"}},"signer_constraint":{"type":"string"},"agent_instructions":{"type":"object"},"agent_memory":{"type":"object"}}}}}}