API Reference
Everything you need to integrate CitedSpy into your workflow. Manage brands, trigger runs, and pull AI visibility data via REST API.
Authentication
All API requests require an API key. Generate one in your dashboard under Settings > API Keys.
Include the key in the Authorization header:
curl https://app.citedspy.com/api/v1/brands \
-H "Authorization: Bearer cspy_your_api_key_here"API keys are prefixed with cspy_ for easy identification. Each key is scoped to a single workspace - all data returned is automatically filtered to that workspace.
Errors
CitedSpy uses standard HTTP status codes. All error responses follow this format:
{
"error": "Description of what went wrong"
}| Status | Meaning |
|---|---|
| 200 | Success |
| 201 | Created (resource was created successfully) |
| 400 | Bad Request (missing or invalid parameters) |
| 401 | Unauthorized (invalid or missing API key) |
| 403 | Forbidden (insufficient permissions) |
| 404 | Not Found (resource does not exist or is not in your workspace) |
| 429 | Rate Limit Exceeded (too many requests) |
| 500 | Internal Server Error |
Rate Limits
API requests are limited to 100 requests per minute per API key. Rate limit information is included in response headers:
| Header | Description |
|---|---|
| X-RateLimit-Limit | Maximum requests per window (100) |
| X-RateLimit-Remaining | Requests remaining in current window |
| X-RateLimit-Reset | Unix timestamp when the window resets |
When you exceed the limit, the API returns a 429 response with a message indicating when you can retry.
Pagination
List endpoints support pagination via limit and offset query parameters:
| Parameter | Type | Default | Description |
|---|---|---|---|
| limit | integer | 50 | Number of items to return (max 200) |
| offset | integer | 0 | Number of items to skip |
Paginated responses include a pagination object:
{
"data": [...],
"pagination": {
"limit": 50,
"offset": 0
}
}Brands
/api/v1/brandsList all brands in your workspace.
Response
{
"data": [
{
"id": "uuid",
"name": "My Brand",
"domain": "mybrand.com",
"category": "SaaS",
"description": "Project management tool",
"aliases": ["MyBrand", "MB"],
"owned_domains": ["mybrand.com", "mybrand.io"],
"logo_url": "https://assets.citedspy.com/brands/...",
"created_at": "2026-05-01T00:00:00.000Z",
"updated_at": "2026-05-10T12:00:00.000Z"
}
]
}/api/v1/brands/:idGet a single brand with its competitors and prompt count.
Path parameters
| Parameter | Type | Description |
|---|---|---|
| id | uuid | The brand ID |
Response
{
"data": {
"id": "uuid",
"name": "My Brand",
"domain": "mybrand.com",
"category": "SaaS",
"description": "Project management tool",
"aliases": ["MyBrand", "MB"],
"competitors": [
{ "id": "uuid", "name": "Competitor A", "domain": "competitor-a.com" }
],
"prompt_count": 12
}
}Prompts
/api/v1/promptsList prompts. Optionally filter by brand.
Query parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
| brand_id | uuid | No | Filter prompts by brand |
| status | string | No | Filter by status: active, paused, archived |
| limit | integer | No | Items per page (default 100, max 200) |
| offset | integer | No | Items to skip (default 0) |
Response
{
"data": [
{
"id": "uuid",
"brand_id": "uuid",
"text": "What is the best project management tool?",
"category": "comparison",
"status": "active",
"tags": ["productivity", "tools"],
"created_at": "2026-05-01T00:00:00.000Z"
}
],
"pagination": { "limit": 100, "offset": 0 }
}/api/v1/prompts/:idGet a single prompt with its run count.
Response
{
"data": {
"id": "uuid",
"brand_id": "uuid",
"text": "What is the best project management tool?",
"category": "comparison",
"status": "active",
"tags": ["productivity"],
"run_count": 45,
"created_at": "2026-05-01T00:00:00.000Z"
}
}/api/v1/promptsCreate a new tracking prompt.
Request body
| Field | Type | Required | Description |
|---|---|---|---|
| brand_id | uuid | Yes | Brand to attach this prompt to |
| text | string | Yes | The prompt text to send to AI engines |
| category | string | No | Category: comparison, recommendation, informational, troubleshooting |
| tags | string[] | No | Array of tags for organizing prompts |
Example
curl -X POST https://app.citedspy.com/api/v1/prompts \
-H "Authorization: Bearer cspy_your_key" \
-H "Content-Type: application/json" \
-d '{
"brand_id": "abc-123",
"text": "What are the top CRM tools for small business?",
"category": "comparison",
"tags": ["crm", "small-business"]
}'Response (201)
{
"data": {
"id": "new-uuid",
"brand_id": "abc-123",
"text": "What are the top CRM tools for small business?",
"category": "comparison",
"status": "active",
"tags": ["crm", "small-business"],
"created_at": "2026-05-17T10:00:00.000Z"
}
}/api/v1/prompts/:idUpdate an existing prompt.
Request body (all fields optional)
| Field | Type | Description |
|---|---|---|
| text | string | Updated prompt text |
| category | string | Updated category |
| status | string | Set to active, paused, or archived |
| tags | string[] | Updated tags array |
/api/v1/prompts/:idDelete a prompt and all its associated run data.
Response
{ "success": true }Runs
/api/v1/runsList prompt execution results.
Query parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
| prompt_id | uuid | No | Filter by prompt |
| engine | string | No | Filter by engine name (e.g. ChatGPT, Perplexity, Gemini, Claude, Copilot) |
| status | string | No | Filter by status: running, completed, failed |
| limit | integer | No | Items per page (default 50, max 200) |
| offset | integer | No | Items to skip |
Response
{
"data": [
{
"id": "uuid",
"prompt_id": "uuid",
"engine_id": "uuid",
"engine_name": "ChatGPT",
"status": "completed",
"scheduled_at": "2026-05-17T08:00:00.000Z",
"completed_at": "2026-05-17T08:00:03.200Z",
"raw_response_text": "Based on my research, the top project...",
"token_cost_usd": 0.0034
}
],
"pagination": { "limit": 50, "offset": 0 }
}/api/v1/runs/:idGet a single run with its citations and mentions.
Response
{
"data": {
"id": "uuid",
"prompt_id": "uuid",
"engine_id": "uuid",
"engine_name": "Perplexity",
"status": "completed",
"raw_response_text": "Here are the top tools...",
"token_cost_usd": 0.0021,
"citations": [
{
"id": "uuid",
"url": "https://mybrand.com/features",
"domain": "mybrand.com",
"position_in_response": 2,
"snippet": "MyBrand offers advanced analytics..."
}
],
"mentions": [
{
"id": "uuid",
"brand_or_competitor_id": "uuid",
"entity_type": "brand",
"sentiment": "positive",
"snippet": "MyBrand is highly recommended for...",
"position_in_response": 1
}
]
}
}/api/v1/runs/triggerTrigger a prompt run across AI engines. Returns results synchronously.
Request body
| Field | Type | Required | Description |
|---|---|---|---|
| prompt_id | uuid | Yes | The prompt to run |
| engines | string[] | No | Specific engines to run (default: all available). Values: ChatGPT, Perplexity, Gemini, Claude, Copilot |
Example
curl -X POST https://app.citedspy.com/api/v1/runs/trigger \
-H "Authorization: Bearer cspy_your_key" \
-H "Content-Type: application/json" \
-d '{
"prompt_id": "abc-123",
"engines": ["ChatGPT", "Perplexity"]
}'Response
{
"data": {
"runs": [
{ "run_id": "uuid", "engine": "ChatGPT", "status": "completed" },
{ "run_id": "uuid", "engine": "Perplexity", "status": "completed" }
],
"completed": 2,
"failed": 0,
"total": 2
}
}Competitors
/api/v1/competitorsList competitors for a specific brand.
Query parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
| brand_id | uuid | Yes | The brand to get competitors for |
Response
{
"data": [
{
"id": "uuid",
"brand_id": "uuid",
"name": "Competitor A",
"domain": "competitor-a.com",
"aliases": ["CompA", "Comp-A"],
"category": "SaaS",
"description": "A competing product",
"created_at": "2026-05-01T00:00:00.000Z"
}
]
}Dashboard
/api/v1/dashboard/:brandIdGet aggregated dashboard metrics for a brand.
Path parameters
| Parameter | Type | Description |
|---|---|---|
| brandId | uuid | The brand ID |
Query parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
| days | integer | 14 | Number of days for the analysis window |
Response
{
"data": {
"brand_id": "uuid",
"snapshot_date": "2026-05-17",
"computed_at": "2026-05-17T06:00:00.000Z",
"mention_rate": 72,
"mention_rate_delta": 5,
"avg_position": 2.3,
"avg_position_delta": -0.4,
"share_of_voice": 34,
"share_of_voice_delta": 2,
"prompts_tracked": 25,
"sentiment_score": 0.78,
"total_runs": 150,
"total_mentions": 108,
"engine_breakdown": [
{ "engine": "ChatGPT", "mention_rate": 80, "avg_position": 1.8 },
{ "engine": "Perplexity", "mention_rate": 65, "avg_position": 3.1 }
],
"competitor_stats": [
{ "name": "Competitor A", "mention_rate": 45, "share_of_voice": 22 }
],
"top_citations": [
{ "domain": "mybrand.com", "count": 34, "url": "https://mybrand.com/features" }
],
"trend_data": [
{ "date": "2026-05-10", "mention_rate": 68, "position": 2.5 },
{ "date": "2026-05-11", "mention_rate": 70, "position": 2.4 }
]
}
}Metrics explained
| Field | Description |
|---|---|
| mention_rate | Percentage of runs where your brand was mentioned (0-100) |
| avg_position | Average position of your brand mention in responses (1 = first mentioned) |
| share_of_voice | Your brand's mentions as % of total mentions (brand + competitors) |
| sentiment_score | Average sentiment score (-1 to 1, where 1 is most positive) |
| *_delta | Change compared to the previous period of equal length |
Citations
/api/v1/citationsList URLs cited by AI engines in their responses.
Query parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
| run_id | uuid | No | Filter by specific run |
| brand_id | uuid | No | Filter citations for a specific brand's prompts |
| limit | integer | No | Items per page (default 50, max 200) |
| offset | integer | No | Items to skip |
Response
{
"data": [
{
"id": "uuid",
"run_id": "uuid",
"url": "https://mybrand.com/blog/guide",
"domain": "mybrand.com",
"position_in_response": 1,
"snippet": "According to MyBrand's guide..."
}
],
"pagination": { "limit": 50, "offset": 0 }
}Mentions
/api/v1/mentionsList brand and competitor mentions detected in AI responses.
Query parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
| brand_id | uuid | No | Filter by brand |
| entity_type | string | No | Filter: brand or competitor |
| sentiment | string | No | Filter: positive, neutral, or negative |
| limit | integer | No | Items per page (default 50, max 200) |
| offset | integer | No | Items to skip |
Response
{
"data": [
{
"id": "uuid",
"run_id": "uuid",
"brand_or_competitor_id": "uuid",
"entity_type": "brand",
"sentiment": "positive",
"snippet": "MyBrand is one of the leading solutions for...",
"position_in_response": 2
}
],
"pagination": { "limit": 50, "offset": 0 }
}Sentiment values
| Value | Description |
|---|---|
| positive | Brand mentioned favorably (recommended, praised, highlighted as a top choice) |
| neutral | Brand mentioned factually without strong positive or negative framing |
| negative | Brand mentioned negatively (criticized, listed as inferior, warned against) |
Engines
/api/v1/enginesList AI engines and their availability status.
Response
{
"data": [
{ "id": "uuid", "name": "ChatGPT", "available": true },
{ "id": "uuid", "name": "Perplexity", "available": true },
{ "id": "uuid", "name": "Gemini", "available": true },
{ "id": "uuid", "name": "Claude", "available": true },
{ "id": "uuid", "name": "Copilot", "available": false }
]
}The available field indicates whether the engine is currently configured and ready to accept runs on your workspace.
Need help with the API?
Our team can help you build custom integrations and troubleshoot any issues.