{"openapi":"3.0.3","info":{"title":"NexGeo.ai API","version":"1.0.0","description":"The NexGeo.ai API lets you programmatically access your AI visibility data, trigger scans, retrieve analytics, and manage recommendations.","contact":{"name":"NexGeo.ai Support","url":"https://nexgeo.ai"}},"servers":[{"url":"/api/v1","description":"v1 API (relative)"}],"security":[{"ApiKeyHeader":[]},{"BearerAuth":[]}],"paths":{"/topics":{"get":{"operationId":"listTopics","summary":"List topics","description":"Returns a paginated list of topics with their latest visibility scores.","tags":["Topics"],"parameters":[{"$ref":"#/components/parameters/Page"},{"$ref":"#/components/parameters/Limit"},{"name":"status","in":"query","description":"Filter by topic status.","schema":{"type":"string","enum":["active","inactive","all"],"default":"active"}}],"responses":{"200":{"description":"Paginated list of topics.","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/TopicSummary"}},"pagination":{"$ref":"#/components/schemas/Pagination"}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/topics/{id}":{"get":{"operationId":"getTopic","summary":"Get topic details","description":"Returns a single topic with full visibility scores and the latest scan results.","tags":["Topics"],"parameters":[{"$ref":"#/components/parameters/TopicId"}],"responses":{"200":{"description":"Topic details with latest scan results.","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/TopicDetail"}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/topics/{id}/history":{"get":{"operationId":"getTopicHistory","summary":"Get topic score history","description":"Returns visibility score history for a topic over time, grouped by scan.","tags":["Topics"],"parameters":[{"$ref":"#/components/parameters/TopicId"},{"name":"days","in":"query","description":"Number of days to look back (max 90).","schema":{"type":"integer","default":30,"minimum":1,"maximum":90}}],"responses":{"200":{"description":"Score history data points.","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/TopicHistory"}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/scans":{"get":{"operationId":"listScans","summary":"List scans","description":"Returns a list of scans for the brand, ordered by creation date (newest first).","tags":["Scans"],"parameters":[{"name":"limit","in":"query","description":"Number of scans to return (max 50).","schema":{"type":"integer","default":20,"minimum":1,"maximum":50}},{"name":"status","in":"query","description":"Filter by scan status.","schema":{"type":"string","enum":["pending","running","completed","failed"]}}],"responses":{"200":{"description":"List of scans.","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Scan"}}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"}}},"post":{"operationId":"triggerScan","summary":"Trigger a new scan","description":"Queues a new visibility scan. The scan runs asynchronously — use the returned scan ID to poll for results. Requires the `write` scope.","tags":["Scans"],"requestBody":{"description":"Optional body. If no engines are specified, the brand's configured engines are used.","required":false,"content":{"application/json":{"schema":{"type":"object","properties":{"engines":{"type":"array","items":{"type":"string"},"description":"AI engines to scan (e.g. \"google_ai\", \"chatgpt\", \"perplexity\"). Defaults to the brand's configured engines.","example":["google_ai","chatgpt","perplexity"]}}}}}},"responses":{"201":{"description":"Scan queued successfully.","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","format":"uuid","description":"The new scan ID."},"status":{"type":"string","example":"pending"},"created_at":{"type":"string","format":"date-time"}}},"message":{"type":"string","example":"Scan queued successfully"}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"409":{"description":"A scan is already in progress.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","example":"A scan is already in progress"},"active_scan_id":{"type":"string","format":"uuid"}}}}}},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/scans/{id}":{"get":{"operationId":"getScan","summary":"Get scan details with results","description":"Returns scan metadata and, if the scan has started or completed, the individual result rows.","tags":["Scans"],"parameters":[{"name":"id","in":"path","required":true,"description":"Scan UUID.","schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Scan details with results.","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/ScanDetail"}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/analytics":{"get":{"operationId":"getAnalytics","summary":"Get analytics data","description":"Returns analytics data — either trend predictions or engine comparison stats.","tags":["Analytics"],"parameters":[{"name":"type","in":"query","required":true,"description":"The type of analytics to retrieve.","schema":{"type":"string","enum":["trends","engines"]}},{"name":"scan_id","in":"query","description":"Optional scan ID to scope engine comparison data to a specific scan (only used when type=engines).","schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Analytics data. Shape varies by type parameter.","content":{"application/json":{"schema":{"oneOf":[{"type":"object","title":"Trends response","properties":{"data":{"$ref":"#/components/schemas/TrendsAnalytics"}}},{"type":"object","title":"Engines response","properties":{"data":{"$ref":"#/components/schemas/EnginesAnalytics"}}}]}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/recommendations":{"get":{"operationId":"listRecommendations","summary":"List recommendations","description":"Returns a paginated list of AI-generated recommendations for improving visibility.","tags":["Recommendations"],"parameters":[{"$ref":"#/components/parameters/Page"},{"$ref":"#/components/parameters/Limit"},{"name":"status","in":"query","description":"Filter by recommendation status.","schema":{"type":"string","enum":["pending","completed","dismissed","all"],"default":"all"}},{"name":"stage","in":"query","description":"Filter by funnel stage.","schema":{"type":"string","enum":["awareness","evaluation","conversion"]}},{"name":"topic_id","in":"query","description":"Filter recommendations for a specific topic.","schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Paginated list of recommendations.","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Recommendation"}},"pagination":{"$ref":"#/components/schemas/Pagination"}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"}}}}},"components":{"securitySchemes":{"ApiKeyHeader":{"type":"apiKey","in":"header","name":"X-API-Key","description":"API key generated from the Developers page. Prefix: `apin_`."},"BearerAuth":{"type":"http","scheme":"bearer","description":"Pass your API key as a Bearer token in the Authorization header."}},"parameters":{"Page":{"name":"page","in":"query","description":"Page number (1-indexed).","schema":{"type":"integer","default":1,"minimum":1}},"Limit":{"name":"limit","in":"query","description":"Items per page (max 100).","schema":{"type":"integer","default":50,"minimum":1,"maximum":100}},"TopicId":{"name":"id","in":"path","required":true,"description":"Topic UUID.","schema":{"type":"string","format":"uuid"}}},"schemas":{"Pagination":{"type":"object","properties":{"page":{"type":"integer","example":1},"limit":{"type":"integer","example":50},"total":{"type":"integer","description":"Total number of matching records.","example":25},"total_pages":{"type":"integer","example":1}}},"Error":{"type":"object","required":["error"],"properties":{"error":{"oneOf":[{"type":"string"},{"type":"object","additionalProperties":true}],"description":"Human-readable error message or structured error object."}}},"TopicSummary":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string","example":"Nike Air Max 90"},"brand":{"type":"string","nullable":true},"category":{"type":"string","nullable":true},"price":{"type":"number","nullable":true,"example":129.99},"currency":{"type":"string","nullable":true,"example":"USD"},"url":{"type":"string","format":"uri","nullable":true},"status":{"type":"string","enum":["active","inactive"]},"visibility_score_overall":{"type":"number","nullable":true,"example":72.5},"visibility_score_awareness":{"type":"number","nullable":true},"visibility_score_evaluation":{"type":"number","nullable":true},"visibility_score_conversion":{"type":"number","nullable":true},"last_scanned_at":{"type":"string","format":"date-time","nullable":true},"created_at":{"type":"string","format":"date-time"}}},"TopicDetail":{"allOf":[{"$ref":"#/components/schemas/TopicSummary"},{"type":"object","properties":{"description":{"type":"string","nullable":true},"image_url":{"type":"string","format":"uri","nullable":true},"updated_at":{"type":"string","format":"date-time"},"latest_scan_results":{"type":"array","items":{"$ref":"#/components/schemas/ScanResultRow"}}}}]},"TopicHistory":{"type":"object","properties":{"topic_id":{"type":"string","format":"uuid"},"topic_name":{"type":"string"},"days":{"type":"integer"},"data_points":{"type":"array","items":{"$ref":"#/components/schemas/HistoryDataPoint"}}}},"HistoryDataPoint":{"type":"object","properties":{"scan_id":{"type":"string","format":"uuid"},"scanned_at":{"type":"string","format":"date-time"},"overall_score":{"type":"number","nullable":true},"stage_scores":{"type":"object","additionalProperties":{"type":"number"},"description":"Map of funnel stage to average score (e.g. { \"awareness\": 75.2, \"evaluation\": 68.0 })."},"total_queries":{"type":"integer"},"mention_rate":{"type":"number","description":"Fraction of queries where the topic was mentioned (0-1)."}}},"Scan":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"status":{"type":"string","enum":["pending","running","completed","failed"]},"total_queries":{"type":"integer","nullable":true},"completed_queries":{"type":"integer","nullable":true},"failed_queries":{"type":"integer","nullable":true},"started_at":{"type":"string","format":"date-time","nullable":true},"completed_at":{"type":"string","format":"date-time","nullable":true},"created_at":{"type":"string","format":"date-time"},"metadata":{"type":"object","nullable":true,"description":"Scan metadata including engines used and trigger source."}}},"ScanDetail":{"allOf":[{"$ref":"#/components/schemas/Scan"},{"type":"object","properties":{"error":{"type":"string","nullable":true,"description":"Error message if the scan failed."},"results":{"type":"array","items":{"$ref":"#/components/schemas/ScanResultRow"},"description":"Scan result rows. Populated when the scan status is \"running\" or \"completed\"."}}}]},"ScanResultRow":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"topic_id":{"type":"string","format":"uuid"},"engine":{"type":"string","description":"AI engine identifier (e.g. google_ai, chatgpt, perplexity)."},"funnel_stage":{"type":"string","enum":["awareness","evaluation","conversion"]},"topic_mentioned":{"type":"boolean"},"mention_position":{"type":"integer","nullable":true,"description":"Position in the AI response where the topic was mentioned."},"sentiment":{"type":"string","nullable":true,"enum":["positive","neutral","negative"]},"score":{"type":"number","nullable":true},"action_recommendation":{"type":"boolean","nullable":true},"sources_cited":{"type":"array","nullable":true,"items":{"type":"string"}},"competitors_mentioned":{"type":"array","nullable":true,"items":{"type":"string"}},"created_at":{"type":"string","format":"date-time"}}},"TrendsAnalytics":{"type":"object","description":"Trend predictions for the brand and its topics.","properties":{"brand_prediction":{"type":"object","properties":{"trajectory":{"type":"string","enum":["improving","stable","declining"]},"confidence":{"type":"string","enum":["high","medium","low"]},"current_score":{"type":"number"},"predicted_2w":{"type":"number"},"predicted_4w":{"type":"number"}}},"topic_predictions":{"type":"array","items":{"type":"object","properties":{"topic_id":{"type":"string","format":"uuid"},"topic_name":{"type":"string"},"trajectory":{"type":"string","enum":["improving","stable","declining"]},"confidence":{"type":"string","enum":["high","medium","low"]},"current_score":{"type":"number"},"predicted_2w":{"type":"number"}}}}}},"EnginesAnalytics":{"type":"object","description":"Cross-engine comparison data.","properties":{"engine_stats":{"type":"object","additionalProperties":{"type":"object","properties":{"avg_score":{"type":"number"},"mention_rate":{"type":"number"},"avg_position":{"type":"number"},"sentiment":{"type":"object","properties":{"positive":{"type":"number"},"neutral":{"type":"number"},"negative":{"type":"number"}}},"avg_citations":{"type":"number"},"recommendation_rate":{"type":"number"}}},"description":"Map of engine ID to aggregated statistics."},"correlation_matrix":{"type":"object","additionalProperties":{"type":"object","additionalProperties":{"type":"number"}},"description":"Pairwise correlation coefficients between engines."}}},"Recommendation":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"topic_id":{"type":"string","format":"uuid","nullable":true},"scan_id":{"type":"string","format":"uuid","nullable":true},"funnel_stage":{"type":"string","enum":["awareness","evaluation","conversion"],"nullable":true},"type":{"type":"string","description":"Recommendation category/type."},"title":{"type":"string"},"description":{"type":"string"},"priority":{"type":"string","enum":["high","medium","low"],"nullable":true},"status":{"type":"string","enum":["pending","completed","dismissed"]},"impact_estimate":{"type":"string","nullable":true,"description":"Estimated impact if the recommendation is applied."},"evidence":{"type":"object","nullable":true,"description":"Supporting data that informed the recommendation."},"applied_at":{"type":"string","format":"date-time","nullable":true},"score_before":{"type":"number","nullable":true},"score_after":{"type":"number","nullable":true},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"}}}},"responses":{"Unauthorized":{"description":"Missing or invalid API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":"Missing API key. Provide via X-API-Key header."}}}},"Forbidden":{"description":"Insufficient scope or plan limit reached.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":"Insufficient scope. Requires \"write\" permission."}}}},"BadRequest":{"description":"Invalid request parameters.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":"Invalid type. Supported: trends, engines"}}}},"NotFound":{"description":"Resource not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":"Topic not found"}}}},"InternalError":{"description":"Internal server error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":"Internal server error"}}}},"RateLimited":{"description":"Rate limit exceeded. Default: 60 requests/minute for reads, 20 requests/minute for writes.","headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per window.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Remaining requests in current window.","schema":{"type":"integer","example":0}},"X-RateLimit-Reset":{"description":"Unix timestamp (seconds) when the window resets.","schema":{"type":"integer"}},"Retry-After":{"description":"Seconds until the rate limit resets.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":"Rate limit exceeded. Please try again later."}}}}}},"tags":[{"name":"Topics","description":"Retrieve your monitored topics and their visibility scores."},{"name":"Scans","description":"List scan history, trigger new scans, and retrieve scan results."},{"name":"Analytics","description":"Access trend predictions and cross-engine analytics data."},{"name":"Recommendations","description":"AI-generated recommendations for improving visibility."}]}