{
  "openapi": "3.1.0",
  "info": {
    "title": "Breeza Storefront API",
    "version": "1.0.0",
    "summary": "Public read-only catalog & reviews API for breezasleep.com.",
    "description": "Read-only, same-origin JSON API for the Breeza cooling-sleep store. Use it to search the product catalog and journal and to read approved customer reviews. No authentication is required for these endpoints; they are rate-limited per client IP and return RFC 9331 `RateLimit-*` headers plus `Retry-After` on 429. Errors are structured JSON (`{ error: { code, message, hint } }`). For a human overview see https://www.breezasleep.com/en/developers, and for an LLM index see https://www.breezasleep.com/llms.txt.",
    "contact": {
      "name": "Breeza",
      "url": "https://www.breezasleep.com/en/contact"
    },
    "license": {
      "name": "Proprietary"
    }
  },
  "servers": [
    {
      "url": "https://www.breezasleep.com",
      "description": "Production"
    }
  ],
  "externalDocs": {
    "description": "Developer portal",
    "url": "https://www.breezasleep.com/en/developers"
  },
  "tags": [
    {
      "name": "catalog",
      "description": "Product & journal search."
    },
    {
      "name": "reviews",
      "description": "Approved customer reviews."
    }
  ],
  "paths": {
    "/api/search": {
      "get": {
        "operationId": "searchCatalog",
        "tags": [
          "catalog"
        ],
        "summary": "Search products and journal articles",
        "description": "Full-text search across the product catalog and the journal. Returns up to 6 products (title, handle, thumbnail, cheapest price in the resolved currency) and up to 5 matching articles. Read-only; never modifies cart or account state.",
        "parameters": [
          {
            "name": "q",
            "in": "query",
            "required": true,
            "description": "Free-text query. Minimum 2 characters.",
            "schema": {
              "type": "string",
              "minLength": 2
            },
            "example": "cooling blanket"
          },
          {
            "name": "country",
            "in": "query",
            "required": false,
            "description": "Two-letter locale/region prefix used to resolve currency and language (e.g. `us`, `fr`, `de`). Defaults to `us`.",
            "schema": {
              "type": "string",
              "default": "us"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Search results.",
            "headers": {
              "RateLimit-Limit": {
                "description": "Request cap for the current window.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Remaining": {
                "description": "Requests still available in the current window.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "description": "Seconds until the rate-limit window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Policy": {
                "description": "Policy descriptor, e.g. `30;w=60` (30 requests / 60s).",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SearchResponse"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded.",
            "headers": {
              "RateLimit-Limit": {
                "description": "Request cap for the current window.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Remaining": {
                "description": "Requests still available in the current window.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "description": "Seconds until the rate-limit window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Policy": {
                "description": "Policy descriptor, e.g. `30;w=60` (30 requests / 60s).",
                "schema": {
                  "type": "string"
                }
              },
              "Retry-After": {
                "description": "Seconds to wait before retrying.",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/reviews": {
      "get": {
        "operationId": "listProductReviews",
        "tags": [
          "reviews"
        ],
        "summary": "List approved reviews for a product",
        "description": "Paginated list of approved customer reviews for one product. Supports sorting, star filtering and a photos-only filter. Read-only and public (only approved reviews are ever returned).",
        "parameters": [
          {
            "name": "product_id",
            "in": "query",
            "required": true,
            "description": "Medusa product id (e.g. `prod_...`).",
            "schema": {
              "type": "string",
              "pattern": "^[\\w-]+$"
            }
          },
          {
            "name": "page",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 1,
              "default": 1
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 50,
              "default": 12
            }
          },
          {
            "name": "sort",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "newest",
                "oldest",
                "highest",
                "lowest",
                "photos_first"
              ],
              "default": "newest"
            }
          },
          {
            "name": "stars",
            "in": "query",
            "required": false,
            "description": "Filter to a single star rating.",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 5
            }
          },
          {
            "name": "with_photos",
            "in": "query",
            "required": false,
            "description": "Set to `1` to return only reviews with photos.",
            "schema": {
              "type": "string",
              "enum": [
                "1"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Approved reviews for the product.",
            "headers": {
              "RateLimit-Limit": {
                "description": "Request cap for the current window.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Remaining": {
                "description": "Requests still available in the current window.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "description": "Seconds until the rate-limit window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Policy": {
                "description": "Policy descriptor, e.g. `30;w=60` (30 requests / 60s).",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ReviewList"
                }
              }
            }
          },
          "422": {
            "description": "Missing or malformed `product_id`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded.",
            "headers": {
              "RateLimit-Limit": {
                "description": "Request cap for the current window.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Remaining": {
                "description": "Requests still available in the current window.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "description": "Seconds until the rate-limit window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Policy": {
                "description": "Policy descriptor, e.g. `30;w=60` (30 requests / 60s).",
                "schema": {
                  "type": "string"
                }
              },
              "Retry-After": {
                "description": "Seconds to wait before retrying.",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "502": {
            "description": "Upstream catalog service unavailable.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "Error": {
        "type": "object",
        "required": [
          "error",
          "message"
        ],
        "properties": {
          "error": {
            "type": "object",
            "required": [
              "code",
              "message"
            ],
            "properties": {
              "code": {
                "type": "string",
                "description": "Stable machine-readable error code.",
                "enum": [
                  "rate_limited",
                  "invalid_request",
                  "not_found",
                  "method_not_allowed",
                  "upstream_unavailable"
                ]
              },
              "message": {
                "type": "string"
              },
              "hint": {
                "type": "string",
                "description": "Optional guidance on how to resolve the error."
              }
            }
          },
          "message": {
            "type": "string"
          }
        }
      },
      "ProductHit": {
        "type": "object",
        "required": [
          "title",
          "handle",
          "thumbnail",
          "price"
        ],
        "properties": {
          "title": {
            "type": "string"
          },
          "handle": {
            "type": "string",
            "description": "URL slug; product page is `/{country}/products/{handle}`."
          },
          "thumbnail": {
            "type": [
              "string",
              "null"
            ],
            "format": "uri"
          },
          "price": {
            "type": [
              "string",
              "null"
            ],
            "description": "Formatted cheapest price in the resolved currency."
          }
        }
      },
      "PostHit": {
        "type": "object",
        "required": [
          "title",
          "slug",
          "category"
        ],
        "properties": {
          "title": {
            "type": "string"
          },
          "slug": {
            "type": "string",
            "description": "Article slug; page is `/{country}/blog/{slug}`."
          },
          "category": {
            "type": "string"
          }
        }
      },
      "SearchResponse": {
        "type": "object",
        "required": [
          "products",
          "posts"
        ],
        "properties": {
          "products": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ProductHit"
            }
          },
          "posts": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/PostHit"
            }
          }
        }
      },
      "Review": {
        "type": "object",
        "properties": {
          "rating": {
            "type": "integer",
            "minimum": 1,
            "maximum": 5
          },
          "title": {
            "type": "string"
          },
          "content": {
            "type": "string"
          },
          "author": {
            "type": "string"
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "has_photos": {
            "type": "boolean"
          }
        }
      },
      "ReviewList": {
        "type": "object",
        "description": "Shape proxied from the catalog backend; `reviews` holds the page.",
        "properties": {
          "reviews": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Review"
            }
          },
          "count": {
            "type": "integer"
          },
          "page": {
            "type": "integer"
          },
          "limit": {
            "type": "integer"
          }
        }
      }
    }
  }
}