{
  "openapi": "3.1.0",
  "info": {
    "title": "Fathers Watches Storefront API",
    "version": "1.0.0",
    "description": "Public, read-only Shopify storefront API of fatherswatches.com (Fathers Watches — Swiss Made automatic watches, Naples, Italy). These are the standard Shopify Online Store JSON endpoints exposed by every Shopify shop; no custom backend. Every operation in this spec was verified live with curl on 2026-09-05: only endpoints that actually responded are documented, and the response schemas list the real top-level properties observed in the live responses. Prices are in EUR; note that /products.json and /search/suggest.json return prices as decimal strings (e.g. \"1179.00\") while /cart.js and /recommendations/products.json return integer cents (e.g. 117900). AI-agent discovery resources for this shop: /llms.txt (LLM-oriented site summary), /agents.md (agent usage guide), /.well-known/ucp (Universal Commerce Protocol discovery document) and /api/mcp (MCP endpoint). No authentication of any kind is required or accepted: this is the public unauthenticated storefront surface, hence the top-level `security: []` declaration and the absence of securitySchemes. The store also exposes the versioned Shopify Storefront GraphQL API at /api/2024-07/graphql.json (URL path versioning, introspection enabled, structured JSON errors, per-query cost extension) — see the storefrontGraphQL operation.",
    "contact": {
      "name": "Fathers Watches",
      "url": "https://fatherswatches.com"
    }
  },
  "servers": [
    {
      "url": "https://fatherswatches.com",
      "description": "Production storefront (Shopify, served via Cloudflare)"
    }
  ],
  "security": [],
  "paths": {
    "/products.json": {
      "get": {
        "operationId": "listProducts",
        "summary": "List catalog products",
        "description": "Returns the published products of the online store as a paginated JSON array. Verified live: 200 with `limit=3` and with `limit=2&page=2`. Standard Shopify storefront pagination: `limit` (max 250) and 1-based `page`.",
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "Maximum number of products to return per page. Shopify caps this at 250; default is 30.",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 250,
              "default": 30
            }
          },
          {
            "name": "page",
            "in": "query",
            "required": false,
            "description": "1-based page number for offset pagination. A page past the end returns an empty `products` array.",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "default": 1
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Product listing. Verified live 2026-09-05 (HTTP 200, application/json).",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "products": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/ProductSummary"
                      }
                    }
                  },
                  "required": [
                    "products"
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/products/{handle}.json": {
      "get": {
        "operationId": "getProductByHandle",
        "summary": "Get product detail by handle",
        "description": "Returns the full detail of a single published product addressed by its URL handle. Verified live with the real handle `seafarer` (HTTP 200): the detail object carries richer variant fields than the listing (barcode, price_currency, quantity_rule, weight, weight_unit, ...) plus `image`, `published_scope` and `template_suffix`.",
        "parameters": [
          {
            "name": "handle",
            "in": "path",
            "required": true,
            "description": "Product URL handle (slug), e.g. `seafarer` or `cocktail-attire`.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Product detail. Verified live 2026-09-05 with GET /products/seafarer.json.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "product": {
                      "$ref": "#/components/schemas/ProductDetail"
                    }
                  },
                  "required": [
                    "product"
                  ]
                }
              }
            }
          },
          "404": {
            "description": "Unknown handle. Verified live 2026-09-05 with GET /products/inesistente-xyz.json: the store answers HTTP 404 with `Content-Type: application/json; charset=utf-8` and an EMPTY body (Content-Length: 0). There is no JSON error object on this endpoint — detect the failure from the status code alone."
          }
        }
      }
    },
    "/collections.json": {
      "get": {
        "operationId": "listCollections",
        "summary": "List collections",
        "description": "Returns the published collections of the store (e.g. `accessori`, `diver-evolution`, `diver-horizon`, `gmt-globetrotter`, `regalo-papa`, `offerte-a-tempo`). Verified live: HTTP 200. Note: collection `id` and `products_count` are both plain JSON numbers (integers).",
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "Maximum number of collections to return per page (standard Shopify storefront parameter).",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 250,
              "default": 30
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Collection listing. Verified live 2026-09-05 (HTTP 200, application/json).",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "collections": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Collection"
                      }
                    }
                  },
                  "required": [
                    "collections"
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/collections/{handle}/products.json": {
      "get": {
        "operationId": "listCollectionProducts",
        "summary": "List products in a collection",
        "description": "Returns the products belonging to one collection. Verified live with the real handles `tutti-gli-orologi` and `diver-evolution` (both HTTP 200). Product objects have the same shape as in /products.json. HONEST CAVEAT (verified): an unknown collection handle does NOT return 404 — GET /collections/inesistente-xyz/products.json answered HTTP 200 with `{\"products\": []}` — so an empty array means either an empty collection or a nonexistent one.",
        "parameters": [
          {
            "name": "handle",
            "in": "path",
            "required": true,
            "description": "Collection URL handle, e.g. `tutti-gli-orologi` or `diver-evolution` (see /collections.json for the live list).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "Maximum number of products to return per page (max 250).",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 250,
              "default": 30
            }
          },
          {
            "name": "page",
            "in": "query",
            "required": false,
            "description": "1-based page number for offset pagination.",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "default": 1
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Products of the collection — also returned (with an empty array) for unknown handles; this endpoint never answered 404 in live verification.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "products": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/ProductSummary"
                      }
                    }
                  },
                  "required": [
                    "products"
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/search/suggest.json": {
      "get": {
        "operationId": "searchSuggest",
        "summary": "Predictive search suggestions",
        "description": "Shopify predictive-search endpoint. Verified live with `q=diver&resources[type]=product` (HTTP 200, 10 product hits). Returns matching products nested under `resources.results.products`; each hit carries a ready-to-use relative `url` with search-attribution query params (`_pos`, `_psq`, `_psid`, `_ss`). Prices here are decimal strings in EUR.",
        "parameters": [
          {
            "name": "q",
            "in": "query",
            "required": true,
            "description": "Search query string, e.g. `diver` or `seafarer`.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "resources[type]",
            "in": "query",
            "required": true,
            "description": "Comma-separated resource types to search. Verified with `product`; Shopify also accepts `page`, `article`, `collection`, `query`.",
            "schema": {
              "type": "string",
              "default": "product",
              "examples": [
                "product"
              ]
            }
          },
          {
            "name": "resources[limit]",
            "in": "query",
            "required": false,
            "description": "Maximum results per resource type (standard Shopify predictive-search parameter; default 10 — matches the 10 hits observed live).",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 10,
              "default": 10
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Predictive search results. Verified live 2026-09-05 (HTTP 200, application/json).",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "resources": {
                      "type": "object",
                      "properties": {
                        "results": {
                          "type": "object",
                          "properties": {
                            "products": {
                              "type": "array",
                              "items": {
                                "$ref": "#/components/schemas/SuggestProduct"
                              }
                            }
                          }
                        }
                      }
                    }
                  },
                  "required": [
                    "resources"
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/cart.js": {
      "get": {
        "operationId": "getCart",
        "summary": "Get current cart (AJAX Cart API)",
        "description": "Shopify AJAX Cart API. Returns the cart bound to the caller's session cookie (`cart` / `_shopify_essential`). Verified live: HTTP 200 with a well-formed empty cart (`item_count: 0`, `currency: \"EUR\"`). All monetary amounts on this endpoint are integers in cents. MEDIA-TYPE EXCEPTION (verified live): unlike the *.json endpoints, this endpoint answers with the header `Content-Type: text/javascript; charset=utf-8`, even though the body is a plain JSON document — parse it as JSON but do not rely on an `application/json` Content-Type header.",
        "responses": {
          "200": {
            "description": "Current cart state. Verified live 2026-09-05: HTTP 200 with `Content-Type: text/javascript; charset=utf-8` (NOT application/json) and a JSON body. The media type below documents the header actually observed; the schema describes the JSON payload it carries.",
            "content": {
              "text/javascript": {
                "schema": {
                  "$ref": "#/components/schemas/Cart"
                }
              }
            }
          }
        }
      }
    },
    "/cart/add.js": {
      "post": {
        "operationId": "addToCart",
        "summary": "Add items to cart (AJAX Cart API)",
        "description": "Standard Shopify AJAX Cart API add endpoint. HONESTY NOTE: this operation was deliberately NOT executed during live verification (to avoid creating cart state on the production store); it is documented from the official Shopify AJAX Cart API specification, which applies unchanged to every Shopify storefront, and its sibling GET /cart.js was verified live on this store. Send a JSON body with an `items` array; each item references a variant `id` (variant ids are available from /products/{handle}.json and /products.json). The cart is tied to the session cookie returned by the store.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "items": {
                    "type": "array",
                    "description": "Line items to add.",
                    "items": {
                      "type": "object",
                      "properties": {
                        "id": {
                          "type": "integer",
                          "description": "Variant id to add (e.g. a variant id from /products/seafarer.json)."
                        },
                        "quantity": {
                          "type": "integer",
                          "minimum": 1,
                          "default": 1,
                          "description": "Quantity of the variant."
                        },
                        "properties": {
                          "type": "object",
                          "description": "Optional custom line-item properties (key-value strings).",
                          "additionalProperties": {
                            "type": "string"
                          }
                        }
                      },
                      "required": [
                        "id"
                      ]
                    }
                  }
                },
                "required": [
                  "items"
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Per the standard Shopify AJAX Cart API (not executed live): returns an object with an `items` array describing the line items that were just added.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "items": {
                      "type": "array",
                      "description": "Line items just added to the cart (Shopify line-item objects).",
                      "items": {
                        "type": "object"
                      }
                    }
                  }
                }
              }
            }
          },
          "422": {
            "description": "Per the standard Shopify AJAX Cart API (not executed live): returned when the variant cannot be added (unknown id, sold out, quantity unavailable), with a JSON error object.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "status": {
                      "type": "integer",
                      "description": "HTTP-like status code, e.g. 422."
                    },
                    "message": {
                      "type": "string",
                      "description": "Short error label, e.g. \"Cart Error\"."
                    },
                    "description": {
                      "type": "string",
                      "description": "Human-readable explanation of why the item could not be added."
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/recommendations/products.json": {
      "get": {
        "operationId": "getProductRecommendations",
        "summary": "Product recommendations",
        "description": "Shopify product-recommendations endpoint. Verified live with the real product id 10530088452438 (Fathers Memoria) and `limit=4`: HTTP 200 with 4 recommended products and `intent: \"related\"`. Product objects here use the section-rendering shape (integer prices in cents, `media`, `featured_image` object, `url`), which differs from /products.json. This is the only endpoint of the store observed to return a structured JSON 404 error body.",
        "parameters": [
          {
            "name": "product_id",
            "in": "query",
            "required": true,
            "description": "Numeric id of the reference product (from /products.json or /products/{handle}.json), e.g. 10530088452438 or 9524427882838 (seafarer).",
            "schema": {
              "type": "integer",
              "format": "int64"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "Maximum number of recommendations to return (Shopify caps this at 10).",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 10,
              "default": 10
            }
          },
          {
            "name": "intent",
            "in": "query",
            "required": false,
            "description": "Recommendation intent (standard Shopify parameter). The live response echoed `\"intent\": \"related\"` as the default.",
            "schema": {
              "type": "string",
              "enum": [
                "related",
                "complementary"
              ],
              "default": "related"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Recommended products for the given product id. Verified live 2026-09-05 (HTTP 200, application/json).",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "products": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/RecommendationProduct"
                      }
                    },
                    "intent": {
                      "type": "string",
                      "description": "Recommendation intent used, e.g. \"related\" (observed live)."
                    }
                  },
                  "required": [
                    "products"
                  ]
                }
              }
            }
          },
          "404": {
            "description": "Unknown or unpublished product_id. Verified live 2026-09-05 with product_id=1: HTTP 404 with a real JSON error body.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/NotFoundError"
                },
                "example": {
                  "status": 404,
                  "message": "Product not found",
                  "description": "No product with id 1 is published in the online store"
                }
              }
            }
          }
        }
      }
    },
    "/api/2024-07/graphql.json": {
      "post": {
        "operationId": "storefrontGraphQL",
        "summary": "Shopify Storefront GraphQL API (versioned, zero-auth for public data)",
        "description": "Versioned public Storefront GraphQL endpoint. URL path versioning: /api/{version}/graphql.json with quarterly Shopify API versions (e.g. 2024-07); deprecation policy documented at https://shopify.dev/docs/api/usage/versioning. Verified live 2026-09-05: POST with JSON body {\"query\": \"...\"} returns 200 application/json WITHOUT authentication for public storefront data (shop, products, collections, prices). GraphQL introspection is ENABLED, so the fully typed schema is machine-discoverable (query __schema). Every response carries extensions.cost.requestedQueryCost documenting per-query cost for rate limiting. Errors are structured JSON with code and message (see 200 response schema; GraphQL returns errors in-band with HTTP 200).",
        "security": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "query"
                ],
                "properties": {
                  "query": {
                    "type": "string",
                    "description": "GraphQL query document",
                    "example": "{ products(first: 5) { nodes { title handle variants(first: 1) { nodes { price { amount currencyCode } } } } } }"
                  },
                  "variables": {
                    "type": "object",
                    "description": "Optional GraphQL variables"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "GraphQL result. Verified live 2026-09-05. Success: {data, extensions.cost}. Errors are returned in-band as structured JSON objects with message, locations, path and extensions.code — verified live example: {\"errors\":[{\"message\":\"Field 'campoInesistente' doesn't exist on type 'QueryRoot'\",\"extensions\":{\"code\":\"undefinedField\"}}]}",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": [
                        "object",
                        "null"
                      ],
                      "description": "Query result when successful"
                    },
                    "errors": {
                      "type": "array",
                      "description": "Structured GraphQL errors (present on failure)",
                      "items": {
                        "type": "object",
                        "properties": {
                          "message": {
                            "type": "string"
                          },
                          "locations": {
                            "type": "array",
                            "items": {
                              "type": "object"
                            }
                          },
                          "path": {
                            "type": "array",
                            "items": {
                              "type": "string"
                            }
                          },
                          "extensions": {
                            "type": "object",
                            "description": "Includes machine-readable error code, e.g. undefinedField"
                          }
                        }
                      }
                    },
                    "extensions": {
                      "type": "object",
                      "description": "Includes cost.requestedQueryCost (query cost accounting for rate limits)"
                    }
                  }
                }
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "ProductSummary": {
        "type": "object",
        "description": "Product object as returned by /products.json and /collections/{handle}/products.json (verified live). Prices inside variants are decimal strings in EUR.",
        "properties": {
          "id": {
            "type": "integer",
            "format": "int64",
            "description": "Numeric product id, e.g. 10530088452438 — usable as product_id for /recommendations/products.json."
          },
          "title": {
            "type": "string",
            "description": "Product title, e.g. \"Fathers Seafarer – Orologio Diver Automatico Swiss Made – Blu 40 mm\"."
          },
          "handle": {
            "type": "string",
            "description": "URL handle (slug) — usable as {handle} in /products/{handle}.json."
          },
          "body_html": {
            "type": "string",
            "description": "Product description as HTML."
          },
          "published_at": {
            "type": "string",
            "format": "date-time",
            "description": "Publication timestamp (ISO 8601 with timezone offset)."
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "description": "Creation timestamp."
          },
          "updated_at": {
            "type": "string",
            "format": "date-time",
            "description": "Last update timestamp."
          },
          "vendor": {
            "type": "string",
            "description": "Brand/vendor, e.g. \"Fathers\"."
          },
          "product_type": {
            "type": "string",
            "description": "Merchant-defined product type, e.g. \"Orologi da polso Uomo\"."
          },
          "tags": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Product tags."
          },
          "variants": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/VariantSummary"
            },
            "description": "Purchasable variants."
          },
          "images": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ProductImage"
            },
            "description": "Product images hosted on cdn.shopify.com."
          },
          "options": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ProductOption"
            },
            "description": "Product options (name, position, values)."
          }
        },
        "required": [
          "id",
          "title",
          "handle",
          "variants"
        ]
      },
      "ProductDetail": {
        "type": "object",
        "description": "Full product object as returned by /products/{handle}.json (verified live with handle `seafarer`). Same fields as ProductSummary plus `image`, `published_scope`, `template_suffix`, and richer variant objects.",
        "properties": {
          "id": {
            "type": "integer",
            "format": "int64",
            "description": "Numeric product id, e.g. 9524427882838 for handle `seafarer`."
          },
          "title": {
            "type": "string",
            "description": "Product title."
          },
          "handle": {
            "type": "string",
            "description": "URL handle (slug)."
          },
          "body_html": {
            "type": "string",
            "description": "Product description as HTML."
          },
          "published_at": {
            "type": "string",
            "format": "date-time",
            "description": "Publication timestamp."
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "description": "Creation timestamp."
          },
          "updated_at": {
            "type": "string",
            "format": "date-time",
            "description": "Last update timestamp."
          },
          "vendor": {
            "type": "string",
            "description": "Brand/vendor, e.g. \"Fathers\"."
          },
          "product_type": {
            "type": "string",
            "description": "Merchant-defined product type."
          },
          "published_scope": {
            "type": "string",
            "description": "Publication scope, e.g. \"web\" or \"global\" (present only on the detail endpoint)."
          },
          "template_suffix": {
            "type": [
              "string",
              "null"
            ],
            "description": "Theme template suffix used to render the product page (present only on the detail endpoint)."
          },
          "tags": {
            "description": "Product tags (string or array depending on Shopify serialization).",
            "oneOf": [
              {
                "type": "string"
              },
              {
                "type": "array",
                "items": {
                  "type": "string"
                }
              }
            ]
          },
          "variants": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/VariantDetail"
            },
            "description": "Purchasable variants with the richer detail shape."
          },
          "images": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ProductImage"
            },
            "description": "Product images."
          },
          "image": {
            "$ref": "#/components/schemas/ProductImage",
            "description": "Featured image (present only on the detail endpoint)."
          },
          "options": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ProductOption"
            },
            "description": "Product options."
          }
        },
        "required": [
          "id",
          "title",
          "handle",
          "variants"
        ]
      },
      "VariantSummary": {
        "type": "object",
        "description": "Variant shape observed in /products.json and /collections/{handle}/products.json. Note: `price` is a decimal STRING in EUR (e.g. \"839.00\").",
        "properties": {
          "id": {
            "type": "integer",
            "format": "int64",
            "description": "Variant id — the value to send as `id` in POST /cart/add.js."
          },
          "title": {
            "type": "string",
            "description": "Variant title, e.g. \"Default Title\" for single-variant products."
          },
          "option1": {
            "type": [
              "string",
              "null"
            ],
            "description": "Value of the first product option."
          },
          "option2": {
            "type": [
              "string",
              "null"
            ],
            "description": "Value of the second product option."
          },
          "option3": {
            "type": [
              "string",
              "null"
            ],
            "description": "Value of the third product option."
          },
          "sku": {
            "type": "string",
            "description": "Stock keeping unit, e.g. \"SMS-ALW-MEM-001\"."
          },
          "requires_shipping": {
            "type": "boolean",
            "description": "Whether the variant needs physical shipping."
          },
          "taxable": {
            "type": "boolean",
            "description": "Whether the variant is taxable."
          },
          "featured_image": {
            "type": [
              "object",
              "null"
            ],
            "description": "Variant-specific image, or null."
          },
          "available": {
            "type": "boolean",
            "description": "Whether the variant is currently purchasable."
          },
          "price": {
            "type": "string",
            "description": "Price as decimal string in EUR, e.g. \"839.00\"."
          },
          "compare_at_price": {
            "type": [
              "string",
              "null"
            ],
            "description": "Strikethrough price as decimal string, or null when not discounted."
          },
          "grams": {
            "type": "integer",
            "description": "Weight in grams, e.g. 130."
          },
          "position": {
            "type": "integer",
            "description": "1-based position among the product's variants."
          },
          "product_id": {
            "type": "integer",
            "format": "int64",
            "description": "Parent product id."
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "description": "Creation timestamp."
          },
          "updated_at": {
            "type": "string",
            "format": "date-time",
            "description": "Last update timestamp."
          }
        },
        "required": [
          "id",
          "price",
          "available"
        ]
      },
      "VariantDetail": {
        "type": "object",
        "description": "Richer variant shape observed on /products/{handle}.json (verified with `seafarer`). Includes everything meaningful for purchasing plus currency and inventory metadata.",
        "properties": {
          "id": {
            "type": "integer",
            "format": "int64",
            "description": "Variant id — the value to send as `id` in POST /cart/add.js."
          },
          "product_id": {
            "type": "integer",
            "format": "int64",
            "description": "Parent product id."
          },
          "title": {
            "type": "string",
            "description": "Variant title."
          },
          "price": {
            "type": "string",
            "description": "Price as decimal string, e.g. \"1179.00\"."
          },
          "price_currency": {
            "type": "string",
            "description": "ISO 4217 currency of `price`, e.g. \"EUR\"."
          },
          "compare_at_price": {
            "type": [
              "string",
              "null"
            ],
            "description": "Strikethrough price, or null."
          },
          "compare_at_price_currency": {
            "type": [
              "string",
              "null"
            ],
            "description": "Currency of compare_at_price."
          },
          "sku": {
            "type": "string",
            "description": "Stock keeping unit."
          },
          "barcode": {
            "type": [
              "string",
              "null"
            ],
            "description": "Barcode (EAN/UPC), if set."
          },
          "position": {
            "type": "integer",
            "description": "1-based position among the product's variants."
          },
          "option1": {
            "type": [
              "string",
              "null"
            ],
            "description": "Value of the first product option."
          },
          "option2": {
            "type": [
              "string",
              "null"
            ],
            "description": "Value of the second product option."
          },
          "option3": {
            "type": [
              "string",
              "null"
            ],
            "description": "Value of the third product option."
          },
          "taxable": {
            "type": "boolean",
            "description": "Whether the variant is taxable."
          },
          "requires_shipping": {
            "type": "boolean",
            "description": "Whether the variant needs physical shipping."
          },
          "fulfillment_service": {
            "type": "string",
            "description": "Fulfillment service handle, e.g. \"manual\"."
          },
          "inventory_management": {
            "type": [
              "string",
              "null"
            ],
            "description": "Inventory tracking system, e.g. \"shopify\" or null."
          },
          "grams": {
            "type": "integer",
            "description": "Weight in grams."
          },
          "weight": {
            "type": "number",
            "description": "Weight in `weight_unit`."
          },
          "weight_unit": {
            "type": "string",
            "description": "Unit of `weight`, e.g. \"kg\"."
          },
          "image_id": {
            "type": [
              "integer",
              "null"
            ],
            "format": "int64",
            "description": "Id of the variant-specific image, or null."
          },
          "quantity_rule": {
            "type": "object",
            "description": "B2B-style quantity rule (min/max/increment)."
          },
          "quantity_price_breaks": {
            "type": "array",
            "items": {
              "type": "object"
            },
            "description": "Quantity price breaks (empty for this store)."
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "description": "Creation timestamp."
          },
          "updated_at": {
            "type": "string",
            "format": "date-time",
            "description": "Last update timestamp."
          }
        },
        "required": [
          "id",
          "price"
        ]
      },
      "ProductImage": {
        "type": "object",
        "description": "Product image object (verified live). `src` points to cdn.shopify.com.",
        "properties": {
          "id": {
            "type": "integer",
            "format": "int64",
            "description": "Image id."
          },
          "product_id": {
            "type": "integer",
            "format": "int64",
            "description": "Parent product id."
          },
          "position": {
            "type": "integer",
            "description": "1-based position in the product gallery."
          },
          "src": {
            "type": "string",
            "format": "uri",
            "description": "Absolute CDN URL of the image (cdn.shopify.com). Append size params like `?width=600` for resizing."
          },
          "width": {
            "type": "integer",
            "description": "Original width in pixels."
          },
          "height": {
            "type": "integer",
            "description": "Original height in pixels."
          },
          "alt": {
            "type": [
              "string",
              "null"
            ],
            "description": "Alt text (present on the detail endpoint's `image`)."
          },
          "variant_ids": {
            "type": "array",
            "items": {
              "type": "integer",
              "format": "int64"
            },
            "description": "Variant ids this image is bound to (usually empty)."
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "description": "Creation timestamp."
          },
          "updated_at": {
            "type": "string",
            "format": "date-time",
            "description": "Last update timestamp."
          }
        }
      },
      "ProductOption": {
        "type": "object",
        "description": "Product option (verified live).",
        "properties": {
          "name": {
            "type": "string",
            "description": "Option name, e.g. \"Title\"."
          },
          "position": {
            "type": "integer",
            "description": "1-based option position."
          },
          "values": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Possible values for this option."
          }
        }
      },
      "Collection": {
        "type": "object",
        "description": "Collection object as returned by /collections.json (verified live). `id` is a plain JSON number (integer), same as product ids.",
        "properties": {
          "id": {
            "type": "integer",
            "format": "int64",
            "description": "Numeric collection id, e.g. 645243076950."
          },
          "title": {
            "type": "string",
            "description": "Collection title, e.g. \"Accessori\"."
          },
          "handle": {
            "type": "string",
            "description": "URL handle — usable as {handle} in /collections/{handle}/products.json, e.g. \"diver-evolution\"."
          },
          "description": {
            "type": "string",
            "description": "Collection description as HTML."
          },
          "published_at": {
            "type": "string",
            "format": "date-time",
            "description": "Publication timestamp."
          },
          "updated_at": {
            "type": "string",
            "format": "date-time",
            "description": "Last update timestamp."
          },
          "image": {
            "type": [
              "object",
              "null"
            ],
            "description": "Collection image object (src, dimensions), or null."
          },
          "products_count": {
            "type": "integer",
            "description": "Number of published products in the collection, e.g. 20."
          }
        },
        "required": [
          "id",
          "title",
          "handle"
        ]
      },
      "SuggestProduct": {
        "type": "object",
        "description": "Product hit as returned by /search/suggest.json (verified live with q=diver). Prices are decimal strings in EUR; `url` is a relative product URL with search-attribution params.",
        "properties": {
          "id": {
            "type": "integer",
            "format": "int64",
            "description": "Product id."
          },
          "title": {
            "type": "string",
            "description": "Product title."
          },
          "handle": {
            "type": "string",
            "description": "Product URL handle."
          },
          "url": {
            "type": "string",
            "description": "Relative product URL including search attribution params, e.g. \"/products/cocktail-attire?_pos=1&_psq=diver&_psid=...&_ss=e\"."
          },
          "body": {
            "type": "string",
            "description": "Product description as HTML."
          },
          "available": {
            "type": "boolean",
            "description": "Whether the product is purchasable."
          },
          "price": {
            "type": "string",
            "description": "Price as decimal string, e.g. \"1179.00\"."
          },
          "price_min": {
            "type": "string",
            "description": "Minimum variant price as decimal string."
          },
          "price_max": {
            "type": "string",
            "description": "Maximum variant price as decimal string."
          },
          "compare_at_price_min": {
            "type": "string",
            "description": "Minimum compare-at price as decimal string (\"0.00\" when none)."
          },
          "compare_at_price_max": {
            "type": "string",
            "description": "Maximum compare-at price as decimal string (\"0.00\" when none)."
          },
          "image": {
            "type": "string",
            "format": "uri",
            "description": "Absolute CDN URL of the main image."
          },
          "featured_image": {
            "type": "object",
            "description": "Featured image object."
          },
          "type": {
            "type": "string",
            "description": "Product type, e.g. \"Orologi da polso Uomo\"."
          },
          "vendor": {
            "type": "string",
            "description": "Brand/vendor, e.g. \"Fathers\"."
          },
          "tags": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Product tags."
          },
          "variants": {
            "type": "array",
            "items": {
              "type": "object"
            },
            "description": "Compact variant objects."
          }
        },
        "required": [
          "id",
          "title",
          "handle",
          "url"
        ]
      },
      "Cart": {
        "type": "object",
        "description": "Cart object as returned by GET /cart.js (verified live, empty cart). All monetary amounts are integers in CENTS.",
        "properties": {
          "token": {
            "type": "string",
            "description": "Cart token bound to the session, e.g. \"08d12c9b1ef0d610e9075794b5a69f3f\"."
          },
          "note": {
            "type": [
              "string",
              "null"
            ],
            "description": "Cart note, or null."
          },
          "attributes": {
            "type": "object",
            "description": "Custom cart attributes."
          },
          "original_total_price": {
            "type": "integer",
            "description": "Total before discounts, in cents."
          },
          "total_price": {
            "type": "integer",
            "description": "Total after discounts, in cents."
          },
          "total_discount": {
            "type": "integer",
            "description": "Total discount, in cents."
          },
          "total_weight": {
            "type": "number",
            "description": "Total weight in grams."
          },
          "item_count": {
            "type": "integer",
            "description": "Number of items in the cart."
          },
          "items": {
            "type": "array",
            "items": {
              "type": "object"
            },
            "description": "Line items (empty array when the cart is empty, as observed)."
          },
          "items_subtotal_price": {
            "type": "integer",
            "description": "Subtotal of line items, in cents."
          },
          "requires_shipping": {
            "type": "boolean",
            "description": "Whether any item requires shipping."
          },
          "currency": {
            "type": "string",
            "description": "ISO 4217 cart currency — \"EUR\" observed live."
          },
          "discount_codes": {
            "type": "array",
            "items": {
              "type": "object"
            },
            "description": "Applied discount codes."
          },
          "cart_level_discount_applications": {
            "type": "array",
            "items": {
              "type": "object"
            },
            "description": "Cart-level discount applications."
          }
        },
        "required": [
          "token",
          "item_count",
          "items",
          "total_price",
          "currency"
        ]
      },
      "RecommendationProduct": {
        "type": "object",
        "description": "Product object as returned by /recommendations/products.json (verified live). Uses the section-rendering shape: prices are INTEGERS in cents (e.g. 83900 = EUR 839.00), and the object carries `media`, `featured_image`, and a relative `url`.",
        "properties": {
          "id": {
            "type": "integer",
            "format": "int64",
            "description": "Product id."
          },
          "title": {
            "type": "string",
            "description": "Product title."
          },
          "handle": {
            "type": "string",
            "description": "Product URL handle."
          },
          "url": {
            "type": "string",
            "description": "Relative product URL, e.g. \"/products/...\"."
          },
          "description": {
            "type": "string",
            "description": "Product description as HTML."
          },
          "available": {
            "type": "boolean",
            "description": "Whether the product is purchasable."
          },
          "price": {
            "type": "integer",
            "description": "Price in cents, e.g. 83900."
          },
          "price_min": {
            "type": "integer",
            "description": "Minimum variant price in cents."
          },
          "price_max": {
            "type": "integer",
            "description": "Maximum variant price in cents."
          },
          "price_varies": {
            "type": "boolean",
            "description": "Whether variant prices differ."
          },
          "compare_at_price": {
            "type": [
              "integer",
              "null"
            ],
            "description": "Compare-at price in cents, or null."
          },
          "compare_at_price_min": {
            "type": "integer",
            "description": "Minimum compare-at price in cents."
          },
          "compare_at_price_max": {
            "type": "integer",
            "description": "Maximum compare-at price in cents."
          },
          "compare_at_price_varies": {
            "type": "boolean",
            "description": "Whether compare-at prices differ."
          },
          "featured_image": {
            "type": "string",
            "description": "URL of the featured image."
          },
          "images": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Image URLs."
          },
          "media": {
            "type": "array",
            "items": {
              "type": "object"
            },
            "description": "Media objects (images with preview data)."
          },
          "options": {
            "type": "array",
            "description": "Product options.",
            "items": {}
          },
          "variants": {
            "type": "array",
            "items": {
              "type": "object"
            },
            "description": "Variant objects in section-rendering shape."
          },
          "type": {
            "type": "string",
            "description": "Product type."
          },
          "vendor": {
            "type": "string",
            "description": "Brand/vendor."
          },
          "tags": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Product tags."
          },
          "requires_selling_plan": {
            "type": "boolean",
            "description": "Whether a selling plan is required."
          },
          "selling_plan_groups": {
            "type": "array",
            "items": {
              "type": "object"
            },
            "description": "Selling plan groups (subscriptions)."
          },
          "published_at": {
            "type": "string",
            "format": "date-time",
            "description": "Publication timestamp."
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "description": "Creation timestamp."
          }
        },
        "required": [
          "id",
          "title",
          "handle",
          "url",
          "price"
        ]
      },
      "NotFoundError": {
        "type": "object",
        "description": "Structured JSON 404 error body, observed live ONLY on /recommendations/products.json. Note: /products/{handle}.json answers 404 with an empty body instead.",
        "properties": {
          "status": {
            "type": "integer",
            "description": "HTTP status code, e.g. 404."
          },
          "message": {
            "type": "string",
            "description": "Short error label, e.g. \"Product not found\"."
          },
          "description": {
            "type": "string",
            "description": "Human-readable explanation, e.g. \"No product with id 1 is published in the online store\"."
          }
        },
        "required": [
          "status",
          "message"
        ]
      }
    }
  }
}