{
  "swagger": "2.0",
  "info": {
    "title": "LLM Pulse API",
    "description": "REST API for the LLM Pulse AI visibility platform. Swagger 2.0 spec kept in sync with the OpenAPI 3.0 spec at /openapi.json. OAuth 2.1 endpoints (/oauth/authorize, /oauth/token, /oauth/register, /oauth/jwks.json, /.well-known/oauth-authorization-server, /.well-known/oauth-protected-resource) are at the host root (outside this spec's /api/v1 basePath). See the OpenAPI 3.0 spec for full schemas. For full endpoint reference (including response shapes) see /api-docs/llms-full.txt or https://api.llmpulse.ai/api-docs.",
    "version": "1.26.0",
    "contact": {
      "name": "LLM Pulse Support",
      "url": "https://llmpulse.ai",
      "email": "info@llmpulse.ai"
    },
    "license": { "name": "Proprietary", "url": "https://llmpulse.ai/terms" }
  },
  "host": "api.llmpulse.ai",
  "basePath": "/api/v1",
  "schemes": ["https"],
  "consumes": ["application/json"],
  "produces": ["application/json"],
  "securityDefinitions": {
    "BearerAuth": {
      "type": "apiKey",
      "name": "Authorization",
      "in": "header",
      "description": "Send `Bearer YOUR_API_KEY`. Keys start with `llmpulse_` and are managed at https://app.llmpulse.ai/app/api_keys."
    }
  },
  "security": [{ "BearerAuth": [] }],
  "tags": [
    { "name": "Health", "description": "Health check that validates an API key and, optionally, access to a project." },
    { "name": "Projects", "description": "A project is one tracked brand. List and read projects, see which AI models and locales have data, create a project in one call, or drive the multi-step draft wizard." },
    { "name": "Metrics", "description": "Aggregated visibility, share of voice, citation and position data for the project and its competitors: time series, period summary, per-prompt summary, Share of Voice and top cited sources." },
    { "name": "Competitors", "description": "The brands tracked alongside your own. Competitor ids are the actor_id values the metrics endpoints report against." },
    { "name": "Prompts", "description": "The questions executed against the AI models every week, and the execution records each run produces." },
    { "name": "Collections & Tags", "description": "Collections (labelled Tags in the app) group prompts by topic, funnel stage or campaign so metrics can be filtered by them." },
    { "name": "Answers", "description": "The AI responses behind every metric, with their full text, mentions, citations and sentiment analysis." },
    { "name": "Mentions & Citations", "description": "The raw records behind the visibility metrics: one row per brand mention or per cited URL, for the project brand, for competitors, or for both in a single stream." },
    { "name": "Sentiments", "description": "Sentiment records with their comments, topics and scores, plus the category catalog used to label them." },
    { "name": "Sources & Citation Intelligence", "description": "Every URL extracted from AI responses, plus grouped URL, domain and host views, page-cache metadata, mention evidence inside cited pages, occurrences and sanitized cached content." },
    { "name": "AI Model Insights", "description": "Aggregate AI Model Insights report endpoints (summary, position distribution, AI Overview results). All filter by executed_at and share a standard actor shape." },
    { "name": "AI & Agent Traffic", "description": "What AI sends to your site: referral traffic from AI assistants measured by the connected web analytics provider, and AI crawler traffic hitting your origin server. Scale plan and above." },
    { "name": "Search Console", "description": "Google Search Console performance data (impressions, clicks, CTR, average position) for projects with a connected GSC property: headline totals, time series, top queries and top pages. Growth plan and above." },
    { "name": "Recommendations", "description": "Recommendation runs that power the in-app Recommendations page, plus the endpoint that launches a new one." },
    { "name": "GEO Writer", "description": "AI-powered GEO Writer tasks (formerly Content Intelligence). Tasks are processed asynchronously, so create one and poll it until it completes." },
    { "name": "Technical GEO Reports", "description": "Run the technical GEO analysis bundle (crawlability, schema, content readiness, discoverability, site structure, robots.txt, agent readiness, llms.txt, AI visibility) for a URL." },
    { "name": "Annotations", "description": "Mark a date on the project timeline (a campaign launch, a site migration) so charts show what happened when." },
    { "name": "Webhooks", "description": "Outbound event notifications: subscribe an HTTPS URL to project events and receive HMAC-signed deliveries with no polling. Scale plan and above." },
    { "name": "MCP", "description": "Model Context Protocol endpoint for AI clients (Claude, ChatGPT, Cursor and other MCP-compatible assistants)." }
  ],
  "parameters": {
    "Output":        { "name": "output",         "in": "query", "type": "string", "enum": ["flat", "csv"], "description": "Rectangular output for BI tools (Tableau, Excel, Sheets, ELT). Omit for the default nested JSON. 'flat' returns the same metadata plus 'columns' and 'rows'; 'csv' returns those rows as text/csv. Errors are always returned as JSON." },
    "SovView":       { "name": "view",           "in": "query", "type": "string", "enum": ["over_time", "current", "breakdown"], "default": "over_time", "description": "Which Share of Voice projection to flatten. Only valid together with 'output'. 'over_time' (default) is one row per date and actor, 'current' the ranked snapshot, 'breakdown' the Top 4 plus Others." },
    "ProjectId":     { "name": "project_id",     "in": "query", "required": true, "type": "integer", "description": "Project ID" },
    "Competitors":   { "name": "competitors",    "in": "query", "type": "string", "description": "Comma-separated competitor IDs" },
    "Page":          { "name": "page",           "in": "query", "type": "integer", "default": 1, "minimum": 1 },
    "PerPage":       { "name": "per_page",       "in": "query", "type": "integer", "default": 20, "maximum": 100, "minimum": 1 },
    "Metrics":       { "name": "metrics",        "in": "query", "type": "string", "description": "Comma-separated list of metrics: mentions, citations, responses, mention_rate, visibility, weighted_visibility, ai_visibility_score, citation_rate, avg_position, avg_mention_position, net_sentiment, sentiment_*_*. Citations and citation_rate include visible citations and background source references; avg_position uses visible citations only." },
    "Granularity":   { "name": "granularity",    "in": "query", "type": "string", "enum": ["day", "week", "month"] },
    "Range":         { "name": "range",          "in": "query", "type": "integer", "description": "Number of days to look back" },
    "From":          { "name": "from",           "in": "query", "type": "string", "format": "date-time" },
    "To":            { "name": "to",             "in": "query", "type": "string", "format": "date-time" },
    "Model":         { "name": "model",          "in": "query", "type": "string", "enum": ["chatgpt", "perplexity", "gemini", "ai_overview", "ai_mode", "copilot", "claude", "grok", "deepseek", "meta_ai", "amazon_rufus"], "description": "Filter by AI model. Models the API key's user has not enabled are silently dropped." },
    "CollectionId":  { "name": "collection_id",  "in": "query", "type": "integer" },
    "CountryCode":   { "name": "country_code",   "in": "query", "type": "string" },
    "LanguageCode":  { "name": "language_code",  "in": "query", "type": "string" },
    "Prompt":        { "name": "prompt",         "in": "query", "type": "integer" },
    "PromptType":    { "name": "prompt_type",    "in": "query", "type": "string", "enum": ["informational", "navigational", "commercial", "transactional"], "description": "Filter by prompt type (search intent)." },
    "BrandKind":     { "name": "brand_kind",     "in": "query", "type": "string", "enum": ["brand", "brand_other", "non_brand"], "description": "Filter by brand kind: brand (own brand/products), brand_other (competitors/other brands), non_brand (generic, no brand named). For fair 1:1 brand-vs-competitor comparisons (visibility, share of voice), use non_brand: brand-focused prompts skew results toward the brand they name. The in-app Overview page applies non_brand by default." },
    "MentionFilter": { "name": "mention_filter",  "in": "query", "type": "string", "enum": ["mentions_you", "not_mentions_you", "mentions_competitor", "not_mentions_competitor", "you_and_competitor", "competitor_not_you", "you_not_competitor", "no_brands"], "description": "Filter by which brands are mentioned, as a two-axis matrix (your brand x competitors). The four combined cells are you_and_competitor, competitor_not_you (a rival wins and you are absent), you_not_competitor and no_brands (no tracked brand appears). Combine with competitors to narrow the competitor side; on a negative cell that reads none of these. On /dimensions/sources it applies to the crawled content of each cited page. The legacy value competitors_only is accepted as an alias of competitor_not_you." },
    "CitationFilter":{ "name": "citation_filter", "in": "query", "type": "string", "enum": ["cites_you", "not_cites_you", "cites_competitor", "not_cites_competitor", "you_and_competitor", "competitor_not_you", "you_not_competitor", "cites_no_brands"], "description": "The same two-axis matrix applied to the domains cited in the answer. Independent of mention_filter; pass both to intersect them." },
    "IncludeProject":{ "name": "include_project","in": "query", "type": "boolean", "default": true },
    "UrlSha256":     { "name": "url_sha256",     "in": "path",  "required": true, "type": "string", "pattern": "^[a-f0-9]{64}$", "description": "64-character hex SHA-256 of the cited URL" }
  },
  "paths": {
    "/ping": {
      "get": {
        "tags": ["Health"], "summary": "Health check", "operationId": "ping",
        "description": "Validates the API key and optionally pings a project.",
        "parameters": [ { "name": "project_id", "in": "query", "required": false, "type": "integer" } ],
        "responses": { "200": { "description": "API is healthy" }, "401": { "$ref": "#/responses/Unauthorized" } }
      }
    },
    "/metrics/timeseries": { "get": { "tags": ["Metrics"], "summary": "Time-series metrics", "operationId": "getTimeseries",
      "parameters": [ { "$ref": "#/parameters/ProjectId" }, { "$ref": "#/parameters/Metrics" }, { "$ref": "#/parameters/Granularity" }, { "$ref": "#/parameters/Range" }, { "$ref": "#/parameters/From" }, { "$ref": "#/parameters/To" }, { "$ref": "#/parameters/Competitors" }, { "$ref": "#/parameters/Model" }, { "$ref": "#/parameters/CollectionId" }, { "$ref": "#/parameters/CountryCode" }, { "$ref": "#/parameters/LanguageCode" }, { "$ref": "#/parameters/Prompt" }, { "$ref": "#/parameters/PromptType" }, { "$ref": "#/parameters/BrandKind" }, { "$ref": "#/parameters/IncludeProject" }, { "$ref": "#/parameters/Output" } ],
      "responses": { "200": { "description": "Time-series data" }, "401": { "$ref": "#/responses/Unauthorized" }, "404": { "$ref": "#/responses/NotFound" }, "422": { "$ref": "#/responses/UnprocessableEntity" } } } },
    "/metrics/summary": { "get": { "tags": ["Metrics"], "summary": "Aggregated metrics summary", "operationId": "getSummary",
      "description": "Same as /metrics/timeseries with an extra summary + position_distribution block. Citations and citation rate include visible citations and background source references; background references use position 0 and are excluded from avg_position and position distributions. total is a SUM for count metrics and an AVERAGE across periods for rate/percentage metrics (never summed); each summary row carries an aggregation field (sum or average).",
      "parameters": [ { "$ref": "#/parameters/ProjectId" }, { "$ref": "#/parameters/Metrics" }, { "$ref": "#/parameters/Granularity" }, { "$ref": "#/parameters/Range" }, { "$ref": "#/parameters/From" }, { "$ref": "#/parameters/To" }, { "$ref": "#/parameters/Competitors" }, { "$ref": "#/parameters/Model" }, { "$ref": "#/parameters/CollectionId" }, { "$ref": "#/parameters/Prompt" }, { "$ref": "#/parameters/PromptType" }, { "$ref": "#/parameters/BrandKind" }, { "$ref": "#/parameters/Output" } ],
      "responses": { "200": { "description": "Summary metrics" } } } },
    "/metrics/prompt_summary": { "get": { "tags": ["Metrics"], "summary": "Per-prompt metrics summary", "operationId": "getPromptSummary",
      "description": "Paginated per-prompt aggregated metrics with optional breakdown=model. Citations and citation rate include visible citations and background source references; avg_position uses visible citations only.",
      "parameters": [ { "$ref": "#/parameters/ProjectId" }, { "$ref": "#/parameters/Range" }, { "$ref": "#/parameters/From" }, { "$ref": "#/parameters/To" }, { "name": "breakdown", "in": "query", "type": "string", "enum": ["model"] }, { "$ref": "#/parameters/Model" }, { "$ref": "#/parameters/CollectionId" }, { "$ref": "#/parameters/CountryCode" }, { "$ref": "#/parameters/LanguageCode" }, { "$ref": "#/parameters/Prompt" }, { "$ref": "#/parameters/PromptType" }, { "$ref": "#/parameters/BrandKind" }, { "name": "sort", "in": "query", "type": "string", "enum": ["responses", "mentions", "citations", "mention_rate", "visibility", "citation_rate", "avg_mention_position", "avg_position"], "default": "responses" }, { "name": "sort_dir", "in": "query", "type": "string", "enum": ["asc", "desc"], "default": "desc" }, { "$ref": "#/parameters/Page" }, { "$ref": "#/parameters/PerPage" }, { "$ref": "#/parameters/Output" } ],
      "responses": { "200": { "description": "Per-prompt metrics" } } } },
    "/metrics/sov": { "get": { "tags": ["Metrics"], "summary": "Share of Voice", "operationId": "getShareOfVoice",
      "parameters": [ { "$ref": "#/parameters/ProjectId" }, { "$ref": "#/parameters/Range" }, { "$ref": "#/parameters/From" }, { "$ref": "#/parameters/To" }, { "$ref": "#/parameters/Granularity" }, { "$ref": "#/parameters/Competitors" }, { "$ref": "#/parameters/Model" }, { "$ref": "#/parameters/CollectionId" }, { "$ref": "#/parameters/Prompt" }, { "$ref": "#/parameters/PromptType" }, { "$ref": "#/parameters/BrandKind" }, { "$ref": "#/parameters/Output" }, { "$ref": "#/parameters/SovView" } ],
      "responses": { "200": { "description": "Share of voice data" } } } },
    "/metrics/top_sources": { "get": { "tags": ["Metrics"], "summary": "Top cited sources", "description": "Registrable-domain rollup including visible citations and background source references, even when exact-subdomain matching is enabled.", "operationId": "getTopSources",
      "parameters": [ { "$ref": "#/parameters/ProjectId" }, { "$ref": "#/parameters/Range" }, { "$ref": "#/parameters/From" }, { "$ref": "#/parameters/To" }, { "$ref": "#/parameters/Model" }, { "$ref": "#/parameters/CollectionId" }, { "$ref": "#/parameters/CountryCode" }, { "$ref": "#/parameters/LanguageCode" }, { "$ref": "#/parameters/Prompt" }, { "$ref": "#/parameters/PromptType" }, { "$ref": "#/parameters/BrandKind" }, { "name": "sort", "in": "query", "type": "string", "enum": ["total_responses", "avg_mention_rate", "avg_visibility"], "default": "total_responses" }, { "name": "query", "in": "query", "type": "string" }, { "$ref": "#/parameters/Page" }, { "$ref": "#/parameters/PerPage" }, { "$ref": "#/parameters/Output" } ],
      "responses": { "200": { "description": "Top sources" } } } },
    "/metrics/agent_traffic": { "get": { "tags": ["AI & Agent Traffic"], "summary": "AI bot crawler traffic (Scale+, Beta)", "operationId": "getAgentTraffic",
      "description": "Aggregated AI bot traffic. Requires the Scale plan; lower tiers receive ERR_PLAN_REQUIRED.",
      "parameters": [ { "$ref": "#/parameters/ProjectId" }, { "$ref": "#/parameters/Range" }, { "$ref": "#/parameters/From" }, { "$ref": "#/parameters/To" }, { "name": "bot", "in": "query", "type": "string" }, { "name": "company", "in": "query", "type": "string" }, { "name": "group_by", "in": "query", "type": "string", "enum": ["bot", "company"], "default": "bot" }, { "$ref": "#/parameters/Granularity" } ],
      "responses": { "200": { "description": "Agent traffic data" }, "403": { "$ref": "#/responses/PlanRequired" } } } },
    "/metrics/ai_traffic": { "get": { "tags": ["AI & Agent Traffic"], "summary": "AI referral traffic (Scale+)", "operationId": "getAiTraffic",
      "description": "AI referral traffic from AI assistants (ChatGPT, Perplexity, Gemini, etc.), measured from the connected web analytics provider (GA4, Adobe, PostHog, Plausible, Piano). Requires a connected provider and the Scale plan; otherwise ERR_AI_TRAFFIC_NOT_CONNECTED / ERR_PLAN_REQUIRED.",
      "parameters": [ { "$ref": "#/parameters/ProjectId" }, { "$ref": "#/parameters/Range" }, { "$ref": "#/parameters/From" }, { "$ref": "#/parameters/To" }, { "name": "source", "in": "query", "type": "string" }, { "$ref": "#/parameters/Granularity" } ],
      "responses": { "200": { "description": "AI referral traffic data" }, "403": { "$ref": "#/responses/PlanRequired" }, "404": { "$ref": "#/responses/NotFound" } } } },

    "/search_console/summary":    { "get": { "tags": ["Search Console"], "summary": "Search Console summary (Growth+)", "operationId": "getSearchConsoleSummary",
      "description": "Google Search Console headline totals (impressions, clicks, ctr as a 0..1 fraction, average position) over a date range, with optional country/device breakdown. Requires a connected Search Console property (Growth+); otherwise ERR_SEARCH_CONSOLE_NOT_CONNECTED / ERR_PLAN_REQUIRED.",
      "parameters": [ { "$ref": "#/parameters/ProjectId" }, { "$ref": "#/parameters/Range" }, { "$ref": "#/parameters/From" }, { "$ref": "#/parameters/To" }, { "name": "dimension", "in": "query", "type": "string", "enum": ["country", "device"] } ],
      "responses": { "200": { "description": "Search Console summary" }, "403": { "$ref": "#/responses/PlanRequired" }, "404": { "$ref": "#/responses/NotFound" } } } },
    "/search_console/timeseries": { "get": { "tags": ["Search Console"], "summary": "Search Console time series (Growth+)", "operationId": "getSearchConsoleTimeseries",
      "description": "Google Search Console property-wide series bucketed by day/week/month. Requires a connected Search Console property (Growth+).",
      "parameters": [ { "$ref": "#/parameters/ProjectId" }, { "$ref": "#/parameters/Range" }, { "$ref": "#/parameters/From" }, { "$ref": "#/parameters/To" }, { "$ref": "#/parameters/Granularity" }, { "$ref": "#/parameters/Output" } ],
      "responses": { "200": { "description": "Search Console time series" }, "403": { "$ref": "#/responses/PlanRequired" }, "404": { "$ref": "#/responses/NotFound" } } } },
    "/search_console/queries":    { "get": { "tags": ["Search Console"], "summary": "Top Search Console queries (Growth+)", "operationId": "getSearchConsoleQueries",
      "description": "Top Google Search Console search queries over a date range, ranked by impressions/clicks/ctr/position, paginated. Requires a connected Search Console property (Growth+).",
      "parameters": [ { "$ref": "#/parameters/ProjectId" }, { "$ref": "#/parameters/Range" }, { "$ref": "#/parameters/From" }, { "$ref": "#/parameters/To" }, { "name": "sort", "in": "query", "type": "string", "enum": ["impressions", "clicks", "ctr", "position"], "default": "impressions" }, { "$ref": "#/parameters/Page" }, { "$ref": "#/parameters/PerPage" }, { "$ref": "#/parameters/Output" } ],
      "responses": { "200": { "description": "Top queries" }, "403": { "$ref": "#/responses/PlanRequired" }, "404": { "$ref": "#/responses/NotFound" } } } },
    "/search_console/pages":      { "get": { "tags": ["Search Console"], "summary": "Top Search Console pages (Growth+)", "operationId": "getSearchConsolePages",
      "description": "Top Google Search Console landing pages over a date range, ranked by impressions/clicks/ctr/position, paginated. Requires a connected Search Console property (Growth+).",
      "parameters": [ { "$ref": "#/parameters/ProjectId" }, { "$ref": "#/parameters/Range" }, { "$ref": "#/parameters/From" }, { "$ref": "#/parameters/To" }, { "name": "sort", "in": "query", "type": "string", "enum": ["impressions", "clicks", "ctr", "position"], "default": "impressions" }, { "$ref": "#/parameters/Page" }, { "$ref": "#/parameters/PerPage" }, { "$ref": "#/parameters/Output" } ],
      "responses": { "200": { "description": "Top pages" }, "403": { "$ref": "#/responses/PlanRequired" }, "404": { "$ref": "#/responses/NotFound" } } } },

    "/dimensions/projects":         { "get": { "tags": ["Projects"], "summary": "List projects", "operationId": "listProjects", "parameters": [{ "$ref": "#/parameters/Output" }],
        "responses": { "200": { "description": "Projects" } } } },
    "/dimensions/projects/{id}":    { "get": { "tags": ["Projects"], "summary": "Project details", "operationId": "getProjectDetails", "parameters": [ { "name": "id", "in": "path", "required": true, "type": "integer" } ], "responses": { "200": { "description": "Project details" } } } },
    "/dimensions/competitors":      { "get": { "tags": ["Competitors"], "summary": "List competitors", "operationId": "listCompetitors", "parameters": [ { "$ref": "#/parameters/ProjectId" }, { "name": "include_project_brand", "in": "query", "type": "boolean", "default": false }, { "$ref": "#/parameters/Output" } ], "responses": { "200": { "description": "Competitors" } } } },
    "/dimensions/competitors/{id}": { "get": { "tags": ["Competitors"], "summary": "Competitor details", "operationId": "getCompetitorDetails", "parameters": [ { "$ref": "#/parameters/ProjectId" }, { "name": "id", "in": "path", "required": true, "type": "integer" } ], "responses": { "200": { "description": "Competitor details" } } } },
    "/dimensions/collections":      { "get": { "tags": ["Collections & Tags"], "summary": "List tags/collections", "operationId": "listCollections", "parameters": [ { "$ref": "#/parameters/ProjectId" }, { "$ref": "#/parameters/Output" } ], "responses": { "200": { "description": "Collections" } } } },
    "/dimensions/tags":             { "get": { "tags": ["Collections & Tags"], "summary": "List tags (alias)", "operationId": "listTags", "parameters": [ { "$ref": "#/parameters/ProjectId" }, { "$ref": "#/parameters/Output" } ], "responses": { "200": { "description": "Tags" } } } },
    "/dimensions/models":           { "get": { "tags": ["Projects"], "summary": "List models with data", "operationId": "listModels", "parameters": [ { "$ref": "#/parameters/ProjectId" } ], "responses": { "200": { "description": "Models" } } } },
    "/dimensions/locales":          { "get": { "tags": ["Projects"], "summary": "List locales", "operationId": "listLocales", "parameters": [ { "$ref": "#/parameters/ProjectId" } ], "responses": { "200": { "description": "Locales" } } } },
    "/dimensions/sentiments":       { "get": { "tags": ["Sentiments"], "summary": "List sentiment categories", "operationId": "listSentimentCategories", "parameters": [ { "$ref": "#/parameters/ProjectId" }, { "$ref": "#/parameters/Output" } ], "responses": { "200": { "description": "Sentiment buckets" } } } },
    "/dimensions/prompts":          { "get": { "tags": ["Prompts"], "summary": "List prompts", "operationId": "listPrompts", "parameters": [ { "$ref": "#/parameters/ProjectId" }, { "$ref": "#/parameters/Page" }, { "$ref": "#/parameters/PerPage" }, { "$ref": "#/parameters/Model" }, { "$ref": "#/parameters/CollectionId" }, { "$ref": "#/parameters/CountryCode" }, { "$ref": "#/parameters/LanguageCode" }, { "$ref": "#/parameters/PromptType" }, { "$ref": "#/parameters/BrandKind" }, { "$ref": "#/parameters/From" }, { "$ref": "#/parameters/To" }, { "$ref": "#/parameters/Output" } ], "responses": { "200": { "description": "Paginated prompts" } } } },
    "/dimensions/prompt_executions":{ "get": { "tags": ["Prompts"], "summary": "List prompt executions", "operationId": "listPromptExecutions", "parameters": [ { "$ref": "#/parameters/ProjectId" }, { "$ref": "#/parameters/Page" }, { "$ref": "#/parameters/PerPage" }, { "$ref": "#/parameters/Model" }, { "$ref": "#/parameters/CollectionId" }, { "$ref": "#/parameters/CountryCode" }, { "$ref": "#/parameters/LanguageCode" }, { "$ref": "#/parameters/Prompt" }, { "$ref": "#/parameters/From" }, { "$ref": "#/parameters/To" }, { "$ref": "#/parameters/MentionFilter" }, { "$ref": "#/parameters/CitationFilter" }, { "$ref": "#/parameters/Competitors" }, { "$ref": "#/parameters/Output" } ], "responses": { "200": { "description": "Paginated executions" } } } },
    "/dimensions/sources":          { "get": { "tags": ["Sources & Citation Intelligence"], "summary": "List source URLs", "operationId": "listSources", "parameters": [ { "$ref": "#/parameters/ProjectId" }, { "$ref": "#/parameters/Page" }, { "$ref": "#/parameters/PerPage" }, { "$ref": "#/parameters/Model" }, { "$ref": "#/parameters/CollectionId" }, { "$ref": "#/parameters/CountryCode" }, { "$ref": "#/parameters/LanguageCode" }, { "$ref": "#/parameters/Prompt" }, { "$ref": "#/parameters/From" }, { "$ref": "#/parameters/To" }, { "name": "source_type", "in": "query", "type": "string", "enum": ["owned", "competitor", "third_party"], "description": "Owned and competitor matching honor the project's exact-subdomain setting." }, { "$ref": "#/parameters/MentionFilter" }, { "$ref": "#/parameters/Competitors" }, { "$ref": "#/parameters/Output" } ], "responses": { "200": { "description": "Paginated sources" } } } },
    "/dimensions/mentions":         { "get": { "tags": ["Mentions & Citations"], "summary": "List brand mentions", "operationId": "listMentions", "parameters": [ { "$ref": "#/parameters/ProjectId" }, { "$ref": "#/parameters/Page" }, { "$ref": "#/parameters/PerPage" }, { "$ref": "#/parameters/Model" }, { "$ref": "#/parameters/CollectionId" }, { "$ref": "#/parameters/CountryCode" }, { "$ref": "#/parameters/LanguageCode" }, { "$ref": "#/parameters/Prompt" }, { "$ref": "#/parameters/From" }, { "$ref": "#/parameters/To" }, { "$ref": "#/parameters/Output" } ], "responses": { "200": { "description": "Paginated mentions" } } } },
    "/dimensions/citations":        { "get": { "tags": ["Mentions & Citations"], "summary": "List brand citations", "description": "Includes visible citations and background source references. Background references use position 0, meaning no visible rank.", "operationId": "listCitations", "parameters": [ { "$ref": "#/parameters/ProjectId" }, { "$ref": "#/parameters/Page" }, { "$ref": "#/parameters/PerPage" }, { "$ref": "#/parameters/Model" }, { "$ref": "#/parameters/CollectionId" }, { "$ref": "#/parameters/CountryCode" }, { "$ref": "#/parameters/LanguageCode" }, { "$ref": "#/parameters/Prompt" }, { "$ref": "#/parameters/From" }, { "$ref": "#/parameters/To" }, { "$ref": "#/parameters/Output" } ], "responses": { "200": { "description": "Paginated citations" } } } },
    "/dimensions/competitor_mentions":  { "get": { "tags": ["Mentions & Citations"], "summary": "List competitor mentions", "operationId": "listCompetitorMentions", "parameters": [ { "$ref": "#/parameters/ProjectId" }, { "$ref": "#/parameters/Competitors" }, { "$ref": "#/parameters/Page" }, { "$ref": "#/parameters/PerPage" }, { "$ref": "#/parameters/Model" }, { "$ref": "#/parameters/CollectionId" }, { "$ref": "#/parameters/Prompt" }, { "$ref": "#/parameters/From" }, { "$ref": "#/parameters/To" }, { "$ref": "#/parameters/Output" } ], "responses": { "200": { "description": "Paginated competitor mentions" } } } },
    "/dimensions/competitor_citations": { "get": { "tags": ["Mentions & Citations"], "summary": "List competitor citations", "description": "Includes visible citations and background source references. Background references use position 0, meaning no visible rank.", "operationId": "listCompetitorCitations", "parameters": [ { "$ref": "#/parameters/ProjectId" }, { "$ref": "#/parameters/Competitors" }, { "$ref": "#/parameters/Page" }, { "$ref": "#/parameters/PerPage" }, { "$ref": "#/parameters/Model" }, { "$ref": "#/parameters/CollectionId" }, { "$ref": "#/parameters/Prompt" }, { "$ref": "#/parameters/From" }, { "$ref": "#/parameters/To" }, { "$ref": "#/parameters/Output" } ], "responses": { "200": { "description": "Paginated competitor citations" } } } },
    "/dimensions/all_mentions":     { "get": { "tags": ["Mentions & Citations"], "summary": "List all mentions (brand + competitor)", "operationId": "listAllMentions", "description": "Each record has an actor_type field.", "parameters": [ { "$ref": "#/parameters/ProjectId" }, { "$ref": "#/parameters/Competitors" }, { "$ref": "#/parameters/Page" }, { "$ref": "#/parameters/PerPage" }, { "$ref": "#/parameters/Model" }, { "$ref": "#/parameters/CollectionId" }, { "$ref": "#/parameters/Prompt" }, { "$ref": "#/parameters/From" }, { "$ref": "#/parameters/To" }, { "$ref": "#/parameters/Output" } ], "responses": { "200": { "description": "Paginated mentions" } } } },
    "/dimensions/all_citations":    { "get": { "tags": ["Mentions & Citations"], "summary": "List all citations (brand + competitor)", "operationId": "listAllCitations", "description": "Each record has an actor_type field. Includes visible citations and background source references; background references use position 0, meaning no visible rank.", "parameters": [ { "$ref": "#/parameters/ProjectId" }, { "$ref": "#/parameters/Competitors" }, { "$ref": "#/parameters/Page" }, { "$ref": "#/parameters/PerPage" }, { "$ref": "#/parameters/Model" }, { "$ref": "#/parameters/CollectionId" }, { "$ref": "#/parameters/Prompt" }, { "$ref": "#/parameters/From" }, { "$ref": "#/parameters/To" }, { "$ref": "#/parameters/Output" } ], "responses": { "200": { "description": "Paginated citations" } } } },
    "/dimensions/agent_bots":       { "get": { "tags": ["AI & Agent Traffic"], "summary": "AI bot catalog (Scale+)", "operationId": "listAgentBots", "description": "Requires the Scale plan; lower tiers receive ERR_PLAN_REQUIRED. The equivalent MCP tool list_agent_bots is available on all plans.", "parameters": [ { "$ref": "#/parameters/ProjectId" }, { "$ref": "#/parameters/Output" } ], "responses": { "200": { "description": "Bot catalog" }, "403": { "$ref": "#/responses/PlanRequired" } } } },

    "/citation_intelligence/groups": { "get": { "tags": ["Sources & Citation Intelligence"], "summary": "Grouped citation intelligence", "description": "Counts and citation rate include visible citations and background source references. Average position excludes position 0. Owned and competitor source matching honor the project's exact-subdomain setting.", "operationId": "listCitationGroups",
      "parameters": [ { "$ref": "#/parameters/ProjectId" }, { "name": "view", "in": "query", "type": "string", "enum": ["url", "domain", "host"], "default": "url" }, { "$ref": "#/parameters/Page" }, { "$ref": "#/parameters/PerPage" }, { "name": "order", "in": "query", "type": "string", "enum": ["group_key", "total_responses", "total_citations", "citation_rate", "avg_citation_position", "first_seen_at", "last_seen_at"] }, { "name": "direction", "in": "query", "type": "string", "enum": ["asc", "desc"] }, { "$ref": "#/parameters/Model" }, { "$ref": "#/parameters/CollectionId" }, { "$ref": "#/parameters/CountryCode" }, { "$ref": "#/parameters/LanguageCode" }, { "$ref": "#/parameters/Prompt" }, { "$ref": "#/parameters/From" }, { "$ref": "#/parameters/To" }, { "name": "query", "in": "query", "type": "string" }, { "name": "source_type", "in": "query", "type": "string", "enum": ["owned", "competitor", "third_party", "social_media", "own_domain", "ugc", "background"] }, { "name": "sentiment", "in": "query", "type": "string", "enum": ["negative"] }, { "name": "content_gap", "in": "query", "type": "string", "enum": ["mentioned", "gap"] } ],
      "responses": { "200": { "description": "Grouped citation intelligence" }, "422": { "$ref": "#/responses/UnprocessableEntity" } } } },
    "/citation_intelligence/mentions_by_domain": { "get": { "tags": ["Sources & Citation Intelligence"], "summary": "Mention share by citing domain", "operationId": "getMentionsByCitingDomain", "parameters": [ { "$ref": "#/parameters/ProjectId" }, { "name": "domains", "in": "query", "required": true, "type": "array", "items": { "type": "string" }, "collectionFormat": "multi" }, { "$ref": "#/parameters/Model" }, { "$ref": "#/parameters/CollectionId" }, { "$ref": "#/parameters/CountryCode" }, { "$ref": "#/parameters/LanguageCode" }, { "$ref": "#/parameters/Prompt" }, { "$ref": "#/parameters/From" }, { "$ref": "#/parameters/To" } ], "responses": { "200": { "description": "Mention share per citing domain" }, "422": { "$ref": "#/responses/UnprocessableEntity" } } } },
    "/citation_intelligence/urls/{url_sha256}":             { "get": { "tags": ["Sources & Citation Intelligence"], "summary": "Cited URL detail", "operationId": "getCitedUrlDetail", "parameters": [ { "$ref": "#/parameters/ProjectId" }, { "$ref": "#/parameters/UrlSha256" } ], "responses": { "200": { "description": "URL-level intelligence" } } } },
    "/citation_intelligence/urls/{url_sha256}/occurrences": { "get": { "tags": ["Sources & Citation Intelligence"], "summary": "Cited URL occurrences", "operationId": "listCitedUrlOccurrences", "parameters": [ { "$ref": "#/parameters/ProjectId" }, { "$ref": "#/parameters/UrlSha256" }, { "$ref": "#/parameters/Page" }, { "$ref": "#/parameters/PerPage" } ], "responses": { "200": { "description": "Paginated occurrences" } } } },
    "/citation_intelligence/urls/{url_sha256}/content":     { "get": { "tags": ["Sources & Citation Intelligence"], "summary": "Cited URL cached content", "operationId": "getCitedUrlContent", "parameters": [ { "$ref": "#/parameters/ProjectId" }, { "$ref": "#/parameters/UrlSha256" } ], "responses": { "200": { "description": "Sanitized cached content" } } } },

    "/reports/ai_model_insights/summary":                { "get": { "tags": ["AI Model Insights"], "summary": "AI Model Insights summary", "operationId": "getAiModelInsightsSummary", "parameters": [ { "$ref": "#/parameters/ProjectId" }, { "$ref": "#/parameters/Range" }, { "$ref": "#/parameters/From" }, { "$ref": "#/parameters/To" }, { "$ref": "#/parameters/Granularity" }, { "$ref": "#/parameters/CollectionId" }, { "$ref": "#/parameters/CountryCode" }, { "$ref": "#/parameters/LanguageCode" }, { "$ref": "#/parameters/PromptType" }, { "$ref": "#/parameters/BrandKind" }, { "$ref": "#/parameters/Competitors" } ], "responses": { "200": { "description": "Summary" } } } },
    "/reports/ai_model_insights/position_distribution":  { "get": { "tags": ["AI Model Insights"], "summary": "Position distribution comparison", "operationId": "getAiModelPositionDistribution", "parameters": [ { "$ref": "#/parameters/ProjectId" }, { "$ref": "#/parameters/Range" }, { "$ref": "#/parameters/From" }, { "$ref": "#/parameters/To" }, { "$ref": "#/parameters/Granularity" }, { "$ref": "#/parameters/CollectionId" }, { "$ref": "#/parameters/CountryCode" }, { "$ref": "#/parameters/LanguageCode" }, { "$ref": "#/parameters/PromptType" }, { "$ref": "#/parameters/BrandKind" }, { "$ref": "#/parameters/Model" }, { "name": "brand1", "in": "query", "type": "integer" }, { "name": "brand2", "in": "query", "type": "integer" } ], "responses": { "200": { "description": "Bucketed position totals" } } } },
    "/reports/ai_model_insights/ai_overview_results":    { "get": { "tags": ["AI Model Insights"], "summary": "Google AI Overview result availability", "operationId": "getAiOverviewResults", "parameters": [ { "$ref": "#/parameters/ProjectId" }, { "$ref": "#/parameters/Range" }, { "$ref": "#/parameters/From" }, { "$ref": "#/parameters/To" }, { "$ref": "#/parameters/Granularity" }, { "$ref": "#/parameters/CollectionId" }, { "$ref": "#/parameters/CountryCode" }, { "$ref": "#/parameters/LanguageCode" }, { "$ref": "#/parameters/PromptType" }, { "$ref": "#/parameters/BrandKind" }, { "$ref": "#/parameters/Page" }, { "$ref": "#/parameters/PerPage" } ], "responses": { "200": { "description": "AI Overview results" } } } },

    "/answers":         { "get": { "tags": ["Answers"], "summary": "List AI responses", "operationId": "listAnswers", "description": "Pass query for case-insensitive full-text search inside response texts: total becomes the exact match count and items return snippet + match_count instead of response.", "parameters": [ { "$ref": "#/parameters/ProjectId" }, { "$ref": "#/parameters/Model" }, { "$ref": "#/parameters/CollectionId" }, { "$ref": "#/parameters/CountryCode" }, { "$ref": "#/parameters/LanguageCode" }, { "$ref": "#/parameters/Prompt" }, { "$ref": "#/parameters/From" }, { "$ref": "#/parameters/To" }, { "$ref": "#/parameters/Page" }, { "$ref": "#/parameters/PerPage" }, { "$ref": "#/parameters/MentionFilter" }, { "$ref": "#/parameters/CitationFilter" }, { "$ref": "#/parameters/Competitors" }, { "name": "query", "in": "query", "required": false, "type": "string", "description": "Case-insensitive full-text search inside AI response texts." } ], "responses": { "200": { "description": "Paginated answers" }, "422": { "$ref": "#/responses/UnprocessableEntity" } } } },
    "/answers/{id}":    { "get": { "tags": ["Answers"], "summary": "Get one AI response", "operationId": "getAnswer", "parameters": [ { "$ref": "#/parameters/ProjectId" }, { "name": "id", "in": "path", "required": true, "type": "integer" }, { "name": "include_source_page_details", "in": "query", "type": "boolean", "default": false } ], "responses": { "200": { "description": "Answer details" } } } },

    "/sentiments":      { "get": { "tags": ["Sentiments"], "summary": "List sentiment records", "operationId": "listSentimentRecords", "parameters": [ { "$ref": "#/parameters/ProjectId" }, { "name": "competitor_id", "in": "query", "type": "integer" }, { "name": "brand_only", "in": "query", "type": "boolean" }, { "name": "analysis", "in": "query", "type": "string", "enum": ["very_positive", "positive", "neutral", "negative", "very_negative"] }, { "$ref": "#/parameters/Model" }, { "$ref": "#/parameters/CollectionId" }, { "$ref": "#/parameters/CountryCode" }, { "$ref": "#/parameters/LanguageCode" }, { "$ref": "#/parameters/From" }, { "$ref": "#/parameters/To" }, { "$ref": "#/parameters/Page" }, { "$ref": "#/parameters/PerPage" } ], "responses": { "200": { "description": "Paginated sentiments" }, "422": { "$ref": "#/responses/UnprocessableEntity" } } } },

    "/recommendations":      { "get": { "tags": ["Recommendations"], "summary": "List recommendation runs", "operationId": "listRecommendations", "parameters": [ { "$ref": "#/parameters/ProjectId" }, { "name": "recommendation_type", "in": "query", "type": "string", "enum": ["ai_visibility", "social_community", "brand_building", "sentiment_reputation"] }, { "name": "status", "in": "query", "type": "string", "enum": ["pending", "processing", "completed", "failed"] }, { "$ref": "#/parameters/Page" }, { "$ref": "#/parameters/PerPage" } ], "responses": { "200": { "description": "Paginated recommendations" } } },
      "post": { "tags": ["Recommendations"], "summary": "Launch a recommendations generation", "operationId": "launchRecommendations",
        "parameters": [ { "name": "body", "in": "body", "required": true, "schema": { "type": "object", "required": ["project_id"], "properties": { "project_id": { "type": "integer" }, "recommendation_type": { "type": "string", "enum": ["ai_visibility", "social_community", "brand_building", "sentiment_reputation"], "default": "ai_visibility" } } } } ],
        "responses": { "201": { "description": "Generation launched (status pending)" }, "403": { "$ref": "#/responses/InsufficientScope" }, "422": { "$ref": "#/responses/UnprocessableEntity" } } } },
    "/recommendations/{id}": { "get": { "tags": ["Recommendations"], "summary": "Get recommendation run", "operationId": "getRecommendation", "parameters": [ { "$ref": "#/parameters/ProjectId" }, { "name": "id", "in": "path", "required": true, "type": "integer" }, { "name": "item_status", "in": "query", "type": "string", "enum": ["active", "completed", "archived"] }, { "name": "resolve_source_refs", "in": "query", "type": "boolean", "default": true } ], "responses": { "200": { "description": "Recommendation detail" } } } },

    "/project_drafts": { "post": { "tags": ["Projects"], "summary": "Start a project draft (wizard step 1)", "operationId": "createProjectDraft",
      "parameters": [ { "name": "body", "in": "body", "required": true, "schema": { "type": "object", "required": ["website_url", "main_country", "main_language"], "properties": { "website_url": { "type": "string", "format": "uri", "description": "Public HTTP(S) URL with a DNS hostname or public IP address. Credentials, private and special IP addresses, localhost and internal hostnames are rejected." }, "main_country": { "type": "string" }, "main_language": { "type": "string" }, "use_subdomain": { "type": "boolean" }, "suggest": { "type": "boolean" }, "execute_prompts_immediately": { "type": "boolean" } } } } ],
      "responses": { "201": { "description": "Draft created" }, "422": { "$ref": "#/responses/UnprocessableEntity" }, "403": { "$ref": "#/responses/InsufficientScope" } } } },
    "/project_drafts/{id}": {
      "get": { "tags": ["Projects"], "summary": "Read a project draft", "operationId": "getProjectDraft",
        "parameters": [ { "name": "id", "in": "path", "required": true, "type": "string" }, { "name": "include_suggestions", "in": "query", "type": "boolean" } ],
        "responses": { "200": { "description": "Draft envelope" }, "404": { "$ref": "#/responses/NotFound" } } },
      "patch": { "tags": ["Projects"], "summary": "Submit a wizard step", "operationId": "updateProjectDraft",
        "parameters": [ { "name": "id", "in": "path", "required": true, "type": "string" }, { "name": "body", "in": "body", "required": true, "schema": { "type": "object", "required": ["step"], "properties": { "step": { "type": "string", "enum": ["details", "prompts", "competitors", "owned_media"] } } } } ],
        "responses": { "200": { "description": "Draft envelope with next-step suggestions" }, "404": { "$ref": "#/responses/NotFound" }, "422": { "$ref": "#/responses/UnprocessableEntity" } } } },
    "/project_drafts/{id}/finalize": { "post": { "tags": ["Projects"], "summary": "Finalize a draft into a real project", "operationId": "finalizeProjectDraft",
      "parameters": [ { "name": "id", "in": "path", "required": true, "type": "string" }, { "name": "body", "in": "body", "required": false, "schema": { "type": "object", "properties": { "weekly_email_subscribed": { "type": "boolean" }, "execute_prompts_immediately": { "type": "boolean" } } } } ],
      "responses": { "201": { "description": "Project created" }, "200": { "description": "Idempotent replay" }, "404": { "$ref": "#/responses/NotFound" }, "422": { "$ref": "#/responses/UnprocessableEntity" } } } },
    "/projects": { "post": { "tags": ["Projects"], "summary": "Create a project (fast mode)", "operationId": "createProject",
      "parameters": [ { "name": "body", "in": "body", "required": true, "schema": { "type": "object", "required": ["website_url", "name", "main_country", "main_language"], "properties": { "website_url": { "type": "string", "format": "uri", "description": "Public HTTP(S) URL with a DNS hostname or public IP address. Credentials, private and special IP addresses, localhost and internal hostnames are rejected." }, "name": { "type": "string" }, "main_country": { "type": "string" }, "main_language": { "type": "string" }, "brand_name": { "type": "string" }, "description": { "type": "string" }, "industry": { "type": "array", "items": { "type": "string" } }, "matching_names": { "type": "array", "items": { "type": "string" } }, "prompts": { "type": "array", "items": { "type": "string" }, "maxItems": 100 }, "competitors": { "type": "array", "items": { "type": "object" } }, "owned_media": { "type": "object" }, "use_subdomain": { "type": "boolean" }, "weekly_email_subscribed": { "type": "boolean" }, "external_identifier": { "type": "string", "pattern": "^[a-z0-9_-]{1,64}$", "description": "Embed-enabled (Enterprise) accounts only; other accounts receive ERR_PLAN_REQUIRED" }, "execute_prompts_immediately": { "type": "boolean" } } } } ],
      "responses": { "201": { "description": "Created" }, "200": { "description": "Idempotent replay (existing external_identifier)" }, "403": { "$ref": "#/responses/InsufficientScope" }, "422": { "$ref": "#/responses/UnprocessableEntity" } } } },

    "/prompts": { "post": { "tags": ["Prompts"], "summary": "Bulk-create prompts", "operationId": "createPrompts",
      "parameters": [ { "name": "body", "in": "body", "required": true, "schema": { "type": "object", "required": ["project_id", "prompts", "country_code", "language_code"], "properties": { "project_id": { "type": "integer" }, "prompts": { "type": "array", "items": { "type": "string" }, "maxItems": 100 }, "country_code": { "type": "string" }, "language_code": { "type": "string" } } } } ],
      "responses": { "201": { "description": "Created" }, "403": { "$ref": "#/responses/InsufficientScope" }, "422": { "$ref": "#/responses/UnprocessableEntity" } } } },
    "/prompts/{id}": { "delete": { "tags": ["Prompts"], "summary": "Delete a prompt", "operationId": "deletePrompt",
      "parameters": [ { "$ref": "#/parameters/ProjectId" }, { "name": "id", "in": "path", "required": true, "type": "integer" } ],
      "responses": { "200": { "description": "Deleted" }, "403": { "$ref": "#/responses/InsufficientScope" }, "404": { "$ref": "#/responses/NotFound" } } } },

    "/prompts/assign_tags": { "post": { "tags": ["Collections & Tags"], "summary": "Bulk-attach tags to prompts", "operationId": "assignPromptTags",
      "parameters": [ { "name": "body", "in": "body", "required": true, "schema": { "type": "object", "required": ["project_id", "prompt_ids"], "properties": { "project_id": { "type": "integer" }, "prompt_ids": { "type": "array", "items": { "type": "integer" } }, "tag_ids": { "type": "array", "items": { "type": "integer" } }, "tag_names": { "type": "array", "items": { "type": "string" } }, "create_missing": { "type": "boolean" } } } } ],
      "responses": { "200": { "description": "Tags attached" }, "403": { "$ref": "#/responses/InsufficientScope" }, "422": { "$ref": "#/responses/UnprocessableEntity" } } } },

    "/competitors": { "post": { "tags": ["Competitors"], "summary": "Add a competitor", "operationId": "createCompetitor",
      "parameters": [ { "name": "body", "in": "body", "required": true, "schema": { "type": "object", "required": ["project_id", "brand_name", "domain"], "properties": { "project_id": { "type": "integer" }, "brand_name": { "type": "string" }, "domain": { "type": "string" }, "matching_names": { "type": "array", "items": { "type": "string" } } } } } ],
      "responses": { "201": { "description": "Created" }, "403": { "$ref": "#/responses/InsufficientScope" }, "422": { "$ref": "#/responses/UnprocessableEntity" } } } },
    "/competitors/{id}": {
      "patch": { "tags": ["Competitors"], "summary": "Update a competitor", "operationId": "updateCompetitor",
        "parameters": [ { "name": "id", "in": "path", "required": true, "type": "integer" }, { "name": "body", "in": "body", "required": true, "schema": { "type": "object", "required": ["project_id"], "properties": { "project_id": { "type": "integer" }, "brand_name": { "type": "string" }, "matching_names": { "type": "array", "items": { "type": "string" } }, "color": { "type": "string" } } } } ],
        "responses": { "200": { "description": "Updated" }, "403": { "$ref": "#/responses/InsufficientScope" }, "404": { "$ref": "#/responses/NotFound" }, "422": { "$ref": "#/responses/UnprocessableEntity" } } },
      "delete": { "tags": ["Competitors"], "summary": "Delete a competitor", "operationId": "deleteCompetitor",
        "parameters": [ { "$ref": "#/parameters/ProjectId" }, { "name": "id", "in": "path", "required": true, "type": "integer" } ],
        "responses": { "200": { "description": "Deleted" }, "403": { "$ref": "#/responses/InsufficientScope" }, "404": { "$ref": "#/responses/NotFound" } } } },

    "/collections": { "post": { "tags": ["Collections & Tags"], "summary": "Create a tag", "operationId": "createCollection",
      "parameters": [ { "name": "body", "in": "body", "required": true, "schema": { "type": "object", "required": ["project_id", "name"], "properties": { "project_id": { "type": "integer" }, "name": { "type": "string" }, "description": { "type": "string" }, "prompt_ids": { "type": "array", "items": { "type": "integer" } } } } } ],
      "responses": { "201": { "description": "Created" }, "403": { "$ref": "#/responses/InsufficientScope" }, "422": { "$ref": "#/responses/UnprocessableEntity" } } } },
    "/collections/{id}": {
      "patch": { "tags": ["Collections & Tags"], "summary": "Update a tag", "operationId": "updateCollection",
        "parameters": [ { "name": "id", "in": "path", "required": true, "type": "integer" }, { "name": "body", "in": "body", "required": true, "schema": { "type": "object", "required": ["project_id"], "properties": { "project_id": { "type": "integer" }, "name": { "type": "string" }, "description": { "type": "string" } } } } ],
        "responses": { "200": { "description": "Updated" }, "403": { "$ref": "#/responses/InsufficientScope" }, "404": { "$ref": "#/responses/NotFound" }, "422": { "$ref": "#/responses/UnprocessableEntity" } } },
      "delete": { "tags": ["Collections & Tags"], "summary": "Delete a tag", "operationId": "deleteCollection",
        "parameters": [ { "$ref": "#/parameters/ProjectId" }, { "name": "id", "in": "path", "required": true, "type": "integer" } ],
        "responses": { "200": { "description": "Deleted" }, "403": { "$ref": "#/responses/InsufficientScope" }, "404": { "$ref": "#/responses/NotFound" } } } },

    "/annotations": {
      "get": { "tags": ["Annotations"], "summary": "List timeline annotations", "operationId": "listAnnotations",
        "description": "Lists project timeline annotations, newest first. Rows can come from manual notes, project automations, GEO tests, or platform events. The origin field distinguishes them; editable says whether the requesting user may modify the row.",
        "parameters": [ { "$ref": "#/parameters/ProjectId" }, { "name": "from", "in": "query", "type": "string", "format": "date" }, { "name": "to", "in": "query", "type": "string", "format": "date" }, { "name": "annotation_category_id", "in": "query", "type": "integer" }, { "$ref": "#/parameters/Page" }, { "$ref": "#/parameters/PerPage" } ],
        "responses": { "200": { "description": "Paginated annotations" }, "403": { "$ref": "#/responses/Forbidden" } } },
      "post": { "tags": ["Annotations"], "summary": "Create a timeline annotation", "operationId": "createAnnotation",
        "parameters": [ { "name": "body", "in": "body", "required": true, "schema": { "type": "object", "required": ["project_id", "title"], "properties": { "project_id": { "type": "integer" }, "title": { "type": "string" }, "annotation_date": { "type": "string", "format": "date" }, "description": { "type": "string" }, "color": { "type": "string" }, "annotation_category_id": { "type": "integer" } } } } ],
        "responses": { "201": { "description": "Created" }, "403": { "$ref": "#/responses/InsufficientScope" }, "422": { "$ref": "#/responses/UnprocessableEntity" } } } },
    "/annotations/{id}": {
      "patch": { "tags": ["Annotations"], "summary": "Update a timeline annotation", "operationId": "updateAnnotation",
        "parameters": [ { "name": "id", "in": "path", "required": true, "type": "integer" }, { "name": "body", "in": "body", "required": true, "schema": { "type": "object", "required": ["project_id"], "properties": { "project_id": { "type": "integer" }, "title": { "type": "string" }, "description": { "type": "string" }, "annotation_date": { "type": "string", "format": "date" }, "color": { "type": "string" }, "annotation_category_id": { "type": "integer" } } } } ],
        "responses": { "200": { "description": "Updated" }, "403": { "$ref": "#/responses/Forbidden" }, "404": { "$ref": "#/responses/NotFound" }, "422": { "$ref": "#/responses/UnprocessableEntity" } } },
      "delete": { "tags": ["Annotations"], "summary": "Delete a timeline annotation", "operationId": "deleteAnnotation",
        "parameters": [ { "$ref": "#/parameters/ProjectId" }, { "name": "id", "in": "path", "required": true, "type": "integer" } ],
        "responses": { "200": { "description": "Deleted" }, "403": { "$ref": "#/responses/Forbidden" }, "404": { "$ref": "#/responses/NotFound" } } } },

    "/technical_geo_reports": { "post": { "tags": ["Technical GEO Reports"], "summary": "Run technical GEO analysis", "operationId": "createTechnicalGeoReports",
      "parameters": [ { "name": "body", "in": "body", "required": true, "schema": { "type": "object", "required": ["project_id", "url"], "properties": { "project_id": { "type": "integer" }, "url": { "type": "string" }, "country_code": { "type": "string" } } } } ],
      "responses": { "201": { "description": "Created" }, "403": { "$ref": "#/responses/InsufficientScope" }, "422": { "$ref": "#/responses/UnprocessableEntity" } } } },

    "/intelligence_tasks": {
      "get":  { "tags": ["GEO Writer"], "summary": "List GEO Writer tasks", "operationId": "listIntelligenceTasks", "parameters": [ { "$ref": "#/parameters/ProjectId" }, { "name": "task_type", "in": "query", "type": "string", "enum": ["brief", "create", "update", "pr_insights", "custom"] }, { "name": "status", "in": "query", "type": "string" }, { "$ref": "#/parameters/Page" }, { "$ref": "#/parameters/PerPage" } ], "responses": { "200": { "description": "Paginated tasks" } } },
      "post": { "tags": ["GEO Writer"], "summary": "Create a GEO Writer task", "operationId": "createIntelligenceTask",
        "parameters": [ { "name": "body", "in": "body", "required": true, "schema": { "type": "object", "required": ["project_id", "task_type"], "properties": { "project_id": { "type": "integer" }, "task_type": { "type": "string", "enum": ["brief", "create", "update", "pr_insights", "custom"] }, "prompt_id": { "type": "integer" }, "custom_topic": { "type": "string" }, "user_instructions": { "type": "string" }, "output_language_code": { "type": "string" }, "existing_content": { "type": "string" }, "existing_content_url": { "type": "string" } } } } ],
        "responses": { "201": { "description": "Created" }, "422": { "$ref": "#/responses/UnprocessableEntity" } } }
    },
    "/intelligence_tasks/{id}": { "get": { "tags": ["GEO Writer"], "summary": "Get a GEO Writer task", "operationId": "getIntelligenceTask", "parameters": [ { "$ref": "#/parameters/ProjectId" }, { "name": "id", "in": "path", "required": true, "type": "string", "description": "Numeric task ID or public_id string token" } ], "responses": { "200": { "description": "Task with result_data when completed" } } } },

    "/webhooks": {
      "get": {
        "tags": ["Webhooks"],
        "summary": "List webhook subscriptions",
        "operationId": "listWebhooks",
        "description": "Lists active webhook subscriptions for the account, optionally filtered by project. Requires the Scale plan or above.",
        "parameters": [
          {
            "name": "project_id",
            "in": "query",
            "required": false,
            "type": "integer",
            "description": "Optional project filter"
          },
          {
            "name": "page",
            "in": "query",
            "required": false,
            "type": "integer"
          },
          {
            "name": "per_page",
            "in": "query",
            "required": false,
            "type": "integer",
            "description": "Max 100"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "schema": {
              "type": "object",
              "properties": {
                "page": {
                  "type": "integer"
                },
                "per_page": {
                  "type": "integer"
                },
                "total": {
                  "type": "integer"
                },
                "data": {
                  "type": "array",
                  "items": {
                    "type": "object",
                    "properties": {
                      "id": {
                        "type": "integer"
                      },
                      "project_id": {
                        "type": "integer"
                      },
                      "event_type": {
                        "type": "string",
                        "enum": [
                          "mention.created",
                          "competitor_mention.created",
                          "citation.created",
                          "prompt_execution.completed",
                          "sentiment.negative_detected",
                          "recommendation.completed",
                          "intelligence_task.completed"
                        ]
                      },
                      "target_url": {
                        "type": "string"
                      },
                      "disabled": {
                        "type": "boolean"
                      },
                      "failure_count": {
                        "type": "integer"
                      },
                      "last_delivered_at": {
                        "type": "string",
                        "format": "date-time"
                      },
                      "created_at": {
                        "type": "string",
                        "format": "date-time"
                      }
                    }
                  }
                },
                "request_id": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "$ref": "#/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/responses/PlanRequired"
          }
        }
      },
      "post": {
        "tags": ["Webhooks"],
        "summary": "Create a webhook subscription",
        "operationId": "createWebhook",
        "description": "Subscribes a public HTTPS URL to a project event. LLM Pulse POSTs a JSON envelope (`event`, `occurred_at`, `project_id`, `subscription_id`, `data`) to the URL every time the event occurs, signed via the `X-LLMPulse-Signature` header (HMAC-SHA256 of the raw body computed with the subscription secret). Failed deliveries are retried 5 times with backoff; subscriptions auto-disable after 20 consecutive failed deliveries. Idempotent for the same project + event + URL. Requires a `read_write` scope API key and the Scale plan or above.",
        "responses": {
          "201": {
            "description": "Created. The signing secret is only returned by this endpoint.",
            "schema": {
              "type": "object",
              "properties": {
                "id": {
                  "type": "integer"
                },
                "project_id": {
                  "type": "integer"
                },
                "event_type": {
                  "type": "string",
                  "enum": [
                    "mention.created",
                    "competitor_mention.created",
                    "citation.created",
                    "prompt_execution.completed",
                    "sentiment.negative_detected",
                    "recommendation.completed",
                    "intelligence_task.completed"
                  ]
                },
                "target_url": {
                  "type": "string"
                },
                "disabled": {
                  "type": "boolean"
                },
                "failure_count": {
                  "type": "integer"
                },
                "last_delivered_at": {
                  "type": "string",
                  "format": "date-time"
                },
                "created_at": {
                  "type": "string",
                  "format": "date-time"
                },
                "secret": {
                  "type": "string",
                  "description": "HMAC signing secret (whsec_...). Only returned on create."
                }
              }
            }
          },
          "401": {
            "$ref": "#/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/responses/InsufficientScope"
          },
          "404": {
            "$ref": "#/responses/NotFound"
          },
          "422": {
            "$ref": "#/responses/UnprocessableEntity"
          }
        },
        "consumes": [
          "application/json"
        ],
        "parameters": [
          {
            "name": "body",
            "in": "body",
            "required": true,
            "schema": {
              "type": "object",
              "required": [
                "project_id",
                "event_type",
                "target_url"
              ],
              "properties": {
                "project_id": {
                  "type": "integer"
                },
                "event_type": {
                  "type": "string",
                  "enum": [
                    "mention.created",
                    "competitor_mention.created",
                    "citation.created",
                    "prompt_execution.completed",
                    "sentiment.negative_detected",
                    "recommendation.completed",
                    "intelligence_task.completed"
                  ]
                },
                "target_url": {
                  "type": "string",
                  "description": "Public HTTPS URL that will receive signed event payloads"
                }
              }
            }
          }
        ]
      }
    },
    "/webhooks/{id}": {
      "delete": {
        "tags": ["Webhooks"],
        "summary": "Delete a webhook subscription",
        "operationId": "deleteWebhook",
        "description": "Deletes a webhook subscription; the target URL stops receiving events immediately. Requires a `read_write` scope API key and the Scale plan or above.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "type": "integer"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "schema": {
              "type": "object",
              "properties": {
                "deleted": {
                  "type": "boolean"
                },
                "id": {
                  "type": "integer"
                },
                "request_id": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "$ref": "#/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/responses/InsufficientScope"
          },
          "404": {
            "$ref": "#/responses/NotFound"
          }
        }
      }
    },
    "/webhooks/sample/{event_type}": {
      "get": {
        "tags": ["Webhooks"],
        "summary": "Sample event payloads",
        "operationId": "sampleWebhookPayloads",
        "description": "Returns up to 3 example event payloads for the event type, built from the project's most recent real data (or a static sample when the project has no data). Used by integration editors such as the Zapier sample loader. Requires the Scale plan or above.",
        "parameters": [
          {
            "name": "event_type",
            "in": "path",
            "required": true,
            "type": "string",
            "enum": [
              "mention.created",
              "competitor_mention.created",
              "citation.created",
              "prompt_execution.completed",
              "sentiment.negative_detected",
              "recommendation.completed",
              "intelligence_task.completed"
            ]
          },
          {
            "name": "project_id",
            "in": "query",
            "required": true,
            "type": "integer"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "schema": {
              "type": "object",
              "properties": {
                "event_type": {
                  "type": "string"
                },
                "data": {
                  "type": "array",
                  "items": {
                    "type": "object",
                    "properties": {
                      "event": {
                        "type": "string"
                      },
                      "occurred_at": {
                        "type": "string",
                        "format": "date-time"
                      },
                      "project_id": {
                        "type": "integer"
                      },
                      "subscription_id": {
                        "type": "integer"
                      },
                      "data": {
                        "type": "object"
                      }
                    }
                  }
                },
                "request_id": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "$ref": "#/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/responses/PlanRequired"
          },
          "404": {
            "$ref": "#/responses/NotFound"
          },
          "422": {
            "$ref": "#/responses/UnprocessableEntity"
          }
        }
      }
    },
    "/mcp": {
      "post": { "tags": ["MCP"], "summary": "MCP JSON-RPC endpoint", "operationId": "handleMcpPost",
        "description": "Available on every plan and during eligible trials. Accepts OAuth 2.1 access tokens (recommended for interactive AI clients: discovery at /.well-known/oauth-authorization-server, DCR at /oauth/register) and Bearer-token API keys (Scale plan or above, headless integrations).",
        "parameters": [ { "name": "body", "in": "body", "required": true, "schema": { "type": "object", "properties": { "jsonrpc": { "type": "string", "enum": ["2.0"] }, "id": { "type": "string" }, "method": { "type": "string" }, "params": { "type": "object" } } } } ],
        "responses": { "200": { "description": "JSON-RPC response" }, "202": { "description": "Notification accepted; empty response body" } } },
      "get":  { "tags": ["MCP"], "summary": "MCP GET handshake", "operationId": "handleMcpGet", "responses": { "200": { "description": "JSON-RPC response" } } }
    },

    "/mcp/server-card": {
      "get": { "tags": ["MCP"], "summary": "MCP server card", "operationId": "getMcpServerCard",
        "description": "Public MCP Server Card describing this server: name, version, the streamable HTTP endpoint, the protocol versions it speaks and the Authorization header a client must send. Requires no authentication, because it is the document a client reads before it holds a credential. The card contains no credential itself; the Authorization entry is a template marked isSecret. Advertised in the Agentic Resource Discovery catalog at /.well-known/ai-catalog.json, and deliberately NOT served at /.well-known/mcp/server-card.json, a location the MCP specification rules out because a single server's card is application-level rather than site-wide metadata.",
        "security": [],
        "produces": ["application/mcp-server-card+json"],
        "responses": { "200": { "description": "MCP server card", "schema": { "type": "object" } }, "304": { "description": "Not modified (If-None-Match matched the ETag)" } } }
    }
  },
  "responses": {
    "Unauthorized":        { "description": "Authentication failed",   "schema": { "$ref": "#/definitions/Error" } },
    "NotFound":            { "description": "Resource not found",      "schema": { "$ref": "#/definitions/Error" } },
    "Forbidden":           { "description": "Access forbidden",        "schema": { "$ref": "#/definitions/Error" } },
    "PlanRequired":        { "description": "Plan upgrade required",   "schema": { "$ref": "#/definitions/Error" } },
    "InsufficientScope":   { "description": "API key lacks write permission", "schema": { "$ref": "#/definitions/Error" } },
    "UnprocessableEntity": { "description": "Invalid parameters",      "schema": { "$ref": "#/definitions/Error" } }
  },
  "definitions": {
    "Error": {
      "type": "object",
      "properties": {
        "error": { "type": "object", "properties": { "code": { "type": "string", "enum": ["ERR_MISSING_AUTH", "ERR_INVALID_API_KEY", "ERR_REVOKED_API_KEY", "ERR_INSUFFICIENT_SCOPE", "ERR_INSUFFICIENT_PERMISSION", "ERR_PLAN_REQUIRED", "ERR_ACCOUNT_INACTIVE", "ERR_DRAFT_NOT_FOUND", "ERR_DRAFT_STATE", "ERR_PROJECT_NOT_FOUND", "ERR_NOT_FOUND", "ERR_SEARCH_CONSOLE_NOT_CONNECTED", "ERR_AI_TRAFFIC_NOT_CONNECTED", "ERR_AGENT_TRAFFIC_NOT_CONNECTED", "ERR_INVALID_PARAM", "ERR_INVALID_RANGE", "ERR_LIMIT_REACHED", "ERR_QUOTA_EXCEEDED", "ERR_RATE_LIMITED"] }, "message": { "type": "string" }, "meta": { "type": "object" } } },
        "request_id": { "type": "string" }
      }
    },
    "Project": {
      "type": "object",
      "properties": {
        "id": { "type": "integer" },
        "name": { "type": "string" },
        "brand_name": { "type": "string", "description": "LLM-facing brand label, distinct from name." }
      }
    }
  }
}
