{
  "openapi": "3.1.0",
  "info": {
    "title": "Blueprint Storefront \u2014 Agent & Developer API",
    "version": "2026-08-27",
    "summary": "Read-only catalog access and UCP/MCP agent commerce for blueprint.bryanjohnson.com.",
    "description": "This storefront runs on Shopify. The endpoints below are Shopify platform endpoints served on the Blueprint domain \u2014 not a first-party Blueprint API, and not independently versioned by Blueprint.\n\nCatalog reads require no authentication. Transactional operations go through the UCP MCP endpoint, which is JSON-RPC and is described formally by the OpenRPC schema linked under `externalDocs`.\n\nCheckout requires explicit, contemporaneous buyer approval.",
    "contact": {
      "name": "Blueprint Support",
      "email": "support@bryanjohnson.com"
    }
  },
  "externalDocs": {
    "description": "UCP shopping service \u2014 OpenRPC schema for the MCP endpoint",
    "url": "https://ucp.dev/2026-04-08/services/shopping/mcp.openrpc.json"
  },
  "servers": [
    {
      "url": "https://blueprint.bryanjohnson.com",
      "description": "Primary storefront"
    },
    {
      "url": "https://blueprint-bryanjohnson.myshopify.com",
      "description": "Canonical Shopify host advertised by /.well-known/ucp"
    }
  ],
  "tags": [
    {
      "name": "discovery",
      "description": "Machine-readable service description"
    },
    {
      "name": "catalog",
      "description": "Unauthenticated read-only product data"
    },
    {
      "name": "agent-commerce",
      "description": "UCP transactional surface over MCP"
    }
  ],
  "paths": {
    "/.well-known/ucp": {
      "get": {
        "tags": [
          "discovery"
        ],
        "summary": "UCP merchant profile",
        "description": "Supported protocol versions, service endpoints, capabilities, and payment handlers. Start here \u2014 prefer the endpoint host this returns over the one hardcoded in documentation.",
        "operationId": "getUcpProfile",
        "responses": {
          "200": {
            "description": "UCP profile",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/UcpProfile"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/.well-known/oauth-authorization-server": {
      "get": {
        "tags": [
          "discovery"
        ],
        "summary": "OAuth 2.0 authorization server metadata",
        "description": "RFC 8414 metadata for Shopify customer accounts. Only needed for customer-scoped access; catalog reads need no credentials. Note that the data-granting scopes are full-access only \u2014 Shopify offers no read-only variants.",
        "operationId": "getOauthMetadata",
        "responses": {
          "200": {
            "description": "Authorization server metadata",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OauthAuthorizationServerMetadata"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/products.json": {
      "get": {
        "tags": [
          "catalog"
        ],
        "summary": "List all published products",
        "description": "Returns the full published catalog. The catalog currently fits in a single response at `limit=250`.\n\nThe `page` parameter is accepted but returns inconsistent results on this storefront; prefer a single `limit=250` request over paging.",
        "operationId": "listProducts",
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "description": "Products per response. Defaults to 24.",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 250,
              "default": 24
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Product list",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "products"
                  ],
                  "properties": {
                    "products": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Product"
                      }
                    }
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/products/{handle}.json": {
      "get": {
        "tags": [
          "catalog"
        ],
        "summary": "Get one product by handle",
        "operationId": "getProduct",
        "parameters": [
          {
            "$ref": "#/components/parameters/Handle"
          }
        ],
        "responses": {
          "200": {
            "description": "Product detail",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "product"
                  ],
                  "properties": {
                    "product": {
                      "$ref": "#/components/schemas/Product"
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Product not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/collections/{handle}/products.json": {
      "get": {
        "tags": [
          "catalog"
        ],
        "summary": "List products in a collection",
        "description": "Use the handle `all` for the full catalog.\n\nAn unknown or misspelled handle returns 200 with an empty `products` array \u2014 it does not 404. Check `products.length`, not the status code.",
        "operationId": "listCollectionProducts",
        "parameters": [
          {
            "$ref": "#/components/parameters/Handle"
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 250,
              "default": 24
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Product list",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "products"
                  ],
                  "properties": {
                    "products": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Product"
                      }
                    }
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/sitemap.xml": {
      "get": {
        "tags": [
          "catalog"
        ],
        "summary": "Sitemap index",
        "description": "XML, not JSON. Links to per-type sitemaps for products, collections, pages, and blogs.",
        "operationId": "getSitemap",
        "responses": {
          "200": {
            "description": "Sitemap index",
            "content": {
              "application/xml": {
                "schema": {
                  "$ref": "#/components/schemas/Sitemap"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/ucp/mcp": {
      "post": {
        "tags": [
          "agent-commerce"
        ],
        "summary": "UCP Model Context Protocol endpoint (JSON-RPC 2.0)",
        "description": "Transactional agent commerce. Call `tools/list` to discover tools and their input schemas \u2014 that response is authoritative, this document is not.\n\nAvailable tools: `search_catalog`, `lookup_catalog`, `get_product`, `create_cart`, `get_cart`, `update_cart`, `cancel_cart`, `create_checkout`, `get_checkout`, `update_checkout`, `complete_checkout`, `cancel_checkout`, `get_order`.\n\nTypical flow: `search_catalog` \u2192 `create_cart` \u2192 `create_checkout` \u2192 `update_checkout` (shipping address and method) \u2192 `complete_checkout`.\n\nMonetary values are integers in ISO 4217 minor units paired with a currency code: `{\"amount\": 2500, \"currency\": \"USD\"}` is $25.00. Convert to major units before quoting a price to a buyer.\n\n`complete_checkout` requires explicit, contemporaneous buyer approval. If you cannot obtain it at the moment of payment, route through the Shop skill (https://shop.app/SKILL.md) and Shop Pay instead.\n\nPass `context.address_country` and `context.currency` for accurate pricing and availability. The endpoint is rate-limited per IP; back off on 429.",
        "operationId": "ucpMcp",
        "externalDocs": {
          "description": "OpenRPC schema \u2014 authoritative method and parameter definitions",
          "url": "https://ucp.dev/2026-04-08/services/shopping/mcp.openrpc.json"
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/JsonRpcRequest"
              },
              "examples": {
                "toolsList": {
                  "summary": "Discover available tools",
                  "value": {
                    "jsonrpc": "2.0",
                    "id": 1,
                    "method": "tools/list"
                  }
                },
                "searchCatalog": {
                  "summary": "Search the catalog",
                  "value": {
                    "jsonrpc": "2.0",
                    "id": 2,
                    "method": "tools/call",
                    "params": {
                      "name": "search_catalog",
                      "arguments": {
                        "query": "olive oil",
                        "context": {
                          "address_country": "US",
                          "currency": "USD"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "JSON-RPC response. Protocol-level success; check the `error` member for method-level failure.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonRpcResponse"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited. Retry after backoff.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/.well-known/ucp/{version}": {
      "get": {
        "operationId": "getUcpProfileVersioned",
        "summary": "Version-pinned UCP merchant profile",
        "description": "Retrieve the UCP profile for a specific protocol version. Supported versions are listed in supported_versions on /.well-known/ucp.",
        "parameters": [
          {
            "name": "version",
            "in": "path",
            "required": true,
            "description": "UCP protocol version to pin.",
            "schema": {
              "type": "string",
              "enum": [
                "2026-04-08",
                "2026-01-23"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Version-pinned UCP profile",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/UcpProfile"
                }
              }
            }
          },
          "404": {
            "description": "Unsupported or unknown protocol version",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "parameters": {
      "Handle": {
        "name": "handle",
        "in": "path",
        "required": true,
        "description": "URL-safe identifier, e.g. `extra-virgin-olive-oil`.",
        "schema": {
          "type": "string"
        },
        "examples": {
          "product": {
            "value": "extra-virgin-olive-oil"
          }
        }
      }
    },
    "schemas": {
      "Product": {
        "type": "object",
        "description": "Shopify storefront product. Prices are decimal strings in the shop's currency \u2014 unlike the MCP endpoint, which uses integer minor units.",
        "properties": {
          "id": {
            "type": "integer"
          },
          "title": {
            "type": "string"
          },
          "handle": {
            "type": "string"
          },
          "body_html": {
            "type": "string",
            "description": "Description as HTML."
          },
          "published_at": {
            "type": "string",
            "format": "date-time"
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "updated_at": {
            "type": "string",
            "format": "date-time"
          },
          "vendor": {
            "type": "string"
          },
          "product_type": {
            "type": "string"
          },
          "tags": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "variants": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Variant"
            }
          },
          "images": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Image"
            }
          },
          "options": {
            "type": "array",
            "items": {
              "type": "object"
            }
          }
        }
      },
      "Variant": {
        "type": "object",
        "properties": {
          "id": {
            "type": "integer"
          },
          "title": {
            "type": "string",
            "examples": [
              "1-Pack"
            ]
          },
          "sku": {
            "type": [
              "string",
              "null"
            ],
            "examples": [
              "BP-EVOO-KIT1"
            ]
          },
          "price": {
            "type": "string",
            "description": "Decimal string in shop currency.",
            "examples": [
              "39.00"
            ]
          },
          "compare_at_price": {
            "type": [
              "string",
              "null"
            ]
          },
          "available": {
            "type": "boolean"
          },
          "requires_shipping": {
            "type": "boolean"
          },
          "taxable": {
            "type": "boolean"
          },
          "grams": {
            "type": "integer"
          },
          "position": {
            "type": "integer"
          },
          "product_id": {
            "type": "integer"
          },
          "option1": {
            "type": [
              "string",
              "null"
            ]
          },
          "option2": {
            "type": [
              "string",
              "null"
            ]
          },
          "option3": {
            "type": [
              "string",
              "null"
            ]
          }
        }
      },
      "Image": {
        "type": "object",
        "properties": {
          "id": {
            "type": "integer"
          },
          "src": {
            "type": "string",
            "format": "uri"
          },
          "width": {
            "type": "integer"
          },
          "height": {
            "type": "integer"
          },
          "position": {
            "type": "integer"
          }
        }
      },
      "JsonRpcRequest": {
        "type": "object",
        "required": [
          "jsonrpc",
          "method"
        ],
        "properties": {
          "jsonrpc": {
            "type": "string",
            "const": "2.0"
          },
          "id": {
            "type": [
              "string",
              "integer"
            ]
          },
          "method": {
            "type": "string",
            "examples": [
              "tools/list",
              "tools/call"
            ]
          },
          "params": {
            "type": "object"
          }
        }
      },
      "JsonRpcResponse": {
        "type": "object",
        "required": [
          "jsonrpc"
        ],
        "properties": {
          "jsonrpc": {
            "type": "string",
            "const": "2.0"
          },
          "id": {
            "type": [
              "string",
              "integer",
              "null"
            ]
          },
          "result": {
            "type": "object"
          },
          "error": {
            "type": "object",
            "properties": {
              "code": {
                "type": "integer"
              },
              "message": {
                "type": "string"
              },
              "data": {}
            }
          }
        }
      },
      "Error": {
        "type": "object",
        "required": [
          "code",
          "message"
        ],
        "properties": {
          "code": {
            "type": "string",
            "description": "Machine-readable error code",
            "examples": [
              "invalid_profile_url"
            ]
          },
          "message": {
            "type": "string",
            "description": "Human-readable description of the failure"
          },
          "continue_url": {
            "type": "string",
            "format": "uri",
            "description": "Resolution hint: where an agent or buyer should go to recover"
          }
        }
      },
      "UcpProfile": {
        "type": "object",
        "properties": {
          "ucp": {
            "type": "object",
            "properties": {
              "version": {
                "type": "string",
                "examples": [
                  "2026-04-08"
                ]
              },
              "supported_versions": {
                "type": "object",
                "additionalProperties": {
                  "type": "string",
                  "format": "uri"
                }
              },
              "services": {
                "type": "object"
              },
              "capabilities": {
                "type": "object"
              }
            }
          }
        }
      },
      "OauthAuthorizationServerMetadata": {
        "type": "object",
        "properties": {
          "issuer": {
            "type": "string",
            "format": "uri"
          },
          "authorization_endpoint": {
            "type": "string",
            "format": "uri"
          },
          "token_endpoint": {
            "type": "string",
            "format": "uri"
          },
          "scopes_supported": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "examples": [
              [
                "openid",
                "email",
                "customer-account-api:full",
                "customer-account-mcp-api:full"
              ]
            ]
          }
        }
      },
      "Sitemap": {
        "type": "string",
        "description": "XML sitemap document listing public store URLs"
      }
    },
    "securitySchemes": {
      "customerAccountOAuth": {
        "type": "oauth2",
        "description": "Shopify customer-account OAuth. Not required for any catalog endpoint; all read endpoints below are public.",
        "flows": {
          "authorizationCode": {
            "authorizationUrl": "https://shopify.com/authentication/77231292701/oauth/authorize",
            "tokenUrl": "https://shopify.com/authentication/77231292701/oauth/token",
            "scopes": {
              "openid": "Identity only",
              "email": "Buyer email address",
              "customer-account-api:full": "Full customer-account data access",
              "customer-account-mcp-api:full": "Full customer-account MCP access"
            }
          }
        }
      }
    }
  },
  "security": []
}