{"openapi":"3.1.0","info":{"title":"Signal360 API","version":"1.0.0","description":"Signal360 Public API — query AEO/GEO analytics, channel metrics, manage webhooks, and integrate with external platforms.\n\n## Authentication\n\nAll endpoints require authentication via one of:\n- **API Key**: Pass your key in the `X-API-Key` header\n- **OAuth 2.0 Bearer Token**: Pass a valid access token in the `Authorization: Bearer <token>` header\n\n## Rate Limits\n\nRate limits depend on your API key tier:\n| Tier | Requests/min | Requests/day | Burst |\n|------|-------------|-------------|-------|\n| free | 60 | 1,000 | +10 |\n| standard | 300 | 10,000 | +50 |\n| professional | 600 | 50,000 | +100 |\n| enterprise | 1,200 | 200,000 | +200 |\n\nRate limit headers are returned on every response:\n- `X-RateLimit-Limit` — Maximum requests per window\n- `X-RateLimit-Remaining` — Remaining requests in current window\n- `X-RateLimit-Reset` — Seconds until window resets\n\n## Pagination\n\nAll list endpoints support pagination via query parameters:\n- `limit` (1-200, default 50)\n- `offset` (default 0)\n- `sort` — field name to sort by\n- `order` — `asc` or `desc` (default `desc`)\n\nPaginated responses include a `meta` object:\n```json\n{\n  \"data\": [...],\n  \"meta\": { \"total\": 100, \"limit\": 50, \"offset\": 0, \"hasMore\": true }\n}\n```\n\n## Errors\n\nAll errors follow a consistent format:\n```json\n{\n  \"error\": {\n    \"code\": \"VALIDATION_ERROR\",\n    \"message\": \"Human-readable message\",\n    \"details\": { ... }\n  }\n}\n```","contact":{"name":"Signal360 Support","email":"support@signal360.ai"},"license":{"name":"Proprietary"}},"servers":[{"url":"https://app.signal360.ai","description":"Production"},{"url":"http://localhost:5001","description":"Local development"}],"security":[{"apiKey":[]},{"bearerAuth":[]}],"components":{"securitySchemes":{"apiKey":{"type":"apiKey","in":"header","name":"X-API-Key","description":"API key obtained from the Signal360 dashboard"},"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"OAuth2 Access Token"}},"schemas":{"Error":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","example":"VALIDATION_ERROR"},"message":{"type":"string","example":"Request validation failed"},"details":{"type":"object","additionalProperties":true}},"required":["code","message"]}}},"PaginationMeta":{"type":"object","properties":{"total":{"type":"integer"},"limit":{"type":"integer"},"offset":{"type":"integer"},"hasMore":{"type":"boolean"}}}},"parameters":{"limit":{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":200,"default":50},"description":"Number of results per page"},"offset":{"name":"offset","in":"query","schema":{"type":"integer","minimum":0,"default":0},"description":"Number of results to skip"},"sort":{"name":"sort","in":"query","schema":{"type":"string"},"description":"Field name to sort by"},"order":{"name":"order","in":"query","schema":{"type":"string","enum":["asc","desc"],"default":"desc"},"description":"Sort order"}}},"paths":{"/api/v1/validate-key":{"post":{"tags":["Authentication"],"summary":"Validate API key","description":"Check if an API key is valid and return its associated scopes, tier, and client binding.","operationId":"validateKey","responses":{"200":{"description":"Key validation result","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"valid":{"type":"boolean"},"organizationId":{"type":"integer"},"scopes":{"type":"array","items":{"type":"string"}},"tier":{"type":"string"},"clientId":{"type":"integer","nullable":true}}}}}}}},"401":{"description":"Invalid or expired key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/channels":{"get":{"tags":["Channels"],"summary":"List connected channels","operationId":"listChannels","parameters":[{"name":"clientId","in":"query","required":true,"schema":{"type":"integer"},"description":"Client ID"}],"responses":{"200":{"description":"List of connected channels"},"401":{"description":"Authentication failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/metrics":{"get":{"tags":["Metrics"],"summary":"Query channel metrics","description":"Retrieve daily channel metrics with optional filtering by channel, brand, client, and date range.","operationId":"getMetrics","parameters":[{"$ref":"#/components/parameters/limit"},{"$ref":"#/components/parameters/offset"},{"name":"channel","in":"query","schema":{"type":"string"},"description":"Filter by channel name"},{"name":"brandId","in":"query","schema":{"type":"integer"},"description":"Filter by brand ID"},{"name":"clientId","in":"query","schema":{"type":"integer"},"description":"Filter by client ID"},{"name":"startDate","in":"query","schema":{"type":"string","format":"date"},"description":"Start date (YYYY-MM-DD)"},{"name":"endDate","in":"query","schema":{"type":"string","format":"date"},"description":"End date (YYYY-MM-DD)"}],"responses":{"200":{"description":"Paginated list of metrics"},"403":{"description":"Missing scope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/campaigns":{"get":{"tags":["Campaigns"],"summary":"Query campaigns","operationId":"getCampaigns","parameters":[{"$ref":"#/components/parameters/limit"},{"$ref":"#/components/parameters/offset"},{"name":"channel","in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":"Paginated list of campaigns"}}}},"/api/v1/content":{"get":{"tags":["Content"],"summary":"Query content","operationId":"getContent","parameters":[{"$ref":"#/components/parameters/limit"},{"$ref":"#/components/parameters/offset"},{"name":"channel","in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":"Paginated list of content"}}}},"/api/v1/audiences":{"get":{"tags":["Audiences"],"summary":"Query audiences","operationId":"getAudiences","parameters":[{"$ref":"#/components/parameters/limit"},{"$ref":"#/components/parameters/offset"},{"name":"channel","in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":"Paginated list of audiences"}}}},"/api/v1/usage":{"get":{"tags":["Usage"],"summary":"Get API usage statistics","operationId":"getUsageStats","parameters":[{"name":"days","in":"query","schema":{"type":"integer","default":30},"description":"Number of days to look back"}],"responses":{"200":{"description":"Usage statistics and endpoint breakdown"}}}},"/api/v1/usage/keys/{keyId}":{"get":{"tags":["Usage"],"summary":"Get usage for a specific API key","operationId":"getKeyUsage","parameters":[{"name":"keyId","in":"path","required":true,"schema":{"type":"integer"}},{"name":"days","in":"query","schema":{"type":"integer","default":30}}],"responses":{"200":{"description":"Daily usage counts for the key"}}}},"/api/v1/webhooks":{"get":{"tags":["Webhooks"],"summary":"List webhooks","operationId":"listWebhooks","parameters":[{"$ref":"#/components/parameters/limit"},{"$ref":"#/components/parameters/offset"}],"responses":{"200":{"description":"Paginated list of webhooks"}}},"post":{"tags":["Webhooks"],"summary":"Create a webhook","operationId":"createWebhook","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["url","events"],"properties":{"url":{"type":"string","format":"uri"},"events":{"type":"array","items":{"type":"string"},"minItems":1},"description":{"type":"string","maxLength":500},"isActive":{"type":"boolean","default":true},"headers":{"type":"object","additionalProperties":{"type":"string"}}}}}}},"responses":{"201":{"description":"Webhook created — includes signing secret (shown once)"}}}},"/api/v1/webhooks/events":{"get":{"tags":["Webhooks"],"summary":"List available webhook event types","operationId":"listWebhookEvents","responses":{"200":{"description":"Array of event type strings"}}}},"/api/v1/webhooks/{id}":{"get":{"tags":["Webhooks"],"summary":"Get webhook details","operationId":"getWebhook","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer"}}],"responses":{"200":{"description":"Webhook details"},"404":{"description":"Webhook not found"}}},"patch":{"tags":["Webhooks"],"summary":"Update a webhook","operationId":"updateWebhook","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer"}}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"url":{"type":"string","format":"uri"},"events":{"type":"array","items":{"type":"string"}},"description":{"type":"string"},"isActive":{"type":"boolean"}}}}}},"responses":{"200":{"description":"Updated webhook"}}},"delete":{"tags":["Webhooks"],"summary":"Delete a webhook","operationId":"deleteWebhook","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer"}}],"responses":{"200":{"description":"Webhook deleted"}}}},"/api/v1/webhooks/{id}/deliveries":{"get":{"tags":["Webhooks"],"summary":"Get delivery history for a webhook","operationId":"getWebhookDeliveries","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer"}},{"name":"limit","in":"query","schema":{"type":"integer","default":50}}],"responses":{"200":{"description":"List of delivery attempts"}}}},"/api/v1/webhooks/{id}/test":{"post":{"tags":["Webhooks"],"summary":"Send a test event to a webhook","operationId":"testWebhook","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer"}}],"responses":{"200":{"description":"Test event dispatched"}}}},"/api/oauth/token":{"post":{"tags":["OAuth"],"summary":"Exchange credentials for tokens","description":"Supports grant_type: authorization_code, client_credentials, refresh_token","operationId":"oauthToken","security":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["grant_type","client_id","client_secret"],"properties":{"grant_type":{"type":"string","enum":["authorization_code","client_credentials","refresh_token"]},"client_id":{"type":"string"},"client_secret":{"type":"string"},"code":{"type":"string","description":"Required for authorization_code grant"},"redirect_uri":{"type":"string","description":"Required for authorization_code grant"},"refresh_token":{"type":"string","description":"Required for refresh_token grant"},"scope":{"type":"string","description":"Space-separated scopes (client_credentials)"}}}}}},"responses":{"200":{"description":"Access token (and optionally refresh token)"},"400":{"description":"Invalid grant"},"401":{"description":"Invalid client"}}}},"/api/oauth/revoke":{"post":{"tags":["OAuth"],"summary":"Revoke a token","operationId":"oauthRevoke","security":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["token","client_id","client_secret"],"properties":{"token":{"type":"string"},"client_id":{"type":"string"},"client_secret":{"type":"string"}}}}}},"responses":{"200":{"description":"Token revoked"}}}},"/api/v1/brands":{"get":{"tags":["Brands"],"summary":"List brands","description":"Retrieve all brands in the organization, optionally filtered by client.","operationId":"listBrands","parameters":[{"name":"clientId","in":"query","schema":{"type":"integer"},"description":"Filter by client ID"}],"responses":{"200":{"description":"Array of brand objects"}}}},"/api/v1/brands/{id}":{"get":{"tags":["Brands"],"summary":"Get brand details","operationId":"getBrand","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer"}}],"responses":{"200":{"description":"Brand details"},"404":{"description":"Brand not found"}}}},"/api/v1/brands/{id}/competitors":{"get":{"tags":["Brands"],"summary":"Get brand competitors","operationId":"getBrandCompetitors","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer"}}],"responses":{"200":{"description":"Array of competitor brands"}}}},"/api/v1/analysis-runs":{"get":{"tags":["Analysis"],"summary":"List analysis runs","description":"Retrieve analysis runs with optional filtering by brand.","operationId":"listAnalysisRuns","parameters":[{"$ref":"#/components/parameters/limit"},{"$ref":"#/components/parameters/offset"},{"name":"brandId","in":"query","schema":{"type":"integer"},"description":"Filter by brand ID"}],"responses":{"200":{"description":"Paginated list of analysis runs"}}}},"/api/v1/analysis-runs/{id}":{"get":{"tags":["Analysis"],"summary":"Get analysis run details","operationId":"getAnalysisRun","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer"}}],"responses":{"200":{"description":"Analysis run details"},"404":{"description":"Not found"}}}},"/api/v1/analysis-runs/{id}/results":{"get":{"tags":["Analysis"],"summary":"Get results for an analysis run","description":"Returns all per-provider results for a specific analysis run.","operationId":"getAnalysisRunResults","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer"}},{"$ref":"#/components/parameters/limit"},{"$ref":"#/components/parameters/offset"}],"responses":{"200":{"description":"Paginated list of analysis results"}}}},"/api/v1/analysis-results":{"get":{"tags":["Analysis"],"summary":"Query analysis results","description":"Cross-run query of analysis results with filtering by brand, provider, and date range.","operationId":"queryAnalysisResults","parameters":[{"$ref":"#/components/parameters/limit"},{"$ref":"#/components/parameters/offset"},{"name":"brandId","in":"query","schema":{"type":"integer"},"description":"Filter by brand"},{"name":"provider","in":"query","schema":{"type":"string"},"description":"Filter by AI provider"},{"name":"startDate","in":"query","schema":{"type":"string","format":"date"}},{"name":"endDate","in":"query","schema":{"type":"string","format":"date"}}],"responses":{"200":{"description":"Paginated list of analysis results"}}}},"/api/v1/audit-requests":{"post":{"tags":["Analysis"],"summary":"Create an audit request","description":"Trigger a new AEO/GEO audit for a brand with specified queries and providers.","operationId":"createAuditRequest","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["brandId","queries"],"properties":{"brandId":{"type":"integer"},"queries":{"type":"array","items":{"type":"string"},"minItems":1},"providers":{"type":"array","items":{"type":"string"},"description":"AI providers to query (defaults to all)"}}}}}},"responses":{"201":{"description":"Audit request created"}}}},"/api/v1/visibility/sov":{"get":{"tags":["Visibility"],"summary":"Get share-of-voice data","description":"Retrieve SOV breakdown across AI providers for a brand over a date range.","operationId":"getShareOfVoice","parameters":[{"name":"brandId","in":"query","required":true,"schema":{"type":"integer"}},{"name":"startDate","in":"query","schema":{"type":"string","format":"date"}},{"name":"endDate","in":"query","schema":{"type":"string","format":"date"}},{"$ref":"#/components/parameters/limit"},{"$ref":"#/components/parameters/offset"}],"responses":{"200":{"description":"Paginated SOV entries by provider and query"}}}},"/api/v1/visibility/sov/latest":{"get":{"tags":["Visibility"],"summary":"Get latest SOV snapshot","description":"Returns the most recent SOV scores for a brand across all providers.","operationId":"getLatestSov","parameters":[{"name":"brandId","in":"query","required":true,"schema":{"type":"integer"}}],"responses":{"200":{"description":"Latest SOV data per provider"}}}},"/api/v1/visibility/trends":{"get":{"tags":["Visibility"],"summary":"Get visibility trends","description":"Track SOV and visibility score changes over time for a brand.","operationId":"getVisibilityTrends","parameters":[{"name":"brandId","in":"query","required":true,"schema":{"type":"integer"}},{"name":"days","in":"query","schema":{"type":"integer","default":30}}],"responses":{"200":{"description":"Time-series visibility trend data"}}}},"/api/v1/aeo/metrics":{"get":{"tags":["AEO"],"summary":"Get AEO metrics","description":"Retrieve Answer Engine Optimization metrics (mention rate, position, accuracy) for a brand.","operationId":"getAeoMetrics","parameters":[{"name":"brandId","in":"query","required":true,"schema":{"type":"integer"}},{"name":"startDate","in":"query","schema":{"type":"string","format":"date"}},{"name":"endDate","in":"query","schema":{"type":"string","format":"date"}}],"responses":{"200":{"description":"AEO metric summaries"}}}},"/api/v1/geo/metrics":{"get":{"tags":["GEO"],"summary":"Get GEO metrics","description":"Retrieve Generative Engine Optimization metrics and scores for a brand.","operationId":"getGeoMetrics","parameters":[{"name":"brandId","in":"query","required":true,"schema":{"type":"integer"}},{"name":"startDate","in":"query","schema":{"type":"string","format":"date"}},{"name":"endDate","in":"query","schema":{"type":"string","format":"date"}}],"responses":{"200":{"description":"GEO metric summaries"}}}},"/api/v1/geo/pages":{"get":{"tags":["GEO"],"summary":"Get GEO page scores","description":"Page-level GEO optimization scores and recommendations.","operationId":"getGeoPages","parameters":[{"name":"brandId","in":"query","required":true,"schema":{"type":"integer"}},{"$ref":"#/components/parameters/limit"},{"$ref":"#/components/parameters/offset"}],"responses":{"200":{"description":"Paginated list of GEO page scores"}}}},"/api/v1/geo/recommendations":{"get":{"tags":["GEO"],"summary":"Get GEO recommendations","description":"Actionable recommendations for improving GEO scores.","operationId":"getGeoRecommendations","parameters":[{"name":"brandId","in":"query","required":true,"schema":{"type":"integer"}}],"responses":{"200":{"description":"Array of GEO recommendations"}}}},"/api/v1/citations/sources":{"get":{"tags":["Citations"],"summary":"List citation sources","description":"Retrieve all citation sources referenced by AI providers for a brand.","operationId":"listCitationSources","parameters":[{"name":"brandId","in":"query","required":true,"schema":{"type":"integer"}},{"$ref":"#/components/parameters/limit"},{"$ref":"#/components/parameters/offset"}],"responses":{"200":{"description":"Paginated list of citation sources"}}}},"/api/v1/citations/sources/{id}":{"get":{"tags":["Citations"],"summary":"Get citation source details","operationId":"getCitationSource","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer"}}],"responses":{"200":{"description":"Citation source details"},"404":{"description":"Not found"}}}},"/api/v1/citations/trends":{"get":{"tags":["Citations"],"summary":"Get citation trends","description":"Track citation count and source changes over time.","operationId":"getCitationTrends","parameters":[{"name":"brandId","in":"query","required":true,"schema":{"type":"integer"}},{"name":"days","in":"query","schema":{"type":"integer","default":30}}],"responses":{"200":{"description":"Time-series citation trend data"}}}},"/api/v1/prompts/insights":{"get":{"tags":["Prompts"],"summary":"Get prompt insights","description":"AI-generated insights about prompt performance and brand representation.","operationId":"getPromptInsights","parameters":[{"name":"brandId","in":"query","required":true,"schema":{"type":"integer"}},{"name":"startDate","in":"query","schema":{"type":"string","format":"date"}},{"name":"endDate","in":"query","schema":{"type":"string","format":"date"}},{"$ref":"#/components/parameters/limit"},{"$ref":"#/components/parameters/offset"}],"responses":{"200":{"description":"Paginated list of prompt insights"}}}},"/api/v1/prompts/discoveries":{"get":{"tags":["Prompts"],"summary":"Get prompt discoveries","description":"New prompts discovered where the brand appears or should appear.","operationId":"getPromptDiscoveries","parameters":[{"name":"brandId","in":"query","required":true,"schema":{"type":"integer"}},{"name":"days","in":"query","schema":{"type":"integer","default":30}}],"responses":{"200":{"description":"Array of prompt discoveries"}}}},"/api/v1/prompts/gaps":{"get":{"tags":["Prompts"],"summary":"Get prompt gaps","description":"Prompts where the brand is missing or underrepresented compared to competitors.","operationId":"getPromptGaps","parameters":[{"name":"brandId","in":"query","required":true,"schema":{"type":"integer"}}],"responses":{"200":{"description":"Array of prompt gap analyses"}}}},"/api/v1/prompts/trends":{"get":{"tags":["Prompts"],"summary":"Get prompt trends","description":"Track prompt mention frequency and positioning over time.","operationId":"getPromptTrends","parameters":[{"name":"brandId","in":"query","required":true,"schema":{"type":"integer"}},{"name":"days","in":"query","schema":{"type":"integer","default":30}}],"responses":{"200":{"description":"Time-series prompt trend data"}}}},"/api/v1/sentiment/by-provider":{"get":{"tags":["Sentiment"],"summary":"Get sentiment by provider","description":"Sentiment analysis breakdown per AI provider for a brand.","operationId":"getSentimentByProvider","parameters":[{"name":"brandId","in":"query","required":true,"schema":{"type":"integer"}},{"name":"startDate","in":"query","schema":{"type":"string","format":"date"}},{"name":"endDate","in":"query","schema":{"type":"string","format":"date"}}],"responses":{"200":{"description":"Sentiment scores per provider"}}}},"/api/v1/sentiment/summary":{"get":{"tags":["Sentiment"],"summary":"Get sentiment summary","description":"Aggregate sentiment summary across all providers.","operationId":"getSentimentSummary","parameters":[{"name":"brandId","in":"query","required":true,"schema":{"type":"integer"}},{"name":"startDate","in":"query","schema":{"type":"string","format":"date"}},{"name":"endDate","in":"query","schema":{"type":"string","format":"date"}}],"responses":{"200":{"description":"Aggregated sentiment summary"}}}},"/api/v1/sentiment/trends":{"get":{"tags":["Sentiment"],"summary":"Get sentiment trends","description":"Track sentiment changes over time across providers.","operationId":"getSentimentTrends","parameters":[{"name":"brandId","in":"query","required":true,"schema":{"type":"integer"}},{"name":"startDate","in":"query","schema":{"type":"string","format":"date"}},{"name":"endDate","in":"query","schema":{"type":"string","format":"date"}}],"responses":{"200":{"description":"Time-series sentiment data"}}}},"/api/v1/changes":{"get":{"tags":["Changes"],"summary":"List detected changes","description":"Query AI response changes detected between analysis runs.","operationId":"listChanges","parameters":[{"name":"brandId","in":"query","required":true,"schema":{"type":"integer"}},{"name":"changeType","in":"query","schema":{"type":"string"},"description":"Filter by change type"},{"name":"startDate","in":"query","schema":{"type":"string","format":"date"}},{"name":"endDate","in":"query","schema":{"type":"string","format":"date"}},{"$ref":"#/components/parameters/limit"},{"$ref":"#/components/parameters/offset"}],"responses":{"200":{"description":"Paginated list of detected changes"}}}},"/api/v1/changes/summary":{"get":{"tags":["Changes"],"summary":"Get changes summary","description":"Aggregated summary of recent changes by type and severity.","operationId":"getChangesSummary","parameters":[{"name":"brandId","in":"query","required":true,"schema":{"type":"integer"}},{"name":"days","in":"query","schema":{"type":"integer","default":30}}],"responses":{"200":{"description":"Changes summary with counts by type"}}}},"/api/v1/agent-analytics/overview":{"get":{"tags":["Agent Analytics"],"summary":"Get agent analytics overview","description":"Summary metrics for AI bot crawling activity: total visits, verified visits, unique bots, and pages crawled.","operationId":"getAgentAnalyticsOverview","parameters":[{"name":"days","in":"query","schema":{"type":"integer","default":30},"description":"Lookback period in days"}],"responses":{"200":{"description":"Overview metrics object"}}}},"/api/v1/agent-analytics/visits":{"get":{"tags":["Agent Analytics"],"summary":"Query bot visits","description":"Paginated list of individual AI bot visits with filtering.","operationId":"getAgentAnalyticsVisits","parameters":[{"name":"days","in":"query","schema":{"type":"integer","default":30}},{"name":"botName","in":"query","schema":{"type":"string"},"description":"Filter by bot name"},{"name":"url","in":"query","schema":{"type":"string"},"description":"Filter by URL pattern"},{"$ref":"#/components/parameters/limit"},{"$ref":"#/components/parameters/offset"}],"responses":{"200":{"description":"Paginated list of bot visits"}}}},"/api/v1/agent-analytics/bots":{"get":{"tags":["Agent Analytics"],"summary":"Get bot breakdown","description":"Aggregated visit counts per AI bot with verification status.","operationId":"getAgentAnalyticsBots","parameters":[{"name":"days","in":"query","schema":{"type":"integer","default":30}}],"responses":{"200":{"description":"Array of bot activity summaries"}}}},"/api/v1/agent-analytics/pages":{"get":{"tags":["Agent Analytics"],"summary":"Get page crawl heatmap","description":"Most-crawled pages with per-bot visit breakdown.","operationId":"getAgentAnalyticsPages","parameters":[{"name":"days","in":"query","schema":{"type":"integer","default":30}}],"responses":{"200":{"description":"Array of page crawl entries"}}}},"/api/v1/agent-analytics/trends":{"get":{"tags":["Agent Analytics"],"summary":"Get bot activity trends","description":"Daily bot visit counts over time for trend analysis.","operationId":"getAgentAnalyticsTrends","parameters":[{"name":"days","in":"query","schema":{"type":"integer","default":30}}],"responses":{"200":{"description":"Time-series bot visit data"}}}},"/api/v1/brand-index/latest":{"get":{"tags":["Brand Index"],"summary":"Get latest brand index score","description":"Composite AI visibility index score combining SOV, sentiment, citations, and GEO metrics.","operationId":"getBrandIndexLatest","parameters":[{"name":"brandId","in":"query","required":true,"schema":{"type":"integer"}}],"responses":{"200":{"description":"Latest brand index score and component breakdown"}}}},"/api/v1/opportunities":{"get":{"tags":["Opportunities"],"summary":"List opportunities","description":"List the canonical opportunities (issues / actions) detected for the API key's organization. Filter by brand, type, severity, status. Defaults to non-terminal status; pass `includeTerminal=true` to include resolved/dismissed.","operationId":"listOpportunities","parameters":[{"name":"brandId","in":"query","schema":{"type":"integer"},"description":"Filter to a single brand"},{"name":"type","in":"query","schema":{"type":"string"},"description":"Comma-separated: misinformation, competitor_gap, missing_citation, sentiment_drop, stability_alert, sov_drop, dropped_from_top3, readiness_gap, schema_gap, seo_task, crawl_block, hallucination_cluster"},{"name":"status","in":"query","schema":{"type":"string"},"description":"Comma-separated lifecycle states"},{"name":"severity","in":"query","schema":{"type":"string"},"description":"Comma-separated: low, medium, high, critical"},{"name":"includeTerminal","in":"query","schema":{"type":"boolean"}},{"name":"limit","in":"query","schema":{"type":"integer","default":50,"maximum":200}},{"name":"offset","in":"query","schema":{"type":"integer","default":0}}],"responses":{"200":{"description":"Paginated list of opportunities"},"401":{"description":"Authentication failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"ApiKeyAuth":["read:opportunities"]}]}},"/api/v1/opportunities/{id}":{"get":{"tags":["Opportunities"],"summary":"Get opportunity by id","operationId":"getOpportunity","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer"}}],"responses":{"200":{"description":"Opportunity detail"},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"ApiKeyAuth":["read:opportunities"]}]}},"/api/v1/opportunities/{id}/transition":{"post":{"tags":["Opportunities"],"summary":"Apply state transition","description":"Transition an opportunity to a new lifecycle state. Validated against the state machine; invalid moves return 400.","operationId":"transitionOpportunity","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["toStatus"],"properties":{"toStatus":{"type":"string","enum":["detected","triaged","assigned","in_progress","fix_deployed","verifying","resolved","regressed","dismissed"]},"reason":{"type":"string"}}}}}},"responses":{"200":{"description":"Transitioned opportunity"},"400":{"description":"Invalid transition","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"ApiKeyAuth":["write:opportunities"]}]}},"/api/v1/opportunities/_summary/kpis":{"get":{"tags":["Opportunities"],"summary":"Aggregate KPIs","description":"Counts of opportunities by status and severity, plus current SLA breach total.","operationId":"getOpportunityKpis","parameters":[{"name":"brandId","in":"query","schema":{"type":"integer"}}],"responses":{"200":{"description":"Aggregate KPIs"}},"security":[{"ApiKeyAuth":["read:opportunities"]}]}},"/api/v1/outcomes/_summary":{"get":{"tags":["Outcomes"],"summary":"Outcome summary","description":"Verified business impact of resolved opportunities — citation rate, AI traffic, conversions, revenue. The CMO-slide endpoint.","operationId":"getOutcomesSummary","parameters":[{"name":"brandId","in":"query","schema":{"type":"integer"}},{"name":"sinceDays","in":"query","schema":{"type":"integer","default":90,"maximum":365}}],"responses":{"200":{"description":"Outcome rows for resolved opportunities in the window"}},"security":[{"ApiKeyAuth":["read:outcomes"]}]}},"/api/v1/citation-sources/top":{"get":{"tags":["Citation Sources"],"summary":"Top citation source domains","description":"Domains that drive what AI engines say about the brand, ranked by consensus score (citation count × provider coverage × recency).","operationId":"getTopCitationSources","parameters":[{"name":"brandId","in":"query","required":true,"schema":{"type":"integer"}},{"name":"range","in":"query","schema":{"type":"integer","default":30,"description":"Days lookback"}},{"name":"limit","in":"query","schema":{"type":"integer","default":50,"maximum":200}}],"responses":{"200":{"description":"Top domains with consensus score and provider breakdown"}},"security":[{"ApiKeyAuth":["read:citation-sources"]}]}},"/api/v1/citation-sources/absences":{"get":{"tags":["Citation Sources"],"summary":"High-influence absence domains","description":"Domains where competitors are cited but the brand is not, ranked by consensus score × competitor density. The PR pitch list.","operationId":"getCitationAbsences","parameters":[{"name":"brandId","in":"query","required":true,"schema":{"type":"integer"}},{"name":"range","in":"query","schema":{"type":"integer","default":30}},{"name":"minScore","in":"query","schema":{"type":"integer","default":50,"description":"Drop domains below this consensus score"}},{"name":"limit","in":"query","schema":{"type":"integer","default":50,"maximum":200}}],"responses":{"200":{"description":"Absence domains"}},"security":[{"ApiKeyAuth":["read:citation-sources"]}]}},"/api/v1/agent-analytics/bot-visits":{"get":{"tags":["Agent Analytics"],"summary":"AI bot crawl activity","description":"Per-request log of AI bots crawling the customer's site (GPTBot, ClaudeBot, PerplexityBot, etc.). Sourced from CDN log ingestion or Node middleware.","operationId":"getBotVisits","parameters":[{"name":"botName","in":"query","schema":{"type":"string"},"description":"Filter by bot name"},{"name":"sinceDays","in":"query","schema":{"type":"integer","default":7,"maximum":90}},{"name":"limit","in":"query","schema":{"type":"integer","default":100,"maximum":500}},{"name":"offset","in":"query","schema":{"type":"integer","default":0}}],"responses":{"200":{"description":"Bot visit rows"}},"security":[{"ApiKeyAuth":["read:agent-analytics"]}]}}},"tags":[{"name":"Authentication","description":"API key and token validation"},{"name":"Brands","description":"Brand management and competitor tracking"},{"name":"Analysis","description":"Analysis runs, results, and audit requests"},{"name":"Visibility","description":"Share-of-voice and visibility trends"},{"name":"AEO","description":"Answer Engine Optimization metrics"},{"name":"GEO","description":"Generative Engine Optimization metrics and recommendations"},{"name":"Citations","description":"Citation source tracking and trends"},{"name":"Prompts","description":"Prompt insights, discoveries, gaps, and trends"},{"name":"Sentiment","description":"Sentiment analysis across AI providers"},{"name":"Changes","description":"AI response change detection"},{"name":"Agent Analytics","description":"AI bot crawl activity from server logs"},{"name":"Brand Index","description":"Composite AI visibility index"},{"name":"Channels","description":"Connected channel information"},{"name":"Metrics","description":"Channel performance metrics"},{"name":"Campaigns","description":"Campaign data"},{"name":"Content","description":"Content analytics"},{"name":"Audiences","description":"Audience data"},{"name":"Usage","description":"API usage analytics"},{"name":"Webhooks","description":"Webhook subscriptions and delivery management"},{"name":"OAuth","description":"OAuth 2.0 authorization and token management"},{"name":"Opportunities","description":"Canonical issue queue with state machine, SLA, ticketing, verification, and outcome attribution"},{"name":"Outcomes","description":"Verified business impact of resolved opportunities"},{"name":"Citation Sources","description":"Domains driving AI citations about the brand, with absence detection"}]}