{
  "openapi": "3.1.0",
  "info": {
    "title": "PawFectHeaven Storefront API",
    "version": "2026-10-16",
    "summary": "Public, read-and-cart endpoints of the PawFectHeaven Shopify store (pawfectheaven.com).",
    "description": "PawFectHeaven sells one product: PawFectHeaven Liquid Taurine, a 60 mL liquid taurine supplement for cats that is added to wet food with a marked dropper. This document describes the public HTTP endpoints that the store's Shopify platform already serves, so an AI agent can look up the product, price and availability, build a cart and hand the shopper to checkout.\n\n## When to use this API\n- A shopper asks an agent about liquid taurine for cats, PawFectHeaven, or the product's price and availability.\n- An agent needs a cart or checkout link for PawFectHeaven Liquid Taurine.\n\n## Access\nFree to use. No account, sign-up or API key is needed for any endpoint below. Payment is always completed by the shopper on Shopify's checkout page (or through the UCP checkout tools with the buyer's approval).\n\n## Identify your agent\nShopify asks automated clients to identify themselves with Web Bot Auth (https://shopify.dev/docs/api/storefront#identifying-bots-with-web-bot-auth). Back off on HTTP 429 and respect Retry-After.\n\n## Which interface to pick\n1. **UCP / MCP** (`POST /api/ucp/mcp`) — Shopify's Universal Commerce Protocol server with catalog, cart and checkout tools. Best for agents.\n2. **Storefront GraphQL API** (`POST /api/2026-10/graphql.json`) — Shopify's typed GraphQL API, tokenless access for products, collections and carts.\n3. **AJAX API** (`/products/{handle}.js`, `/cart/*.js`) — simple JSON endpoints. Carts are tied to the `cart` cookie, so keep cookies between calls.\n\n## Errors\nAJAX endpoints return JSON errors shaped `{status, message, description}` (HTTP 400/404/422). GraphQL returns `{errors:[{message, extensions.code}]}`. The MCP endpoint returns JSON-RPC 2.0 errors `{error:{code, message, data}}`.\n\n## Versioning\nThe Storefront GraphQL API is versioned by date in the path (`/api/2026-10/`); Shopify releases a version every quarter and supports each for at least 12 months. The AJAX endpoints are unversioned and maintained by Shopify. This document's `info.version` is the date it was last checked against the live store.\n\n## Sandbox\nThere is no separate PawFectHeaven sandbox. To test Storefront GraphQL calls without touching a real store, Shopify runs a free mock store at https://mock.shop. Read-only and cart calls on this store are safe: a cart is never charged unless a shopper completes checkout.\n\nMore: https://www.pawfectheaven.com/pages/developers · https://www.pawfectheaven.com/agents.md · https://www.pawfectheaven.com/llms.txt",
    "contact": {
      "name": "PawFectHeaven support",
      "email": "Support@pawfectheaven.com",
      "url": "https://www.pawfectheaven.com/pages/contact-us"
    },
    "termsOfService": "https://www.pawfectheaven.com/policies/terms-of-service",
    "license": {
      "name": "Proprietary — free to call, see terms of service",
      "url": "https://www.pawfectheaven.com/policies/terms-of-service"
    }
  },
  "externalDocs": {
    "description": "Developer and agent guide",
    "url": "https://www.pawfectheaven.com/pages/developers"
  },
  "servers": [
    {
      "url": "https://www.pawfectheaven.com",
      "description": "Live store (prices shown in the shopper's local currency)"
    }
  ],
  "security": [
    {}
  ],
  "tags": [
    {
      "name": "Catalog",
      "description": "Read the product catalog."
    },
    {
      "name": "Cart",
      "description": "Build a cart (cookie-based session)."
    },
    {
      "name": "Agent protocols",
      "description": "Shopify's UCP/MCP and Storefront GraphQL endpoints for this store."
    },
    {
      "name": "Discovery",
      "description": "Machine-readable discovery documents."
    }
  ],
  "paths": {
    "/products/{handle}.js": {
      "get": {
        "operationId": "getProduct",
        "tags": [
          "Catalog"
        ],
        "summary": "Get one product with variants, price and availability",
        "description": "Returns the product, its variants (use `variants[].id` for /cart/add.js), prices in minor units of the shopper's currency, and subscription options. Unknown handles return HTTP 404 with an empty body.",
        "parameters": [
          {
            "$ref": "#/components/parameters/handle"
          }
        ],
        "responses": {
          "200": {
            "description": "Product found.",
            "content": {
              "text/javascript": {
                "schema": {
                  "$ref": "#/components/schemas/Product"
                }
              }
            }
          },
          "404": {
            "description": "No product with that handle (empty body)."
          },
          "429": {
            "description": "Too many requests. Shopify rate-limits unidentified or heavy traffic: back off and respect Retry-After (see /agents.md)."
          }
        }
      }
    },
    "/products.json": {
      "get": {
        "operationId": "listProducts",
        "tags": [
          "Catalog"
        ],
        "summary": "List all published products (paginated)",
        "description": "Returns published products with variants. Prices are decimal strings. Page with `limit` and `page`.",
        "parameters": [
          {
            "$ref": "#/components/parameters/limit"
          },
          {
            "$ref": "#/components/parameters/page"
          }
        ],
        "responses": {
          "200": {
            "description": "A page of products.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProductList"
                }
              }
            }
          },
          "429": {
            "description": "Too many requests. Shopify rate-limits unidentified or heavy traffic: back off and respect Retry-After (see /agents.md)."
          }
        }
      }
    },
    "/collections/{collection}/products.json": {
      "get": {
        "operationId": "listCollectionProducts",
        "tags": [
          "Catalog"
        ],
        "summary": "List the products in a collection (paginated)",
        "description": "Use `all` for every product. An unknown collection returns an empty `products` array.",
        "parameters": [
          {
            "name": "collection",
            "in": "path",
            "required": true,
            "description": "Collection handle, e.g. `all`.",
            "schema": {
              "type": "string"
            },
            "example": "all"
          },
          {
            "$ref": "#/components/parameters/limit"
          },
          {
            "$ref": "#/components/parameters/page"
          }
        ],
        "responses": {
          "200": {
            "description": "A page of products.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProductList"
                }
              }
            }
          },
          "429": {
            "description": "Too many requests. Shopify rate-limits unidentified or heavy traffic: back off and respect Retry-After (see /agents.md)."
          }
        }
      }
    },
    "/search/suggest.json": {
      "get": {
        "operationId": "searchProducts",
        "tags": [
          "Catalog"
        ],
        "summary": "Search products by keyword",
        "description": "Predictive search. Missing `q` returns HTTP 422 with a JSON error.",
        "parameters": [
          {
            "name": "q",
            "in": "query",
            "required": true,
            "description": "Search terms.",
            "schema": {
              "type": "string"
            },
            "example": "taurine"
          },
          {
            "name": "resources[type]",
            "in": "query",
            "required": false,
            "description": "Comma-separated resource types.",
            "schema": {
              "type": "string",
              "default": "product"
            },
            "example": "product"
          },
          {
            "name": "resources[limit]",
            "in": "query",
            "required": false,
            "description": "Max results per type (1-10).",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 10
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Search results.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SuggestResponse"
                }
              }
            }
          },
          "422": {
            "description": "Missing or empty `q`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AjaxError"
                }
              }
            }
          },
          "429": {
            "description": "Too many requests. Shopify rate-limits unidentified or heavy traffic: back off and respect Retry-After (see /agents.md)."
          }
        }
      }
    },
    "/cart.js": {
      "get": {
        "operationId": "getCart",
        "tags": [
          "Cart"
        ],
        "summary": "Get the current cart",
        "description": "Returns the cart for the `cart` cookie (a new empty cart if none). Send the cookie back on later calls.",
        "responses": {
          "200": {
            "description": "The cart.",
            "content": {
              "text/javascript": {
                "schema": {
                  "$ref": "#/components/schemas/Cart"
                }
              }
            }
          },
          "429": {
            "description": "Too many requests. Shopify rate-limits unidentified or heavy traffic: back off and respect Retry-After (see /agents.md)."
          }
        }
      }
    },
    "/cart/add.js": {
      "post": {
        "operationId": "addToCart",
        "tags": [
          "Cart"
        ],
        "summary": "Add one or more items to the cart",
        "description": "Adds variants to the cart in one request. Unknown variant IDs return HTTP 422; a missing `items` array returns HTTP 400. Then send the shopper to `/checkout` (or `/cart`) with the same cookie.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/AddItemsRequest"
              },
              "example": {
                "items": [
                  {
                    "id": 58584130126172,
                    "quantity": 1
                  }
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The added lines.",
            "content": {
              "text/javascript": {
                "schema": {
                  "$ref": "#/components/schemas/AddItemsResponse"
                }
              }
            }
          },
          "400": {
            "description": "Missing or invalid `items` (served as text/javascript).",
            "content": {
              "text/javascript": {
                "schema": {
                  "$ref": "#/components/schemas/AjaxError"
                }
              }
            }
          },
          "422": {
            "description": "Variant not found or not purchasable.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AjaxError"
                }
              }
            }
          },
          "429": {
            "description": "Too many requests. Shopify rate-limits unidentified or heavy traffic: back off and respect Retry-After (see /agents.md)."
          }
        }
      }
    },
    "/cart/change.js": {
      "post": {
        "operationId": "changeCartLine",
        "tags": [
          "Cart"
        ],
        "summary": "Change the quantity of one cart line",
        "description": "Identify the line by `id` (line key) or `line` (1-based index). Quantity 0 removes it. An unknown line key returns HTTP 422.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ChangeLineRequest"
              },
              "example": {
                "line": 1,
                "quantity": 2
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The updated cart.",
            "content": {
              "text/javascript": {
                "schema": {
                  "$ref": "#/components/schemas/Cart"
                }
              }
            }
          },
          "400": {
            "description": "Neither `line` nor `id` given (served as text/javascript).",
            "content": {
              "text/javascript": {
                "schema": {
                  "$ref": "#/components/schemas/AjaxError"
                }
              }
            }
          },
          "422": {
            "description": "Line or variant not found.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AjaxError"
                }
              }
            }
          },
          "429": {
            "description": "Too many requests. Shopify rate-limits unidentified or heavy traffic: back off and respect Retry-After (see /agents.md)."
          }
        }
      }
    },
    "/cart/update.js": {
      "post": {
        "operationId": "updateCart",
        "tags": [
          "Cart"
        ],
        "summary": "Set quantities for several lines, or the cart note and attributes",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UpdateCartRequest"
              },
              "example": {
                "updates": {
                  "58584130126172": 1
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The updated cart.",
            "content": {
              "text/javascript": {
                "schema": {
                  "$ref": "#/components/schemas/Cart"
                }
              }
            }
          },
          "422": {
            "description": "Variant not found.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AjaxError"
                }
              }
            }
          },
          "429": {
            "description": "Too many requests. Shopify rate-limits unidentified or heavy traffic: back off and respect Retry-After (see /agents.md)."
          }
        }
      }
    },
    "/cart/clear.js": {
      "post": {
        "operationId": "clearCart",
        "tags": [
          "Cart"
        ],
        "summary": "Remove every item from the cart",
        "responses": {
          "200": {
            "description": "The empty cart.",
            "content": {
              "text/javascript": {
                "schema": {
                  "$ref": "#/components/schemas/Cart"
                }
              }
            }
          },
          "429": {
            "description": "Too many requests. Shopify rate-limits unidentified or heavy traffic: back off and respect Retry-After (see /agents.md)."
          }
        }
      }
    },
    "/api/2026-10/graphql.json": {
      "post": {
        "operationId": "storefrontGraphql",
        "tags": [
          "Agent protocols"
        ],
        "summary": "Query Shopify's Storefront GraphQL API (tokenless)",
        "description": "Shopify's typed Storefront API for this store. Tokenless access covers products, collections, search and carts (`cartCreate` returns a `checkoutUrl`). Introspection is supported. Errors come back as `errors[]` with `extensions.code`. Schema reference: https://shopify.dev/docs/api/storefront/2026-10",
        "externalDocs": {
          "url": "https://shopify.dev/docs/api/storefront/2026-10"
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/GraphQLRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "GraphQL result (check `errors`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GraphQLResponse"
                }
              }
            }
          },
          "415": {
            "description": "Body is not valid JSON (`extensions.code` = UNSUPPORTED_MEDIA_TYPE).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GraphQLResponse"
                }
              }
            }
          },
          "429": {
            "description": "Too many requests. Shopify rate-limits unidentified or heavy traffic: back off and respect Retry-After (see /agents.md)."
          }
        }
      }
    },
    "/api/ucp/mcp": {
      "post": {
        "operationId": "ucpMcp",
        "tags": [
          "Agent protocols"
        ],
        "summary": "Shopify UCP shopping server (Model Context Protocol, Streamable HTTP)",
        "description": "JSON-RPC 2.0 MCP server run by Shopify for this store. 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. Call `tools/list` for schemas. Purchases need the buyer's approval. Spec: https://ucp.dev",
        "externalDocs": {
          "url": "https://shopify.dev/docs/agents"
        },
        "security": [
          {},
          {
            "shopifyCustomerAccount": [
              "dev.ucp.shopping.catalog.search:read",
              "dev.ucp.shopping.checkout:manage"
            ]
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/JsonRpcRequest"
              },
              "example": {
                "jsonrpc": "2.0",
                "id": 1,
                "method": "tools/list"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "JSON-RPC result or error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonRpcResponse"
                }
              }
            }
          },
          "400": {
            "description": "Invalid JSON-RPC request (JSON-RPC error body).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonRpcResponse"
                }
              }
            }
          },
          "429": {
            "description": "Too many requests. Shopify rate-limits unidentified or heavy traffic: back off and respect Retry-After (see /agents.md)."
          }
        }
      }
    },
    "/.well-known/ucp": {
      "get": {
        "operationId": "getUcpProfile",
        "tags": [
          "Discovery"
        ],
        "summary": "Get the store's UCP discovery profile",
        "description": "Lists UCP versions, the MCP service endpoint and supported capabilities (checkout, cart, fulfillment, discount).",
        "responses": {
          "200": {
            "description": "UCP profile.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/UcpProfile"
                }
              }
            }
          },
          "429": {
            "description": "Too many requests. Shopify rate-limits unidentified or heavy traffic: back off and respect Retry-After (see /agents.md)."
          }
        }
      }
    },
    "/agents.md": {
      "get": {
        "operationId": "getAgentGuide",
        "tags": [
          "Discovery"
        ],
        "summary": "Get the agent guide (Markdown)",
        "responses": {
          "200": {
            "description": "Agent guide.",
            "content": {
              "text/markdown": {
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "429": {
            "description": "Too many requests. Shopify rate-limits unidentified or heavy traffic: back off and respect Retry-After (see /agents.md)."
          }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "AjaxError": {
        "type": "object",
        "description": "Error body returned by Shopify AJAX endpoints.",
        "required": [
          "status",
          "message",
          "description"
        ],
        "properties": {
          "status": {
            "description": "HTTP status code (number) or a short error code string such as `bad_request`.",
            "oneOf": [
              {
                "type": "integer"
              },
              {
                "type": "string"
              }
            ]
          },
          "message": {
            "type": "string",
            "description": "Short error title, e.g. `Cart Error`."
          },
          "description": {
            "type": "string",
            "description": "Human-readable reason and hint, e.g. `Cannot find variant`."
          }
        },
        "examples": [
          {
            "status": 422,
            "message": "Cart Error",
            "description": "Cannot find variant"
          }
        ]
      },
      "Money": {
        "type": "string",
        "pattern": "^[0-9]+\\.[0-9]{2}$",
        "description": "Decimal amount in the shopper's currency, e.g. `34.00`."
      },
      "Variant": {
        "type": "object",
        "required": [
          "id",
          "title",
          "price",
          "available"
        ],
        "properties": {
          "id": {
            "type": "integer",
            "description": "Variant ID — pass this as `id` to /cart/add.js."
          },
          "title": {
            "type": "string"
          },
          "sku": {
            "type": [
              "string",
              "null"
            ]
          },
          "price": {
            "description": "Price. Minor units (integer, e.g. 3400 = 34.00) in `.js` responses; decimal string in `.json` responses.",
            "oneOf": [
              {
                "type": "integer"
              },
              {
                "$ref": "#/components/schemas/Money"
              }
            ]
          },
          "compare_at_price": {
            "description": "Original price before discount, same format as price.",
            "oneOf": [
              {
                "type": "integer"
              },
              {
                "$ref": "#/components/schemas/Money"
              },
              {
                "type": "null"
              }
            ]
          },
          "available": {
            "type": "boolean"
          },
          "requires_shipping": {
            "type": "boolean"
          }
        },
        "additionalProperties": true
      },
      "Product": {
        "type": "object",
        "required": [
          "id",
          "title",
          "handle",
          "variants"
        ],
        "properties": {
          "id": {
            "type": "integer"
          },
          "title": {
            "type": "string"
          },
          "handle": {
            "type": "string"
          },
          "vendor": {
            "type": "string"
          },
          "available": {
            "type": "boolean",
            "description": "Present in `.js` responses."
          },
          "price": {
            "type": "integer",
            "description": "Lowest variant price in minor units (`.js` responses)."
          },
          "description": {
            "type": "string",
            "description": "HTML description (`.js` responses)."
          },
          "body_html": {
            "type": "string",
            "description": "HTML description (`.json` responses)."
          },
          "url": {
            "type": "string"
          },
          "images": {
            "type": "array",
            "items": {
              "oneOf": [
                {
                  "type": "string"
                },
                {
                  "type": "object"
                }
              ]
            }
          },
          "variants": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Variant"
            }
          },
          "selling_plan_groups": {
            "type": "array",
            "description": "Subscription options (e.g. Subscribe and save), `.js` responses.",
            "items": {
              "type": "object"
            }
          }
        },
        "additionalProperties": true
      },
      "ProductList": {
        "type": "object",
        "required": [
          "products"
        ],
        "properties": {
          "products": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Product"
            }
          }
        }
      },
      "CartLine": {
        "type": "object",
        "required": [
          "id",
          "quantity",
          "key"
        ],
        "properties": {
          "id": {
            "type": "integer",
            "description": "Variant ID."
          },
          "variant_id": {
            "type": "integer"
          },
          "key": {
            "type": "string",
            "description": "Line key, usable as `id` in /cart/change.js."
          },
          "quantity": {
            "type": "integer"
          },
          "title": {
            "type": "string"
          },
          "price": {
            "type": "integer",
            "description": "Minor units."
          },
          "line_price": {
            "type": "integer",
            "description": "Minor units."
          },
          "url": {
            "type": "string"
          }
        },
        "additionalProperties": true
      },
      "Cart": {
        "type": "object",
        "required": [
          "token",
          "item_count",
          "items",
          "currency",
          "total_price"
        ],
        "properties": {
          "token": {
            "type": "string"
          },
          "item_count": {
            "type": "integer"
          },
          "items": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/CartLine"
            }
          },
          "currency": {
            "type": "string",
            "description": "ISO 4217 code of the cart currency."
          },
          "total_price": {
            "type": "integer",
            "description": "Minor units."
          },
          "original_total_price": {
            "type": "integer"
          },
          "total_discount": {
            "type": "integer"
          },
          "note": {
            "type": [
              "string",
              "null"
            ]
          },
          "attributes": {
            "type": "object"
          },
          "requires_shipping": {
            "type": "boolean"
          }
        },
        "additionalProperties": true
      },
      "AddItemsRequest": {
        "type": "object",
        "required": [
          "items"
        ],
        "properties": {
          "items": {
            "type": "array",
            "minItems": 1,
            "description": "One or more lines to add in a single request.",
            "items": {
              "type": "object",
              "required": [
                "id",
                "quantity"
              ],
              "properties": {
                "id": {
                  "type": "integer",
                  "description": "Variant ID from a product lookup.",
                  "examples": [
                    58584130126172
                  ]
                },
                "quantity": {
                  "type": "integer",
                  "minimum": 1,
                  "examples": [
                    1
                  ]
                },
                "selling_plan": {
                  "type": "integer",
                  "description": "Optional selling plan ID (subscription) from `selling_plan_groups`."
                },
                "properties": {
                  "type": "object",
                  "additionalProperties": {
                    "type": "string"
                  }
                }
              }
            }
          }
        }
      },
      "AddItemsResponse": {
        "type": "object",
        "required": [
          "items"
        ],
        "properties": {
          "items": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/CartLine"
            }
          }
        }
      },
      "ChangeLineRequest": {
        "type": "object",
        "required": [
          "quantity"
        ],
        "properties": {
          "id": {
            "type": "string",
            "description": "Line key (or variant ID) of the line to change."
          },
          "line": {
            "type": "integer",
            "minimum": 1,
            "description": "1-based line index, alternative to `id`."
          },
          "quantity": {
            "type": "integer",
            "minimum": 0,
            "description": "New quantity; 0 removes the line."
          }
        }
      },
      "UpdateCartRequest": {
        "type": "object",
        "properties": {
          "updates": {
            "type": "object",
            "description": "Map of variant ID (or line key) to new quantity.",
            "additionalProperties": {
              "type": "integer",
              "minimum": 0
            }
          },
          "note": {
            "type": "string"
          },
          "attributes": {
            "type": "object",
            "additionalProperties": {
              "type": "string"
            }
          }
        }
      },
      "SuggestResponse": {
        "type": "object",
        "required": [
          "resources"
        ],
        "properties": {
          "resources": {
            "type": "object",
            "properties": {
              "results": {
                "type": "object",
                "properties": {
                  "products": {
                    "type": "array",
                    "items": {
                      "type": "object",
                      "properties": {
                        "id": {
                          "type": "integer"
                        },
                        "title": {
                          "type": "string"
                        },
                        "handle": {
                          "type": "string"
                        },
                        "url": {
                          "type": "string"
                        },
                        "price": {
                          "$ref": "#/components/schemas/Money"
                        },
                        "available": {
                          "type": "boolean"
                        }
                      },
                      "additionalProperties": true
                    }
                  }
                }
              }
            }
          }
        }
      },
      "GraphQLRequest": {
        "type": "object",
        "required": [
          "query"
        ],
        "properties": {
          "query": {
            "type": "string",
            "examples": [
              "{ products(first: 5) { nodes { title handle priceRange { minVariantPrice { amount currencyCode } } } } }"
            ]
          },
          "variables": {
            "type": "object"
          },
          "operationName": {
            "type": "string"
          }
        }
      },
      "GraphQLResponse": {
        "type": "object",
        "properties": {
          "data": {
            "type": [
              "object",
              "null"
            ]
          },
          "errors": {
            "type": "array",
            "items": {
              "type": "object",
              "required": [
                "message"
              ],
              "properties": {
                "message": {
                  "type": "string"
                },
                "path": {
                  "type": "array",
                  "items": {
                    "type": "string"
                  }
                },
                "extensions": {
                  "type": "object",
                  "properties": {
                    "code": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "extensions": {
            "type": "object",
            "properties": {
              "cost": {
                "type": "object"
              }
            }
          }
        }
      },
      "JsonRpcRequest": {
        "type": "object",
        "required": [
          "jsonrpc",
          "method"
        ],
        "properties": {
          "jsonrpc": {
            "const": "2.0"
          },
          "id": {
            "oneOf": [
              {
                "type": "integer"
              },
              {
                "type": "string"
              }
            ]
          },
          "method": {
            "type": "string",
            "description": "MCP method, e.g. `initialize`, `tools/list`, `tools/call`.",
            "examples": [
              "tools/list"
            ]
          },
          "params": {
            "type": "object"
          }
        }
      },
      "JsonRpcResponse": {
        "type": "object",
        "required": [
          "jsonrpc"
        ],
        "properties": {
          "jsonrpc": {
            "const": "2.0"
          },
          "id": {
            "oneOf": [
              {
                "type": "integer"
              },
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ]
          },
          "result": {
            "type": "object"
          },
          "error": {
            "type": "object",
            "required": [
              "code",
              "message"
            ],
            "properties": {
              "code": {
                "type": "integer"
              },
              "message": {
                "type": "string"
              },
              "data": {}
            }
          }
        }
      },
      "UcpProfile": {
        "type": "object",
        "required": [
          "ucp"
        ],
        "properties": {
          "ucp": {
            "type": "object",
            "properties": {
              "version": {
                "type": "string"
              },
              "services": {
                "type": "object"
              },
              "capabilities": {
                "type": "object"
              }
            },
            "additionalProperties": true
          }
        },
        "additionalProperties": true
      }
    },
    "parameters": {
      "handle": {
        "name": "handle",
        "in": "path",
        "required": true,
        "description": "Product handle (URL-encoded). The main product's handle is `pawfectheaven™-liquid-taurine-supplement`.",
        "schema": {
          "type": "string"
        },
        "example": "pawfectheaven™-liquid-taurine-supplement"
      },
      "limit": {
        "name": "limit",
        "in": "query",
        "required": false,
        "description": "Products per page (max 250).",
        "schema": {
          "type": "integer",
          "minimum": 1,
          "maximum": 250,
          "default": 30
        }
      },
      "page": {
        "name": "page",
        "in": "query",
        "required": false,
        "description": "1-based page number. Stop when a page returns an empty `products` array.",
        "schema": {
          "type": "integer",
          "minimum": 1,
          "default": 1
        }
      }
    },
    "securitySchemes": {
      "shopifyCustomerAccount": {
        "type": "oauth2",
        "description": "Optional. Shopify's customer-account OAuth 2.0 server for this store (see /.well-known/openid-configuration). Not needed for any AJAX or GraphQL call here. It is used by the UCP/MCP endpoint for buyer identity linking (signed-in checkout). Clients must be registered with Shopify; there is no self-serve key from PawFectHeaven.",
        "flows": {
          "authorizationCode": {
            "authorizationUrl": "https://shopify.com/authentication/86806724956/oauth/authorize",
            "tokenUrl": "https://shopify.com/authentication/86806724956/oauth/token",
            "refreshUrl": "https://shopify.com/authentication/86806724956/oauth/token",
            "scopes": {
              "openid": "Sign the shopper in (OpenID Connect).",
              "email": "Read the signed-in shopper's email address.",
              "dev.ucp.shopping.catalog.search:read": "Search the catalog through UCP on the shopper's behalf.",
              "dev.ucp.shopping.checkout:manage": "Create and update UCP checkouts on the shopper's behalf.",
              "customer-account-api:full": "Shopify Customer Account API (orders, addresses) for the signed-in shopper.",
              "customer-account-mcp-api:full": "Shopify customer-account MCP tools for the signed-in shopper."
            }
          }
        }
      }
    }
  }
}