Developer Docs

API Reference

Everything you need to integrate CitedSpy into your workflow. Manage brands, trigger runs, and pull AI visibility data via REST API.

Base URL: https://app.citedspy.com/api/v1Rate limit: 100 req/min

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.

API keys are hashed with SHA-256 before storage. The plaintext key is shown only once at creation. If you lose it, generate a new one.

Errors

CitedSpy uses standard HTTP status codes. All error responses follow this format:

{
  "error": "Description of what went wrong"
}
StatusMeaning
200Success
201Created (resource was created successfully)
400Bad Request (missing or invalid parameters)
401Unauthorized (invalid or missing API key)
403Forbidden (insufficient permissions)
404Not Found (resource does not exist or is not in your workspace)
429Rate Limit Exceeded (too many requests)
500Internal Server Error

Rate Limits

API requests are limited to 100 requests per minute per API key. Rate limit information is included in response headers:

HeaderDescription
X-RateLimit-LimitMaximum requests per window (100)
X-RateLimit-RemainingRequests remaining in current window
X-RateLimit-ResetUnix 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:

ParameterTypeDefaultDescription
limitinteger50Number of items to return (max 200)
offsetinteger0Number of items to skip

Paginated responses include a pagination object:

{
  "data": [...],
  "pagination": {
    "limit": 50,
    "offset": 0
  }
}

Brands

GET/api/v1/brands

List 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"
    }
  ]
}

GET/api/v1/brands/:id

Get a single brand with its competitors and prompt count.

Path parameters

ParameterTypeDescription
iduuidThe 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

GET/api/v1/prompts

List prompts. Optionally filter by brand.

Query parameters

ParameterTypeRequiredDescription
brand_iduuidNoFilter prompts by brand
statusstringNoFilter by status: active, paused, archived
limitintegerNoItems per page (default 100, max 200)
offsetintegerNoItems 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 }
}

GET/api/v1/prompts/:id

Get 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"
  }
}

POST/api/v1/prompts

Create a new tracking prompt.

Request body

FieldTypeRequiredDescription
brand_iduuidYesBrand to attach this prompt to
textstringYesThe prompt text to send to AI engines
categorystringNoCategory: comparison, recommendation, informational, troubleshooting
tagsstring[]NoArray 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"
  }
}

PATCH/api/v1/prompts/:id

Update an existing prompt.

Request body (all fields optional)

FieldTypeDescription
textstringUpdated prompt text
categorystringUpdated category
statusstringSet to active, paused, or archived
tagsstring[]Updated tags array

DELETE/api/v1/prompts/:id

Delete a prompt and all its associated run data.

Response

{ "success": true }

Runs

GET/api/v1/runs

List prompt execution results.

Query parameters

ParameterTypeRequiredDescription
prompt_iduuidNoFilter by prompt
enginestringNoFilter by engine name (e.g. ChatGPT, Perplexity, Gemini, Claude, Copilot)
statusstringNoFilter by status: running, completed, failed
limitintegerNoItems per page (default 50, max 200)
offsetintegerNoItems 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 }
}

GET/api/v1/runs/:id

Get 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
      }
    ]
  }
}

POST/api/v1/runs/trigger

Trigger a prompt run across AI engines. Returns results synchronously.

Request body

FieldTypeRequiredDescription
prompt_iduuidYesThe prompt to run
enginesstring[]NoSpecific 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
  }
}
Runs execute synchronously and may take 5-15 seconds depending on the number of engines. For production use, consider implementing a webhook or polling pattern.

Competitors

GET/api/v1/competitors

List competitors for a specific brand.

Query parameters

ParameterTypeRequiredDescription
brand_iduuidYesThe 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

GET/api/v1/dashboard/:brandId

Get aggregated dashboard metrics for a brand.

Path parameters

ParameterTypeDescription
brandIduuidThe brand ID

Query parameters

ParameterTypeDefaultDescription
daysinteger14Number 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

FieldDescription
mention_ratePercentage of runs where your brand was mentioned (0-100)
avg_positionAverage position of your brand mention in responses (1 = first mentioned)
share_of_voiceYour brand's mentions as % of total mentions (brand + competitors)
sentiment_scoreAverage sentiment score (-1 to 1, where 1 is most positive)
*_deltaChange compared to the previous period of equal length

Citations

GET/api/v1/citations

List URLs cited by AI engines in their responses.

Query parameters

ParameterTypeRequiredDescription
run_iduuidNoFilter by specific run
brand_iduuidNoFilter citations for a specific brand's prompts
limitintegerNoItems per page (default 50, max 200)
offsetintegerNoItems 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

GET/api/v1/mentions

List brand and competitor mentions detected in AI responses.

Query parameters

ParameterTypeRequiredDescription
brand_iduuidNoFilter by brand
entity_typestringNoFilter: brand or competitor
sentimentstringNoFilter: positive, neutral, or negative
limitintegerNoItems per page (default 50, max 200)
offsetintegerNoItems 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

ValueDescription
positiveBrand mentioned favorably (recommended, praised, highlighted as a top choice)
neutralBrand mentioned factually without strong positive or negative framing
negativeBrand mentioned negatively (criticized, listed as inferior, warned against)

Engines

GET/api/v1/engines

List 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.

Contact support Back to docs