Skip to main content

Overview

The API gives you read-only access to your project’s weekly prompt metrics, raw LLM responses, content item evaluations, and reporting-dashboard aggregates (the same LLM metrics and GA-based series the Reporting page uses). Use it to:
  • Pull brand mention and citation rates into your own dashboards
  • Read the raw LLM responses behind those metrics — useful when briefing a writer
  • Track prompt and provider performance over time
  • Read prompt metadata (collections, sentiment) alongside visibility metrics
  • Export content quality scores (extractability, humanness, and related evaluation fields)
  • Automate exports that match Impact and Competitors reporting

Access and authentication

Generate your project token in Settings → API.
  • One active token per project
  • Token is scoped to that project only
  • Regenerating immediately invalidates the previous token
Send it in the Authorization header:
Authorization: Bearer tp_your_token_here
The reporting endpoints (/reports/llm, /reports/ga) also accept a Supabase user JWT for in-app use; see those sections for details.

Response shape

Every endpoint returns one of:
// success — single resource
{ "request_id": "...", "data": { ... } }

// success — list resource
{ "request_id": "...", "data": [ ... ], "pagination": { "has_more": false, "next_cursor": null } }

// error
{ "request_id": "...", "error": { "code": "invalid_request", "message": "id is required" } }
The /reports/llm and /reports/ga endpoints are exceptions — they return the existing dashboard payloads unchanged for backward compatibility with the in-app Reporting page.

Data freshness

  • Prompt metrics are updated weekly
  • Weekly windows are Sunday-based
  • If you do not pass week_start, endpoints that need a week return your latest available week

Base URL

https://<your-project-ref>.supabase.co/functions/v1

Endpoint index

ResourceMethod & pathNotes
List promptsGET /promptsPaginated, filterable
Single promptGET /prompts/{id}Metrics + provider breakdown + top citations
List responses for a promptGET /prompts/{id}/responsesRaw LLM responses, paginated
Single responseGET /prompts/{id}/responses/{response_id}One iteration’s full text
Prompt timeseriesGET /prompts/{id}/timeseriesTrend across weeks for one prompt
Project timeseriesGET /timeseriesTrend across weeks for the whole project
Project providersGET /providersProvider breakdown for one week
List content itemsGET /content-itemsPaginated
Single content itemGET /content-items/{id}With latest evaluation
LLM reportGET /reports/llmVisibility & competitor aggregates
GA reportGET /reports/gaGA4 traffic + AI-platform filter
SummaryGET /reports/summaryTop-line weekly metrics

Prompts

List prompts — GET /prompts

Paginated prompt-level metrics for one week. Each row includes collections and average_sentiment from the prompt record. Query params
ParameterDescription
week_startOptional, YYYY-MM-DD, normalized to Sunday
providerOptional AI provider id
queryOptional, case-insensitive substring match on prompt text
limitOptional, default 50, max 100
cursorOptional, opaque cursor from pagination.next_cursor
Response data
{
  "request_id": "...",
  "data": {
    "week_start": "2026-05-03",
    "prompts": [
      {
        "id": "...",
        "text": "...",
        "intent": "commercial",
        "search_volume_score": 0.42,
        "average_sentiment": 3.1,
        "collections": [{ "id": "...", "name": "Enterprise" }],
        "mention_rate": 60.0,
        "first_mention_rate": 40.0,
        "citation_rate": 50.0,
        "rank": 1
      }
    ]
  },
  "pagination": { "has_more": false, "next_cursor": null }
}

Single prompt — GET /prompts/{id}

Detail for a single prompt for one week. Query params
  • week_start (optional)
Response data
  • week_start
  • prompt: id, text, intent, search_volume_score, average_sentiment, collections[]
  • mention_rate, first_mention_rate, citation_rate, search_count
  • providers[]: id, name, mention_rate, first_mention_rate, citation_rate
  • top_citations[]: url, domain, citation_type, count
Errors
  • 404 if the prompt does not exist or is not in this project

Responses for a prompt — GET /prompts/{id}/responses

Raw LLM output for each iteration recorded against this prompt during the week. Useful for content briefs — you can see exactly what each provider said. Query params
ParameterDescription
week_startOptional, defaults to the latest week
providerOptional AI provider id to filter to one provider
limitOptional, default 25, max 100
cursorOptional pagination cursor
Response data
{
  "request_id": "...",
  "data": {
    "week_start": "2026-05-03",
    "prompt_id": "...",
    "responses": [
      {
        "id": "...",
        "run_id": "...",
        "provider": { "id": "...", "name": "ChatGPT" },
        "response_text": "...",
        "created_at": "2026-05-04T10:13:22Z"
      }
    ]
  },
  "pagination": { "has_more": true, "next_cursor": "..." }
}
Responses are ordered newest first. Page through with cursor to read every iteration in the week. Errors
  • 404 if the prompt does not exist or is not in this project

Single response — GET /prompts/{id}/responses/{response_id}

A single LLM response by id. Response data
  • id, run_id, prompt_id
  • provider: id, name
  • response_text
  • created_at
Errors
  • 404 if the response does not exist or its prompt is not in this project

Prompt timeseries — GET /prompts/{id}/timeseries

Trend across weeks for one prompt. Query params
  • from_week_start (optional, defaults to 12 weeks ago)
  • to_week_start (optional, defaults to latest week)
  • provider (optional)
Limits
  • At most 52 weeks per request
