{
  "openapi": "3.1.0",
  "info": {
    "title": "BoutiqueRugs Agent API",
    "version": "0.1.0",
    "description": "Read-only product catalog + collection endpoints for AI agents. Backed by the Shopify Storefront API. Authentication is not required for catalog reads; cart and checkout flows are handled via /acp.",
    "contact": {
      "name": "BoutiqueRugs",
      "url": "https://boutiquerugs.com"
    }
  },
  "servers": [
    {
      "url": "https://boutiquerugs-companion.boutiquerugs-administrator.workers.dev",
      "description": "Production"
    }
  ],
  "paths": {
    "/health": {
      "get": {
        "summary": "Health check",
        "operationId": "health",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean"
                    },
                    "version": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/products": {
      "get": {
        "summary": "Natural-language product search",
        "operationId": "searchProducts",
        "description": "Natural-language search against the BoutiqueRugs catalog. Powered by a Claude Haiku query parser that extracts price ranges (\"under $200\"), sizes (\"8x10\"), colors (\"navy\"), materials (\"wool\"), tags (\"washable\", \"pet-friendly\", \"outdoor\"), and rooms (\"kids room\") from free-text queries. The response includes an \"interpreted\" object showing exactly which filters the parser extracted — use it to refine follow-up queries or build a faceted UI. Falls back to Shopify keyword search if the NL backend is unavailable (response \"backend\" field indicates which path served the request).",
        "parameters": [
          {
            "name": "q",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Natural-language query, e.g. \"washable rug under $200 for kids room\""
          },
          {
            "name": "page",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "default": 1
            },
            "description": "1-based page. Page size is fixed on the NL backend (~24/page)."
          },
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 50,
              "default": 10
            },
            "description": "Only used when falling back to Shopify keyword search."
          }
        ],
        "responses": {
          "200": {
            "description": "Search results with interpreted filters",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProductList"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/interpret": {
      "get": {
        "summary": "Parse a query into structured filters (no products)",
        "operationId": "interpretQuery",
        "description": "Run a natural-language shopping query through the Claude Haiku parser and return the structured filter interpretation without fetching products. Useful for building a faceted filter UI client-side, debugging search results, or letting an agent refine a query before committing to a full search.",
        "parameters": [
          {
            "name": "q",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Query to parse, e.g. \"soft washable rug under $200\""
          }
        ],
        "responses": {
          "200": {
            "description": "Parsed filter structure",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/QueryInterpretation"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/products/{handle}": {
      "get": {
        "summary": "Get product by handle",
        "operationId": "getProduct",
        "parameters": [
          {
            "name": "handle",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Product detail",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Product"
                }
              }
            }
          },
          "404": {
            "description": "Not found"
          }
        }
      }
    },
    "/api/v1/collections": {
      "get": {
        "summary": "List collections",
        "operationId": "listCollections",
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 250,
              "default": 50
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Collection list",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "count": {
                      "type": "integer"
                    },
                    "collections": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Collection"
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/collections/{handle}": {
      "get": {
        "summary": "Get collection with products",
        "operationId": "getCollection",
        "parameters": [
          {
            "name": "handle",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "default": 24
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Collection detail",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/Collection"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "products": {
                          "type": "array",
                          "items": {
                            "$ref": "#/components/schemas/ProductSummary"
                          }
                        }
                      }
                    }
                  ]
                }
              }
            }
          },
          "404": {
            "description": "Not found"
          }
        }
      }
    },
    "/acp/checkout/session": {
      "post": {
        "summary": "Create an ACP checkout session",
        "operationId": "acpCreateCheckoutSession",
        "description": "Creates a pre-built Shopify cart from the provided items and returns a hosted checkout URL. Payment data never touches this Worker — the returned checkout_url points at Shopify.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "items"
                ],
                "properties": {
                  "items": {
                    "type": "array",
                    "items": {
                      "type": "object",
                      "required": [
                        "variant_id",
                        "quantity"
                      ],
                      "properties": {
                        "variant_id": {
                          "oneOf": [
                            {
                              "type": "string"
                            },
                            {
                              "type": "integer"
                            }
                          ]
                        },
                        "quantity": {
                          "type": "integer",
                          "minimum": 1
                        }
                      }
                    }
                  },
                  "buyer": {
                    "type": "object",
                    "properties": {
                      "email": {
                        "type": "string"
                      },
                      "phone": {
                        "type": "string"
                      },
                      "first_name": {
                        "type": "string"
                      },
                      "last_name": {
                        "type": "string"
                      },
                      "country": {
                        "type": "string"
                      }
                    }
                  },
                  "shipping_address": {
                    "type": "object",
                    "properties": {
                      "line1": {
                        "type": "string"
                      },
                      "line2": {
                        "type": "string"
                      },
                      "city": {
                        "type": "string"
                      },
                      "state": {
                        "type": "string"
                      },
                      "postal_code": {
                        "type": "string"
                      },
                      "country": {
                        "type": "string"
                      },
                      "phone": {
                        "type": "string"
                      }
                    }
                  },
                  "attributes": {
                    "type": "array",
                    "items": {
                      "type": "object",
                      "properties": {
                        "key": {
                          "type": "string"
                        },
                        "value": {
                          "type": "string"
                        }
                      }
                    }
                  },
                  "note": {
                    "type": "string"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Session created"
          },
          "400": {
            "description": "Invalid input"
          },
          "502": {
            "description": "Upstream error (Storefront API)"
          }
        }
      }
    },
    "/acp/checkout/session/{id}": {
      "get": {
        "summary": "Retrieve an ACP checkout session",
        "operationId": "acpGetCheckoutSession",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Session detail"
          },
          "400": {
            "description": "Invalid session id"
          },
          "404": {
            "description": "Session not found or expired"
          }
        }
      }
    },
    "/acp/catalog/search": {
      "get": {
        "summary": "ACP catalog search",
        "operationId": "acpCatalogSearch",
        "parameters": [
          {
            "name": "q",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 50,
              "default": 10
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Search results"
          },
          "400": {
            "description": "Missing query"
          }
        }
      }
    },
    "/mcp": {
      "post": {
        "summary": "MCP JSON-RPC endpoint (Streamable HTTP transport)",
        "description": "See /.well-known/mcp/server-card.json for capabilities. Accepts JSON-RPC 2.0 requests, returns JSON-RPC responses. Supported methods: initialize, tools/list, tools/call.",
        "operationId": "mcpRpc",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "description": "JSON-RPC 2.0 envelope"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "JSON-RPC response"
          }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "ProductSummary": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "handle": {
            "type": "string"
          },
          "title": {
            "type": "string"
          },
          "vendor": {
            "type": "string"
          },
          "url": {
            "type": "string",
            "format": "uri"
          },
          "available": {
            "type": "boolean"
          },
          "price_min": {
            "type": "number"
          },
          "price_max": {
            "type": "number"
          },
          "currency": {
            "type": "string"
          },
          "image": {
            "type": "object",
            "nullable": true,
            "properties": {
              "url": {
                "type": "string"
              },
              "alt": {
                "type": "string"
              }
            }
          }
        }
      },
      "Product": {
        "allOf": [
          {
            "$ref": "#/components/schemas/ProductSummary"
          },
          {
            "type": "object",
            "properties": {
              "description": {
                "type": "string"
              },
              "description_html": {
                "type": "string"
              },
              "tags": {
                "type": "array",
                "items": {
                  "type": "string"
                }
              },
              "options": {
                "type": "array",
                "items": {
                  "type": "object"
                }
              },
              "variants": {
                "type": "array",
                "items": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string"
                    },
                    "title": {
                      "type": "string"
                    },
                    "sku": {
                      "type": "string"
                    },
                    "available": {
                      "type": "boolean"
                    },
                    "price": {
                      "type": "number"
                    },
                    "currency": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          }
        ]
      },
      "ProductList": {
        "type": "object",
        "properties": {
          "query": {
            "type": "string"
          },
          "backend": {
            "type": "string",
            "enum": [
              "nlp",
              "shopify",
              "shopify-fallback"
            ],
            "description": "Which backend served the request. \"nlp\" = Haiku-parsed NL search, \"shopify\" = keyword fallback, \"shopify-fallback\" = NL outage triggered fallback."
          },
          "count": {
            "type": "integer",
            "description": "Products in this page."
          },
          "total": {
            "type": "integer",
            "nullable": true,
            "description": "Total matching products across all pages (NL only)."
          },
          "page": {
            "type": "integer",
            "nullable": true
          },
          "pages": {
            "type": "integer",
            "nullable": true
          },
          "has_next_page": {
            "type": "boolean",
            "nullable": true
          },
          "next_page_url": {
            "type": "string",
            "nullable": true
          },
          "interpreted": {
            "type": "object",
            "nullable": true,
            "description": "Structured filters the NL parser extracted from the query (NL backend only).",
            "properties": {
              "action": {
                "type": "string",
                "nullable": true
              },
              "matches": {
                "type": "array",
                "items": {
                  "type": "object",
                  "properties": {
                    "tag": {
                      "type": "string"
                    },
                    "type": {
                      "type": "string"
                    },
                    "theme": {
                      "type": "string"
                    }
                  }
                }
              },
              "price": {
                "type": "object",
                "nullable": true,
                "properties": {
                  "min": {
                    "type": "number",
                    "nullable": true
                  },
                  "max": {
                    "type": "number",
                    "nullable": true
                  }
                }
              },
              "source": {
                "type": "string",
                "nullable": true
              }
            }
          },
          "products": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ProductSummary"
            }
          }
        }
      },
      "QueryInterpretation": {
        "type": "object",
        "properties": {
          "query": {
            "type": "string"
          },
          "action": {
            "type": "string",
            "nullable": true
          },
          "matches": {
            "type": "array",
            "items": {
              "type": "object"
            }
          },
          "price": {
            "type": "object",
            "nullable": true
          },
          "total_candidates": {
            "type": "integer",
            "nullable": true,
            "description": "How many products would match if the query were executed."
          }
        }
      },
      "Collection": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "handle": {
            "type": "string"
          },
          "title": {
            "type": "string"
          },
          "description": {
            "type": "string"
          },
          "url": {
            "type": "string",
            "format": "uri"
          }
        }
      }
    }
  }
}