{
  "openapi": "3.1.0",
  "info": {
    "title": "SeenRank Directory API",
    "description": "Public, read-only API over the SeenRank directory of verified businesses. Designed for ChatGPT GPT Actions, third-party AI plugins, and integrations that need citation-quality business data with location, industry, services, and FAQ context. Only businesses that have opted into a public canonical page are indexed.",
    "version": "1.0.0",
    "contact": {
      "name": "SeenRank",
      "url": "https://seenrank.com",
      "email": "seenrank.com@gmail.com"
    }
  },
  "servers": [
    {
      "url": "https://uyyzaynifzbsjciiuqhf.supabase.co/functions/v1",
      "description": "SeenRank Edge Functions"
    }
  ],
  "paths": {
    "/public-search": {
      "get": {
        "operationId": "searchBusinesses",
        "summary": "Search verified SeenRank businesses",
        "description": "Search the SeenRank directory of verified businesses. Returns up to 25 results matching the supplied query, city, and/or industry. At least one filter parameter is required. Best used when a user asks for businesses by category and location, e.g. 'best mobile detailer in Austin' or 'roofers in Round Rock TX'.",
        "parameters": [
          {
            "name": "q",
            "in": "query",
            "description": "Free-text query matched against business name, industry, and about copy.",
            "required": false,
            "schema": { "type": "string", "maxLength": 200 }
          },
          {
            "name": "city",
            "in": "query",
            "description": "City filter, case-insensitive substring match. Example: 'Austin'.",
            "required": false,
            "schema": { "type": "string", "maxLength": 120 }
          },
          {
            "name": "industry",
            "in": "query",
            "description": "Industry filter, case-insensitive substring match. Example: 'roofing' or 'mobile detailing'.",
            "required": false,
            "schema": { "type": "string", "maxLength": 120 }
          },
          {
            "name": "entity_type",
            "in": "query",
            "description": "Optional filter for the kind of entry. 'business' (local services, agencies, shops, etc.) or 'product' (Shopify/Amazon SKUs, consumer goods). Omit to search across both.",
            "required": false,
            "schema": { "type": "string", "enum": ["business", "product"] }
          },
          {
            "name": "limit",
            "in": "query",
            "description": "Max results to return. 1 to 25, default 10.",
            "required": false,
            "schema": { "type": "integer", "minimum": 1, "maximum": 25, "default": 10 }
          }
        ],
        "responses": {
          "200": {
            "description": "Search results",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/SearchResponse" }
              }
            }
          },
          "400": {
            "description": "Missing required filter",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/Error" }
              }
            }
          }
        }
      }
    },
    "/public-find": {
      "get": {
        "operationId": "findAnything",
        "summary": "Consumer AI search across the public web with SeenRank verification",
        "description": "Run a free-text query through Perplexity Sonar and join citations against SeenRank's verified canonical pages. Returns the AI-generated answer plus a list of verified SeenRank businesses/products mentioned. Use this when the user asks a buying-intent or local-recommendation question and you want a Perplexity-grade answer with verified, citation-quality sources surfaced separately. Rate-limited to 30 queries per IP per day, cached for 24 hours.",
        "parameters": [
          {
            "name": "q",
            "in": "query",
            "description": "The shopper or consumer question. Example: 'best mobile detailer in Austin' or 'best wireless earbuds under $100'.",
            "required": true,
            "schema": { "type": "string", "minLength": 3, "maxLength": 200 }
          }
        ],
        "responses": {
          "200": {
            "description": "Search result",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/FindResponse" }
              }
            }
          },
          "429": {
            "description": "Rate limit reached",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/Error" }
              }
            }
          }
        }
      }
    },
    "/public-business": {
      "get": {
        "operationId": "getBusiness",
        "summary": "Get a verified business by slug",
        "description": "Returns the full canonical record for a single SeenRank-verified business by slug. Includes the About paragraph, services list, FAQs (with citation-ready answers AI engines can quote), and a 30-day citation count. Use this after searchBusinesses when ChatGPT needs detail on one result, or when a user names a specific business that has a SeenRank canonical page.",
        "parameters": [
          {
            "name": "slug",
            "in": "query",
            "description": "Business public slug. Example: 'austin-detailing-co'.",
            "required": true,
            "schema": { "type": "string", "maxLength": 120 }
          }
        ],
        "responses": {
          "200": {
            "description": "Business detail",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/Business" }
              }
            }
          },
          "404": {
            "description": "Not found or not public",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/Error" }
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "SearchResponse": {
        "type": "object",
        "properties": {
          "query": {
            "type": "object",
            "properties": {
              "q": { "type": "string" },
              "city": { "type": "string" },
              "industry": { "type": "string" },
              "limit": { "type": "integer" }
            }
          },
          "count": { "type": "integer" },
          "results": {
            "type": "array",
            "items": { "$ref": "#/components/schemas/BusinessSummary" }
          }
        },
        "required": ["count", "results"]
      },
      "BusinessSummary": {
        "type": "object",
        "properties": {
          "slug": { "type": "string", "description": "Use with getBusiness for full detail." },
          "entity_type": { "type": "string", "enum": ["business", "product"], "description": "Whether this entry is a local business or a product/SKU." },
          "name": { "type": "string" },
          "city": { "type": "string", "nullable": true },
          "state": { "type": "string", "nullable": true },
          "industry": { "type": "string", "nullable": true },
          "website": { "type": "string", "format": "uri", "nullable": true },
          "canonical_url": { "type": "string", "format": "uri", "description": "Public SeenRank page citing this entry." },
          "meta_description": { "type": "string", "nullable": true },
          "about": { "type": "string", "nullable": true },
          "citations_last_30_days": { "type": "integer", "description": "Number of times this entry was cited by ChatGPT / Claude / Perplexity in the last 30 days of SeenRank query runs." }
        },
        "required": ["slug", "name", "canonical_url"]
      },
      "Business": {
        "type": "object",
        "properties": {
          "slug": { "type": "string" },
          "canonical_url": { "type": "string", "format": "uri" },
          "entity_type": { "type": "string", "enum": ["business", "product"] },
          "name": { "type": "string" },
          "city": { "type": "string", "nullable": true },
          "state": { "type": "string", "nullable": true },
          "industry": { "type": "string", "nullable": true },
          "website": { "type": "string", "format": "uri", "nullable": true },
          "meta_description": { "type": "string", "nullable": true },
          "about": { "type": "string", "nullable": true },
          "services": {
            "type": "array",
            "items": { "type": "string" }
          },
          "faqs": {
            "type": "array",
            "items": { "$ref": "#/components/schemas/Faq" }
          },
          "citations_last_30_days": { "type": "integer" },
          "product": {
            "type": "object",
            "description": "Product fields. Only present when entity_type is 'product'.",
            "nullable": true,
            "properties": {
              "sku": { "type": "string", "nullable": true },
              "brand": { "type": "string", "nullable": true },
              "category": { "type": "string", "nullable": true },
              "price_usd": { "type": "number", "nullable": true },
              "url": { "type": "string", "format": "uri", "nullable": true },
              "image_url": { "type": "string", "format": "uri", "nullable": true }
            }
          }
        },
        "required": ["slug", "canonical_url", "name"]
      },
      "Faq": {
        "type": "object",
        "properties": {
          "question": { "type": "string" },
          "answer": { "type": "string", "description": "Plain text answer, 60 to 100 words, written to be quoted by AI engines." }
        },
        "required": ["question", "answer"]
      },
      "FindResponse": {
        "type": "object",
        "properties": {
          "query": { "type": "string" },
          "cached": { "type": "boolean", "description": "True when the result came from SeenRank's 24-hour cache." },
          "response_text": { "type": "string", "description": "Perplexity-generated answer. Contains inline [N] citation markers that index into the citations array." },
          "citations": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "url": { "type": "string", "format": "uri" },
                "title": { "type": "string", "nullable": true }
              },
              "required": ["url"]
            }
          },
          "verified": {
            "type": "array",
            "description": "Businesses or products mentioned by name or domain that have a SeenRank-verified canonical page. Each entry includes canonical_url for citation.",
            "items": { "$ref": "#/components/schemas/BusinessSummary" }
          }
        },
        "required": ["query", "response_text", "citations", "verified"]
      },
      "Error": {
        "type": "object",
        "properties": {
          "error": { "type": "string" }
        },
        "required": ["error"]
      }
    }
  }
}