Response data
  • prompt_id
  • series[]: each point has week_start, mention_rate, first_mention_rate, citation_rate, prompt_count, search_count

Project-level

Project timeseries — GET /timeseries

Same shape as /prompts/{id}/timeseries but aggregated across every prompt in the project. Query params
  • from_week_start, to_week_start, provider (all optional)
Response data
  • series[]: as above

Providers — GET /providers

Per-provider breakdown for one week. Query params
  • week_start (optional)
Response data
  • week_start
  • providers[]: id, name, prompt_count, search_count, mention_rate, first_mention_rate, citation_rate, owned_citations, social_citations, earned_citations, competitor_citations

Content

List content items — GET /content-items

All content items in the project, paginated, with the latest evaluation per item. Query params
  • limit (optional, default 50, max 100)
  • cursor (optional)
Response data
  • content_items[]: id, title, url, created_at, updated_at, evaluation
  • evaluation is null if there is no row in executing_contentitemevaluation, otherwise an object with: score, content_quality, audience_alignment, seo_optimization, engagement_potential, eeat, extractability, humanness_score, prompt_focus, created_at, updated_at and (when present) llm_justifications

Single content item — GET /content-items/{id}

Response data Same shape as one element of content_items[] above. Errors
  • 404 if the item does not exist or is not in this project

Reports

The three reporting endpoints power the in-app Reporting page. Periods use 7 / 30 / 365 calendar days for week / month / year.

Authentication

  • Project API token: Authorization: Bearer tp_.... Do not pass project_id.
  • Logged-in user (Supabase JWT): Authorization: Bearer <access_token> plus project_id in the query string. The user must have access to that project.

LLM report — GET /reports/llm

Full LLM-side reporting: weighted mention rate, citation rate, sentiment, competitor tables and weekly series, citation bucket breakdown, optional experiments. Returns the same payload the in-app Reporting page consumes (with a top-level meta object). Query params
ParameterDescription
project_idRequired for user JWT; omit with API token
start_date, end_dateYYYY-MM-DD inclusive window
periodweek | month | year (default month; ignored when start_date and end_date are set)
collectionsComma-separated tag names
tag_idsComma-separated tag UUIDs
intent / intentsComma-separated intent values
llm_provider / provider_idsComma-separated AI provider UUIDs
location / locationsComma-separated location strings
include_experimentstrue/false (default true)
skip_competitorstrue/false (default false)
page, page_sizePagination for the weekly series slice (defaults 0, 50, max 500)
company_idOptional
target_type, target_idOptional experiment filter
Example
curl -s "https://<your-project-ref>.supabase.co/functions/v1/reports/llm?period=month&collections=Enterprise&intent=commercial" \
  -H "Authorization: Bearer tp_your_token_here"

GA report — GET /reports/ga

GA4 traffic with platform-filtered series. Calls the fetch-google-analytics pipeline, then returns the full analytics payload plus filtered_daily rows (traffic_raw, ai_sessions) using the same platform rules as the Reporting UI. Requires GA4 connected for the project. Query params
ParameterDescription
project_idRequired for user JWT; omit with API token
start_date, end_dateYYYY-MM-DD; both required together if you override period
periodweek | month | year (default month)
page_pathOptional; restricts GA to one landing path
platformsComma-separated UI platform ids (e.g. chatgpt,google-serps). Omit or empty = all traffic
If GA is not connected or tokens are invalid, the status and body match fetch-google-analytics (e.g. 401 with authError: true).

Summary — GET /reports/summary

Top-line metrics for one week. Query params
  • week_start (optional, normalized to Sunday)
  • provider (optional, AI provider id)
Response data
  • week_start
  • totals: prompt_count, search_count, mention_rate, first_mention_rate, citation_rate
  • citations: owned, social, earned, competitor
  • providers[]: id, name, mention_rate, first_mention_rate, citation_rate

Rate and timeout limits

  • Prompts list, responses list, and content items list are capped at 100 rows per request
  • Timeseries is capped at 52 weeks
  • Requests may return 429 if rate or time budgets are exceeded

Errors

Common status codes:
  • 400 invalid input
  • 401 missing or invalid token
  • 404 not found (prompt, response, or content item)
  • 405 method not allowed
  • 429 rate or timeout guardrail
  • 500 unexpected server error
Example body:
{
  "request_id": "...",
  "error": { "code": "invalid_request", "message": "id is required" }
}

Migrating from the previous API (May 2026)

The earlier flat endpoints were replaced with this REST hierarchy in May 2026. The old paths now return 404. If you have an integration written against the previous shape, update the paths as follows:
Old pathNew path
GET /prompt?id=GET /prompts/{id}
GET /prompt-timeseries?id=GET /prompts/{id}/timeseries
GET /prompt-timeseries (no id)GET /timeseries
GET /prompt-providersGET /providers
GET /content-item?id=GET /content-items/{id}
GET /reportGET /reports/llm
GET /ga-reportGET /reports/ga
GET /summaryGET /reports/summary
Response shapes also changed: every endpoint (other than /reports/llm and /reports/ga, which preserve the dashboard payload for in-app use) now returns the standard envelope:
{ "request_id": "...", "data": ..., "pagination": { "has_more": false, "next_cursor": null } }
Where the previous endpoints returned fields like prompts, content_items, series, etc. at the top level, those now live under data. Pagination cursors that were nested under page.has_more / page.next_cursor are now under pagination.has_more / pagination.next_cursor.