{
  "openapi": "3.1.0",
  "info": {
    "title": "Jhilke Studio storefront API",
    "version": "2026-10-08",
    "summary": "Read the catalogue, search prints and build a cart on jhilkestudio.com.",
    "description": "Jhilke Studio sells wall prints (Nepal trek route maps, Nepali words and proverbs) through Shopify. These are the\nshop's public storefront endpoints, run by Shopify. No API key and no account are needed.\n\nPrices in the `.js` endpoints are integers in the smallest currency unit (2695 is EUR 26.95); the `products.json`\nendpoints give decimal strings (\"26.95\"). Prices follow the buyer's market: send the request from the buyer's\ncountry, or use the shop MCP server with `context.address_country`.\n\nThe cart lives in the `cart` cookie that Shopify sets on the first cart call: keep cookies between calls.\nCheckout is not an API call: open https://jhilkestudio.com/checkout in the buyer's browser, where the buyer reviews and pays.\nFor agent shopping with a buyer-approved checkout, the shop's MCP server is https://jhilkestudio.com/api/ucp/mcp (see /agents.md).\n\nErrors are JSON: `{ \"status\": 422, \"message\": \"Cart Error\", \"description\": \"...\" }`.",
    "contact": {
      "name": "Jhilke Studio",
      "url": "https://jhilkestudio.com/pages/contact"
    },
    "termsOfService": "https://jhilkestudio.com/policies/terms-of-service"
  },
  "servers": [
    {
      "url": "https://jhilkestudio.com",
      "description": "The live shop"
    }
  ],
  "externalDocs": {
    "description": "Guide for AI agents",
    "url": "https://jhilkestudio.com/agents.md"
  },
  "tags": [
    {
      "name": "catalogue",
      "description": "Products and collections"
    },
    {
      "name": "search",
      "description": "Find prints by word"
    },
    {
      "name": "cart",
      "description": "The buyer's cart (cookie based)"
    }
  ],
  "paths": {
    "/products.json": {
      "get": {
        "operationId": "listProducts",
        "tags": [
          "catalogue"
        ],
        "summary": "List all products",
        "description": "Every published print with its variants and images, newest first, in pages. Prices are decimal strings.",
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "description": "Products per page, 1 to 250.",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 250,
              "default": 30
            }
          },
          {
            "name": "page",
            "in": "query",
            "description": "Page number, from 1.",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "default": 1
            }
          }
        ],
        "responses": {
          "200": {
            "description": "A page of products.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "products"
                  ],
                  "properties": {
                    "products": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/CatalogueProduct"
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/products/{handle}.js": {
      "get": {
        "operationId": "getProduct",
        "tags": [
          "catalogue"
        ],
        "summary": "Get one product",
        "description": "One print by its handle (the last part of its URL), with every size and format as a variant. Prices are integers in cents. Shopify serves this JSON with the content type text/javascript.",
        "parameters": [
          {
            "name": "handle",
            "in": "path",
            "required": true,
            "description": "Product handle, for example everest-base-camp-dark.",
            "schema": {
              "type": "string",
              "pattern": "^[a-z0-9_-]+$"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The product.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Product"
                }
              }
            }
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      }
    },
    "/collections/{handle}/products.json": {
      "get": {
        "operationId": "listCollectionProducts",
        "tags": [
          "catalogue"
        ],
        "summary": "List the products in a collection",
        "description": "Prints in one collection: trek-route-maps, ek-shabda-one-word, eternal-voice, voices-of-home or all. An unknown collection gives an empty list.",
        "parameters": [
          {
            "name": "handle",
            "in": "path",
            "required": true,
            "description": "Collection handle.",
            "schema": {
              "type": "string",
              "pattern": "^[a-z0-9_-]+$"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "description": "Products per page, 1 to 250.",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 250,
              "default": 30
            }
          },
          {
            "name": "page",
            "in": "query",
            "description": "Page number, from 1.",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "default": 1
            }
          }
        ],
        "responses": {
          "200": {
            "description": "A page of products.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "products"
                  ],
                  "properties": {
                    "products": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/CatalogueProduct"
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/search/suggest.json": {
      "get": {
        "operationId": "searchProducts",
        "tags": [
          "search"
        ],
        "summary": "Search prints by word",
        "description": "Products whose title, tags or description match the words, best match first. Prices are decimal strings.",
        "parameters": [
          {
            "name": "q",
            "in": "query",
            "required": true,
            "description": "Search words, for example \"annapurna\" or \"karma\".",
            "schema": {
              "type": "string",
              "minLength": 1
            }
          },
          {
            "name": "resources[type]",
            "in": "query",
            "description": "What to search; use product.",
            "schema": {
              "type": "string",
              "enum": [
                "product"
              ],
              "default": "product"
            }
          },
          {
            "name": "resources[limit]",
            "in": "query",
            "description": "Results to return, 1 to 10.",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 10,
              "default": 10
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Matching products.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "resources": {
                      "type": "object",
                      "properties": {
                        "results": {
                          "type": "object",
                          "properties": {
                            "products": {
                              "type": "array",
                              "items": {
                                "$ref": "#/components/schemas/SearchResult"
                              }
                            }
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/cart.js": {
      "get": {
        "operationId": "getCart",
        "tags": [
          "cart"
        ],
        "summary": "Read the cart",
        "description": "The cart for the `cart` cookie sent with the request: lines, quantities and totals in cents. Without a cookie it is an empty cart.",
        "responses": {
          "200": {
            "description": "The cart.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Cart"
                }
              }
            }
          }
        }
      }
    },
    "/cart/add.js": {
      "post": {
        "operationId": "addToCart",
        "tags": [
          "cart"
        ],
        "summary": "Add prints to the cart",
        "description": "Adds one or more variants (a print in one size and format) to the cart. Take variant ids from getProduct. Returns the added lines.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "items"
                ],
                "properties": {
                  "items": {
                    "type": "array",
                    "minItems": 1,
                    "items": {
                      "type": "object",
                      "required": [
                        "id",
                        "quantity"
                      ],
                      "properties": {
                        "id": {
                          "type": "integer",
                          "description": "Variant id."
                        },
                        "quantity": {
                          "type": "integer",
                          "minimum": 1
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The lines that were added.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "items": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/CartLine"
                      }
                    }
                  }
                }
              }
            }
          },
          "422": {
            "$ref": "#/components/responses/Unprocessable"
          }
        }
      }
    },
    "/cart/change.js": {
      "post": {
        "operationId": "changeCartLine",
        "tags": [
          "cart"
        ],
        "summary": "Change or remove a cart line",
        "description": "Sets the quantity of one line, found by its line key (or variant id). Quantity 0 removes the line. Returns the whole cart.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "id",
                  "quantity"
                ],
                "properties": {
                  "id": {
                    "type": "string",
                    "description": "Line key from getCart (or a variant id)."
                  },
                  "quantity": {
                    "type": "integer",
                    "minimum": 0
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The cart after the change.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Cart"
                }
              }
            }
          },
          "422": {
            "$ref": "#/components/responses/Unprocessable"
          }
        }
      }
    }
  },
  "components": {
    "responses": {
      "NotFound": {
        "description": "Nothing is published at this address.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "Unprocessable": {
        "description": "The request could not be done, for example an unknown variant id.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      }
    },
    "schemas": {
      "Error": {
        "type": "object",
        "required": [
          "status",
          "message"
        ],
        "properties": {
          "status": {
            "type": [
              "integer",
              "string"
            ],
            "description": "HTTP status."
          },
          "message": {
            "type": "string",
            "description": "Short error name."
          },
          "description": {
            "type": "string",
            "description": "What went wrong and what to do."
          }
        }
      },
      "Variant": {
        "type": "object",
        "properties": {
          "id": {
            "type": "integer"
          },
          "title": {
            "type": "string",
            "description": "Size and format, for example \"30x40 cm / Framed\"."
          },
          "price": {
            "type": "integer",
            "description": "Cents."
          },
          "available": {
            "type": "boolean"
          },
          "sku": {
            "type": [
              "string",
              "null"
            ]
          }
        }
      },
      "Product": {
        "type": "object",
        "properties": {
          "id": {
            "type": "integer"
          },
          "title": {
            "type": "string"
          },
          "handle": {
            "type": "string"
          },
          "description": {
            "type": "string",
            "description": "HTML."
          },
          "vendor": {
            "type": "string"
          },
          "type": {
            "type": "string"
          },
          "tags": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "price": {
            "type": "integer",
            "description": "Lowest variant price in cents."
          },
          "price_min": {
            "type": "integer"
          },
          "price_max": {
            "type": "integer"
          },
          "available": {
            "type": "boolean"
          },
          "url": {
            "type": "string"
          },
          "featured_image": {
            "type": [
              "string",
              "null"
            ]
          },
          "images": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "variants": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Variant"
            }
          }
        }
      },
      "CatalogueProduct": {
        "type": "object",
        "properties": {
          "id": {
            "type": "integer"
          },
          "title": {
            "type": "string"
          },
          "handle": {
            "type": "string"
          },
          "body_html": {
            "type": "string"
          },
          "vendor": {
            "type": "string"
          },
          "product_type": {
            "type": "string"
          },
          "tags": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "variants": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "id": {
                  "type": "integer"
                },
                "title": {
                  "type": "string"
                },
                "price": {
                  "type": "string",
                  "description": "Decimal, for example \"26.95\"."
                },
                "available": {
                  "type": "boolean"
                }
              }
            }
          },
          "images": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "src": {
                  "type": "string"
                },
                "alt": {
                  "type": [
                    "string",
                    "null"
                  ]
                }
              }
            }
          }
        }
      },
      "SearchResult": {
        "type": "object",
        "properties": {
          "id": {
            "type": "integer"
          },
          "title": {
            "type": "string"
          },
          "handle": {
            "type": "string"
          },
          "url": {
            "type": "string"
          },
          "price": {
            "type": "string",
            "description": "Decimal."
          },
          "available": {
            "type": "boolean"
          },
          "image": {
            "type": [
              "string",
              "null"
            ]
          }
        }
      },
      "CartLine": {
        "type": "object",
        "properties": {
          "key": {
            "type": "string"
          },
          "id": {
            "type": "integer",
            "description": "Variant id."
          },
          "product_title": {
            "type": "string"
          },
          "variant_title": {
            "type": [
              "string",
              "null"
            ]
          },
          "quantity": {
            "type": "integer"
          },
          "price": {
            "type": "integer",
            "description": "Cents."
          },
          "line_price": {
            "type": "integer",
            "description": "Cents."
          },
          "url": {
            "type": "string"
          }
        }
      },
      "Cart": {
        "type": "object",
        "properties": {
          "token": {
            "type": "string"
          },
          "item_count": {
            "type": "integer"
          },
          "total_price": {
            "type": "integer",
            "description": "Cents."
          },
          "currency": {
            "type": "string"
          },
          "requires_shipping": {
            "type": "boolean"
          },
          "items": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/CartLine"
            }
          }
        }
      }
    }
  }
}