{
  "openapi": "3.1.0",
  "info": {
    "title": "DealSeek Public API",
    "version": "1.0.0",
    "description": "Public HTTP API for dealseek.com. Every error — unknown paths, validation failures, unsupported methods (405) — uses the ErrorEnvelope shape { error: { code, message, hint } }. Agent entry points: /llms.txt, /sitemap.xml, /.well-known/oauth-protected-resource.",
    "contact": {
      "url": "https://dealseek.com/contact"
    }
  },
  "servers": [
    {
      "url": "https://dealseek.com"
    }
  ],
  "components": {
    "securitySchemes": {
      "supabaseBearer": {
        "type": "http",
        "scheme": "bearer",
        "bearerFormat": "JWT",
        "description": "Supabase-issued user JWT. Required only for endpoints operating on a user's own data."
      }
    },
    "schemas": {
      "ErrorEnvelope": {
        "type": "object",
        "required": [
          "error"
        ],
        "properties": {
          "error": {
            "type": "object",
            "required": [
              "code",
              "message"
            ],
            "properties": {
              "code": {
                "type": "string",
                "description": "Stable machine-readable error code",
                "examples": [
                  "not_found",
                  "bad_request",
                  "internal_error"
                ]
              },
              "message": {
                "type": "string",
                "description": "Human-readable explanation of the failure"
              },
              "hint": {
                "type": "string",
                "description": "How a client can resolve or avoid the error"
              }
            }
          }
        }
      }
    }
  },
  "paths": {
    "/api/merchant-statistics": {
      "get": {
        "operationId": "getMerchantStatistics",
        "summary": "Merchant statistics by slug",
        "description": "Check whether merchant statistics exist for a slug. The slug is matched case-insensitively; dashes/underscores are treated as spaces. A miss is HTTP 200 with exists=false, not a 404.",
        "security": [],
        "parameters": [
          {
            "name": "slug",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            },
            "example": "best-buy"
          }
        ],
        "responses": {
          "200": {
            "description": "Lookup result — exists=false when no merchant matched",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "exists",
                    "matchedMerchantQuery"
                  ],
                  "properties": {
                    "exists": {
                      "type": "boolean"
                    },
                    "matchedMerchantQuery": {
                      "type": [
                        "string",
                        "null"
                      ],
                      "description": "The merchant_query variant that matched, or null on a miss"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Missing slug",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "405": {
            "description": "Method not supported on this route. The Allow header lists the supported methods.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "500": {
            "description": "Statistics backend unavailable",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          }
        }
      }
    },
    "/api/verify-promo": {
      "post": {
        "operationId": "verifyPromo",
        "summary": "Verify a promo code for a product",
        "description": "Checks whether a promo code currently applies to the given Amazon ASIN. Anonymous access is allowed; scoped clients should request promos:verify.",
        "security": [
          {}
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "asin",
                  "code"
                ],
                "properties": {
                  "asin": {
                    "type": "string",
                    "example": "B0F9WTJW68"
                  },
                  "code": {
                    "type": "string",
                    "example": "SAVE20"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Verification result",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "400": {
            "description": "Missing asin or code",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "405": {
            "description": "Method not supported on this route. The Allow header lists the supported methods.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "500": {
            "description": "Verification backend unavailable",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          }
        }
      }
    },
    "/api/report-deal": {
      "post": {
        "operationId": "reportDeal",
        "summary": "Report an inaccurate or expired deal",
        "description": "Submit a report about a deal. Anonymous requests must include userEmail; authenticated sessions may omit it.",
        "security": [
          {},
          {
            "supabaseBearer": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "deal"
                ],
                "properties": {
                  "deal": {
                    "type": "object",
                    "required": [
                      "asin",
                      "merchant_id"
                    ],
                    "properties": {
                      "asin": {
                        "type": "string"
                      },
                      "merchant_id": {
                        "type": "string"
                      },
                      "deal_hash": {
                        "type": "string"
                      },
                      "title": {
                        "type": "string"
                      },
                      "image": {
                        "type": "string"
                      }
                    }
                  },
                  "userEmail": {
                    "type": "string",
                    "format": "email"
                  },
                  "source": {
                    "type": "string"
                  },
                  "reason": {
                    "type": "string"
                  },
                  "reasons": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    }
                  },
                  "reportKind": {
                    "type": "string",
                    "example": "flag"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Report stored",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "400": {
            "description": "User email not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "405": {
            "description": "Method not supported on this route. The Allow header lists the supported methods.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "500": {
            "description": "Failed to store report",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          }
        }
      }
    },
    "/api/{path}": {
      "get": {
        "operationId": "unknownApiPath",
        "summary": "Any undocumented /api path",
        "description": "Every /api path not documented here returns HTTP 404 with a structured JSON error.",
        "security": [],
        "parameters": [
          {
            "name": "path",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "404": {
            "description": "Structured JSON error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          }
        }
      }
    }
  }
}