{
  "openapi": "3.1.1",
  "info": {
    "title": "Paqari public product API",
    "version": "1.0.0",
    "description": "Read public product details from Paqari's Shopify storefront. No authentication or OAuth scopes are required for this read-only API. Prices and availability are live values; do not infer availability from this specification. Checkout, customer accounts and Shopify Admin operations are outside this contract. Error responses are controlled by Shopify and may have an empty body."
  },
  "servers": [{"url": "https://paqariofficial.com"}],
  "security": [],
  "externalDocs": {
    "description": "Shopify Ajax Product API, including locale-aware URLs and presentment currency",
    "url": "https://shopify.dev/docs/api/ajax/reference/product"
  },
  "paths": {
    "/products/{handle}.js": {
      "get": {
        "operationId": "getPublicProduct",
        "summary": "Read a public Paqari product",
        "description": "Use a product handle from a current storefront product URL or sitemap. Returns product and variant data without changing a cart or creating an order. Prices use Shopify's presentment-currency subunit convention; this response does not identify the currency. Use locale-aware storefront context when presenting prices to a buyer. Back off on HTTP 429; do not assume a fixed request allowance.",
        "parameters": [{
          "name": "handle",
          "in": "path",
          "required": true,
          "description": "Product URL handle, not a product title or numeric ID.",
          "schema": {"type": "string", "minLength": 1},
          "example": "the-throw-natural"
        }],
        "responses": {
          "200": {
            "description": "Current public product data.",
            "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Product"}}}
          },
          "404": {"description": "Product not found. Shopify may return an empty body. Discover valid product URLs through /sitemap.xml; do not assume every error body is JSON."},
          "429": {"description": "Shopify rate limit reached. Honor Retry-After when provided; otherwise retry with exponential backoff."},
          "default": {"description": "Upstream error. Inspect the HTTP status and content type before parsing; a structured JSON error is not guaranteed."}
        }
      }
    }
  },
  "components": {
    "schemas": {
      "Product": {
        "type": "object",
        "required": ["id", "title", "handle", "price", "available", "variants", "url"],
        "properties": {
          "id": {"type": "integer", "description": "Shopify product ID."},
          "title": {"type": "string"},
          "handle": {"type": "string"},
          "description": {"type": ["string", "null"], "description": "Product description, which can include HTML."},
          "price": {"type": "integer", "description": "Product price in Shopify presentment-currency subunits."},
          "available": {"type": "boolean", "description": "Whether at least one variant is available for sale."},
          "url": {"type": "string", "description": "Relative storefront product URL."},
          "variants": {"type": "array", "items": {"$ref": "#/components/schemas/Variant"}},
          "images": {"type": "array", "items": {"type": "string"}}
        }
      },
      "Variant": {
        "type": "object",
        "required": ["id", "title", "price", "available"],
        "properties": {
          "id": {"type": "integer"},
          "title": {"type": "string"},
          "price": {"type": "integer", "description": "Variant price in Shopify presentment-currency subunits."},
          "available": {"type": "boolean"},
          "sku": {"type": ["string", "null"]}
        }
      }
    }
  }
}
