{ "openapi": "3.1.0", "info": { "title": "Faïença Broderie public catalog API", "summary": "Zero-auth catalog JSON plus Shopify UCP/MCP for shopping agents.", "description": "Read products without an API key. Cart and checkout go through UCP MCP and still require buyer approval for payment. Canonical agent docs: /agents.md", "version": "1.0.0", "contact": { "name": "Faïença Broderie", "url": "https:\/\/faienca.fr", "email": "contact@faienca.fr" } }, "servers": [ { "url": "https:\/\/faienca.fr", "description": "Live store" } ], "tags": [ { "name": "Catalog", "description": "Public JSON, no authentication" }, { "name": "UCP", "description": "Universal Commerce Protocol discovery and MCP tools" }, { "name": "Docs", "description": "Agent and developer documents" } ], "paths": { "/products.json": { "get": { "operationId": "listProductsJson", "tags": ["Catalog"], "summary": "List products as JSON", "description": "Zero-auth product list. Prices are live. Paginate with limit and page.", "parameters": [ { "name": "limit", "in": "query", "schema": { "type": "integer", "minimum": 1, "maximum": 250 }, "description": "Page size" }, { "name": "page", "in": "query", "schema": { "type": "integer", "minimum": 1 }, "description": "Page number" } ], "responses": { "200": { "description": "Product list", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ProductList" } } } }, "default": { "$ref": "#/components/responses/JsonError" } } } }, "/products/{handle}.json": { "get": { "operationId": "getProductByHandleJson", "tags": ["Catalog"], "summary": "Retrieve one product as JSON", "description": "Zero-auth product detail by handle. Missing handles return JSON, not the HTML app shell.", "parameters": [ { "name": "handle", "in": "path", "required": true, "schema": { "type": "string" }, "description": "Product handle" } ], "responses": { "200": { "description": "Product", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ProductEnvelope" } } } }, "404": { "$ref": "#/components/responses/JsonError" } } } }, "/collections/{handle}/products.json": { "get": { "operationId": "listCollectionProductsJson", "tags": ["Catalog"], "summary": "List products in a collection", "description": "Zero-auth collection products. Example handles: kits-de-broderie, provence, saint-eloi.", "parameters": [ { "name": "handle", "in": "path", "required": true, "schema": { "type": "string" }, "description": "Collection handle such as kits-de-broderie or provence" } ], "responses": { "200": { "description": "Collection products", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ProductList" } } } }, "404": { "$ref": "#/components/responses/JsonError" } } } }, "/.well-known/ucp": { "get": { "operationId": "getUcpDiscovery", "tags": ["UCP"], "summary": "UCP discovery document", "description": "Machine-readable Universal Commerce Protocol discovery, including scoped permissions.", "responses": { "200": { "description": "UCP discovery", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/UcpDiscovery" } } } } } } }, "/pages/mcp": { "get": { "operationId": "getMcpManifest", "tags": ["UCP"], "summary": "MCP server manifest (Streamable HTTP)", "description": "Theme-hosted MCP discovery JSON. Prefer this over /.well-known/mcp.json, which Shopify may serve empty.", "responses": { "200": { "description": "MCP manifest", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/McpManifest" } } } } } } }, "/api/ucp/mcp": { "post": { "operationId": "callUcpMcp", "tags": ["UCP"], "summary": "UCP MCP Streamable HTTP", "description": "JSON-RPC MCP. Tools only: search_catalog, lookup_catalog, get_product, cart, and checkout. Do not read resources. Include meta.ucp-agent.profile. Request the minimum scope.", "security": [{ "UcpOAuth": ["ucp.catalog.read"] }], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/JsonRpcRequest" } } } }, "responses": { "200": { "description": "JSON-RPC result or error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/JsonRpcResponse" } } } }, "default": { "$ref": "#/components/responses/JsonError" } } } }, "/agents.md": { "get": { "operationId": "getAgentsMarkdown", "tags": ["Docs"], "summary": "Canonical agent instructions including when to use this store", "description": "Markdown agent guide: catalog, UCP, scopes, and recovery links.", "responses": { "200": { "description": "Markdown", "content": { "text/markdown": { "schema": { "$ref": "#/components/schemas/MarkdownDocument" } } } } } } }, "/llms.txt": { "get": { "operationId": "getLlmsTxt", "tags": ["Docs"], "summary": "Short agent index with when-to-use guidance", "description": "Compact markdown index pointing at agents.md, OpenAPI, and MCP.", "responses": { "200": { "description": "Plain text / markdown", "content": { "text/plain": { "schema": { "$ref": "#/components/schemas/MarkdownDocument" } } } } } } }, "/pages/developers": { "get": { "operationId": "getDeveloperPortal", "tags": ["Docs"], "summary": "Developer portal: scopes, OpenAPI, MCP, sandbox", "description": "Human-readable developer portal for Faïença Broderie APIs.", "responses": { "200": { "description": "HTML developer portal", "content": { "text/html": { "schema": { "$ref": "#/components/schemas/HtmlDocument" } } } } } } }, "/pages/pricing": { "get": { "operationId": "getPricingPage", "tags": ["Docs"], "summary": "Public kit, PDF and custom pricing", "description": "Public prices for kits, PDF motifs, and made-to-order hoops.", "responses": { "200": { "description": "HTML pricing page", "content": { "text/html": { "schema": { "$ref": "#/components/schemas/HtmlDocument" } } } } } } } }, "components": { "securitySchemes": { "UcpOAuth": { "type": "oauth2", "description": "Scoped UCP permissions. Catalog JSON needs no token. MCP checkout requires buyer consent.", "flows": { "clientCredentials": { "tokenUrl": "https:\/\/faienca.fr\/api\/ucp\/mcp", "scopes": { "ucp.catalog.read": "Search and read products, prices, and availability", "ucp.cart.write": "Create and update shopping carts", "ucp.checkout.write": "Create checkout sessions; payment still needs human approval", "ucp.orders.read": "Read order status for the authenticated buyer" } } } } }, "schemas": { "ProductList": { "type": "object", "properties": { "products": { "type": "array", "items": { "$ref": "#/components/schemas/Product" } } } }, "ProductEnvelope": { "type": "object", "properties": { "product": { "$ref": "#/components/schemas/Product" } } }, "Product": { "type": "object", "properties": { "id": { "type": "integer" }, "title": { "type": "string" }, "handle": { "type": "string" }, "body_html": { "type": "string" }, "variants": { "type": "array", "items": { "type": "object", "properties": { "id": { "type": "integer" }, "price": { "type": "string" }, "available": { "type": "boolean" } } } } } }, "JsonRpcRequest": { "type": "object", "required": ["jsonrpc", "method"], "properties": { "jsonrpc": { "type": "string", "enum": ["2.0"] }, "id": { "type": ["integer", "string"] }, "method": { "type": "string" }, "params": { "type": "object", "additionalProperties": true } } }, "UcpDiscovery": { "type": "object", "required": ["ucp"], "properties": { "ucp": { "type": "object", "properties": { "version": { "type": "string" }, "services": { "type": "object", "additionalProperties": true } } } } }, "McpManifest": { "type": "object", "required": ["name", "url", "transport"], "properties": { "name": { "type": "string" }, "title": { "type": "string" }, "description": { "type": "string" }, "version": { "type": "string" }, "url": { "type": "string", "format": "uri" }, "transport": { "type": "string", "enum": ["streamable-http"] }, "mcp_version": { "type": "string" }, "protocolVersion": { "type": "string" }, "capabilities": { "type": "object", "properties": { "tools": { "type": "object" } } }, "endpoints": { "type": "array", "items": { "type": "object", "properties": { "url": { "type": "string", "format": "uri" }, "transport": { "type": "string" }, "capabilities": { "type": "array", "items": { "type": "string" } } } } } } }, "MarkdownDocument": { "type": "string", "description": "Markdown or plain-text agent documentation" }, "HtmlDocument": { "type": "string", "description": "HTML page" }, "JsonRpcResponse": { "type": "object", "properties": { "jsonrpc": { "type": "string" }, "id": { "type": ["integer", "string", "null"] }, "result": { "type": "object", "additionalProperties": true }, "error": { "$ref": "#/components/schemas/ErrorObject" } } }, "ErrorObject": { "type": "object", "required": ["code", "message"], "properties": { "code": { "type": ["string", "integer"] }, "message": { "type": "string" }, "hint": { "type": "string" } } } }, "responses": { "JsonError": { "description": "Structured JSON error", "content": { "application/json": { "schema": { "type": "object", "properties": { "error": { "$ref": "#/components/schemas/ErrorObject" } } } } } } } } }