API Documentation

Access your AI visibility data with the REST API, native Rust CLI, official SDKs for 12 languages, or MCP. Build dashboards, ETL pipelines, and automated workflows.

API: LLMPulse

Build dashboards, ETL pipelines and automations with a clean, well-typed API.

LLM Pulse is an AI visibility analytics platform that monitors how your brand appears in AI-generated responses from ChatGPT, Perplexity, Gemini, and other LLMs. The API gives you programmatic access to all your visibility data, including brand mentions, citation sources, sentiment analysis, and share of voice metrics. Use it to build custom dashboards, automate reports, or integrate AI visibility tracking into your existing tools.

Authentication

Use a Bearer token from your API Key.

Authorization: Bearer YOUR_API_KEY

Base URL

Use this base URL for all endpoints below. Examples already include the full path.

https://api.llmpulse.ai/api/v1

Using an AI agent? Read the llms.txt

We serve a machine-readable version of these docs so coding agents (Claude Code, Cursor, ChatGPT, etc.) can find the right endpoint without parsing this page.

/api-docs/llms.txt : short index, generated from the live route table.

/api-docs/llms-full.txt : full reference (every endpoint, every parameter).

100% UI-to-API parity, found a gap? We''ll close it

We aim for 100% UI-to-API parity, anything you can see in the LLM Pulse dashboard should be reachable through the API. If you find a gap, report it and we commit to implementing it, typically within hours to a few days.

Quick start

The logical flow is: list resources → (optionally) fetch dimensions → query metrics. The first call to /dimensions/projects already validates your API key.

  1. List your projects: GET /dimensions/projects
  2. (Optional) Fetch project dimensions (competitors, models, locales, tags)
  3. Request metrics under /metrics/*

Official CLI & SDKs

Use the native CLI from a terminal or add a typed SDK to your application. Both cover all 71 documented REST operations and work with the same API keys and base URL shown in this reference.

Rust CLI

A native Rust client for macOS, Linux, and Windows with named profiles plus JSON, table, and CSV output. Use it for quick checks, shell scripts, scheduled exports, and CI jobs.

SDKs for 12 languages

Official generated clients for TypeScript, Python, Go, Java, Kotlin, C#, PHP, Ruby, Rust, Swift, Dart, and R. Each client stays aligned with the published OpenAPI document.

API Playground

API Playground

Test API endpoints live
curl -X GET "https://api.llmpulse.ai/api/v1/ping" -H "Authorization: Bearer YOUR_API_KEY"
\--
Response will appear here...

Sign up to get your API key and start testing

Get API Key

Authentication

Send your key in the Authorization header as a Bearer token. Rotate/revoke under Settings → API Keys.

Missing or malformed headers return 401 ERR_MISSING_AUTH. Unknown keys return 401 ERR_INVALID_API_KEY. Revoked keys return 403 ERR_REVOKED_API_KEY.

Each call runs in the context of the API key’s user. Projects must belong to that user; otherwise 404 ERR_PROJECT_NOT_FOUND.

Versioning & Rate limits

Current version: v1. Future breaking changes will bump the path (e.g. /api/v2).

Rate limiting: 300 requests per minute per API key. Contact us for higher quotas.

Metrics endpoints support conditional GET (ETag/Last-Modified); see Cache & Conditional GET.

Dimensions endpoints

GET/dimensions/projects

Lists the authenticated user’s projects (this is also an auth check).

GET/dimensions/competitors

Lists competitors for the project.

GET/dimensions/collections

Lists collections (Tags) belonging to the project.

GET/dimensions/tags

Alias for /dimensions/collections. Returns the same payload, but named as tags for consistency with the UI.

GET/dimensions/models

Lists models present in daily metrics for the project.

GET/dimensions/locales

Lists countries and languages present in daily metrics for the project.

GET/dimensions/sentiments

(Optional) Lists available sentiment buckets and their metric names.

Params:
  • project_idrequired

GET/dimensions/prompts

Lists prompts in a project.

Params:
  • project_idrequired
  • collection_id
  • promptprompt ID
  • country_code
  • language_code
  • from
  • to
  • page
  • per_page≤100

GET/dimensions/prompt_executions

Lists prompt executions in a project.

Params:
  • project_idrequired
  • model
  • collection_id
  • promptprompt ID
  • country_code
  • language_code
  • from
  • to
  • page
  • per_page
  • mention_filter
  • citation_filter
  • competitorsthe two-axis matrix described under GET /answers

GET/dimensions/sources

Lists non-rejected sources produced by prompt executions.

Params:
  • project_idrequired
  • model
  • collection_id
  • promptprompt ID
  • country_code
  • language_code
  • from
  • to
  • page
  • per_page
  • source_type
  • mention_filter
  • competitors

Here mention_filter applies to the brands named in the crawled content of each cited page, not in the AI answer, mirroring the Citations page.

GET/dimensions/mentions

Lists mentions created by your project.

Params:
  • project_idrequired
  • collection_id
  • promptprompt ID
  • from
  • to
  • page
  • per_page

GET/dimensions/citations

Lists citations created by your project.

Params:
  • project_idrequired
  • collection_id
  • promptprompt ID
  • from
  • to
  • page
  • per_page

GET/dimensions/competitor_mentions

Lists competitor mentions detected in your executions.

Params:
  • project_idrequired
  • competitorsCSV ids
  • promptprompt ID
  • from
  • to
  • page
  • per_page

GET/dimensions/competitor_citations

Lists competitor citations detected in your executions.

Params:
  • project_idrequired
  • competitorsCSV ids
  • promptprompt ID
  • from
  • to
  • page
  • per_page

GET/dimensions/all_mentions

Unified endpoint combining brand and competitor mentions. Each record includes an actor_type field (project or competitor).

Params:
  • project_idrequired
  • competitorsCSV ids
  • model
  • collection_id
  • promptprompt ID
  • country_code
  • language_code
  • from
  • to
  • page
  • per_page

GET/dimensions/all_citations

Unified endpoint combining brand and competitor citations. Each record includes an actor_type field (project or competitor).

Params:
  • project_idrequired
  • competitorsCSV ids
  • model
  • collection_id
  • promptprompt ID
  • country_code
  • language_code
  • from
  • to
  • page
  • per_page

GET/dimensions/projects/:id

Get detailed information about a project: matching names, industry, business model, prompt counts per brand focus, and data_coverage (the models, countries and languages that actually have data), so one call replaces separate models/locales lookups.

GET/dimensions/competitors/:id

Get detailed information about a competitor including matching names and app store IDs.

Agent Analytics

Surfaces AI bot crawler traffic hitting your origin server (GPTBot, PerplexityBot, ClaudeBot, OAI-SearchBot, Google-Extended, and ~25 other AI bots) from Cloudflare or CSV uploads. Available on Scale and above.

GET/metrics/agent_traffic

Aggregated AI bot traffic for a project, grouped by bot or by company, with daily/weekly/monthly granularity.

Params:
  • project_idrequired
  • range
  • from
  • to
  • bot
  • company
  • group_bybot|company
  • granularityday|week|month

GET/dimensions/agent_bots

Static catalog of AI bots that Agent Analytics can identify. Use it to render filter UIs that mirror our internal classification (slug, display name, company, category, Cloudflare verified-bot mapping). Requires Scale or above; the MCP tool list_agent_bots is available on every plan.

Params:
  • project_idrequired

Search Console

Google Search Console performance data (impressions, clicks, CTR, average position) for projects with a connected GSC property. Growth plan or above required. ctr is a 0..1 fraction and position is the impression-weighted average, matching the Search Console API. Projects without a connected property return ERR_SEARCH_CONSOLE_NOT_CONNECTED (404).

GET/search_console/summary

Property-wide headline totals for the range, with an optional country or device breakdown aggregated over the same range.

Params:
  • project_idrequired
  • range
  • from
  • to
  • dimensioncountry|device

GET/search_console/timeseries

Property-wide series bucketed by day, week or month.

Params:
  • project_idrequired
  • range
  • from
  • to
  • granularityday|week|month

GET/search_console/queries

Top search queries for the range, ranked and paginated. Knowingly undercounts anonymized queries, so they do not sum exactly to the summary totals (same as the GSC UI).

Params:
  • project_idrequired
  • range
  • from
  • to
  • sortimpressions|clicks|ctr|position
  • page
  • per_page

GET/search_console/pages

Top landing pages for the range, ranked and paginated. Same shape as the queries endpoint, with each row key being a page URL.

Params:
  • project_idrequired
  • range
  • from
  • to
  • sortimpressions|clicks|ctr|position
  • page
  • per_page

Citation Intelligence

Cited-page intelligence, grouped URL/domain/host views, page-cache metadata, mention evidence inside cited pages, occurrence lists, and sanitized cached content.

GET/citation_intelligence/groups

Grouped citation intelligence by url, domain, or host with per-model breakdown, citation rate, and average citation position (ignores position = 0 rows).

Params:
  • project_idrequired
  • viewurl|domain|host
  • page
  • per_page
  • ordergroup_key, total_responses, total_citations, citation_rate, avg_citation_position, first_seen_at, last_seen_at
  • direction
  • model
  • collection_id
  • country_code
  • language_code
  • prompt
  • from
  • to
  • query
  • source_typeowned|competitor|third_party|social_media|own_domain|ugc|background
  • sentimentnegative
  • content_gapmentioned|gap

Invalid enum values return ERR_INVALID_PARAM.

GET/citation_intelligence/mentions_by_domain

For the responses where each given source domain is cited, the share of those responses that mention your brand vs each competitor. Brand and competitors are normalized to sum to 100% per domain, mirroring the Share of Voice mention definition. Pass several domains to analyze the whole matrix in one call.

Params:
  • project_idrequired
  • domainsrequired array, e.g. domains[]=example.com, max 50
  • model
  • collection_id
  • collection_ids
  • country_code
  • language_code
  • prompt
  • from
  • to

Empty domains returns ERR_INVALID_PARAM. Each row has responses_citing, total_mentions, and an actors array (brand and competitors with mentions and share).

GET/citation_intelligence/urls/:url_sha256

URL-level detail for one cited page: totals, citation rate, avg citation position, source-type counts, per-model counts, distinct URL variants, page-cache metadata, and page mention evidence with snippets and actor labels.

  • Params: project_id (required), :url_sha256 (64 hex chars in URL), same optional filters as /citation_intelligence/groups. ERR_NOT_FOUND only when the URL was never cited by the project; filters that empty the result still return 200 with zero stats.

GET/citation_intelligence/urls/:url_sha256/occurrences

Paginated occurrences of a cited URL across prompt executions, with response excerpt, prompt text, model, executed_at, citation_position and source_type per row.

  • Params: project_id (required), :url_sha256 (64 hex chars), page, per_page, same optional filters as /citation_intelligence/groups.

GET/citation_intelligence/urls/:url_sha256/content

Sanitized cached page content for a cited URL: page-cache metadata, mention evidence and snippets, full plain text, and rendered HTML (scripts and unsafe markup removed).

Params:
  • project_idrequired
  • :url_sha25664 hex chars

AI Model Insights

Aggregate parts of the in-app AI Model Insights report. All three endpoints filter by executed_at (not created_at) and share a standard actor shape: { type, id, competitor_id, name, domain } with bare (scheme-less) domains.

GET/reports/ai_model_insights/summary

Per-model mention counts and shares, citation counts and shares, brand net sentiment with raw positive/negative counts, weighted visibility totals and shares, plus actor matrices for each.

Params:
  • project_idrequired
  • rangedefault 28
  • from
  • to
  • granularityday|week|month
  • collection_id
  • country_code
  • language_code
  • prompt_type
  • brand_kinduse non_brand to match the in-app AI Model Insights Overview tab and for fair brand-vs-competitor comparisons
  • competitorsCSV of competitor IDs; unknown IDs → ERR_INVALID_PARAM

GET/reports/ai_model_insights/position_distribution

Position-distribution comparison used in the AI Model Insights report: one or two brand series with bucketed totals (Position 1, Position 2-3, Position 4-7, Position 8+) and chart-ready time series per bucket.

Params:
  • project_idrequired
  • range
  • from
  • to
  • granularity
  • collection_id
  • country_code
  • language_code
  • prompt_type
  • brand_kinduse non_brand for a fair head-to-head, the in-app default
  • modelrestrict to one model
  • brand1
  • brand2competitor IDs for the comparison brands; omit brand1 to compare the project brand

GET/reports/ai_model_insights/ai_overview_results

Aggregate Google AI Overview result-availability data: total AI Overview responses, responses with results (no_result = false), result rate, chart-ready trend data, and a paginated by-prompt result-rate table.

Params:
  • project_idrequired
  • range
  • from
  • tofilters by executed_at
  • collection_id
  • country_code
  • language_code
  • prompt_type
  • brand_kind
  • granularity
  • page
  • per_page

Recommendations

Read-only API for the same recommendation runs that power the in-app Recommendations experience.

GET/recommendations

Lists recommendation runs for a project with type/status filters.

Params:
  • project_idrequired
  • recommendation_typeai_visibility|social_community|brand_building|sentiment_reputation
  • statuspending|processing|completed|failed
  • page
  • per_page

Invalid enum values return ERR_INVALID_PARAM.

GET/recommendations/:id

One recommendation run with its items and report data: items array with title, priority, action steps, metadata, source references, plus item counts grouped by active, completed, archived.

Params:
  • project_idrequired
  • :idin URL
  • item_statusactive|completed|archived
  • resolve_source_refsdefault true

POST/recommendations

Launch a new generation (same engine as the in-app Recommendations page). Runs async (1-3 minutes); poll GET /recommendations/:id until status is completed. Consumes the project weekly recommendation-item budget (ERR_LIMIT_REACHED when exhausted, or when a run of the same type is already pending). sentiment_reputation requires Scale or above. Requires a writable API key.

Body (JSON):
  • project_idrequired
  • recommendation_typeai_visibility default | social_community | brand_building | sentiment_reputation

Answers (AI Responses)

Access the actual AI-generated responses with full content, mentions, citations, and sentiment analysis.

GET/answers

List AI responses with their content. Returns paginated results with truncated response text (max 10,000 chars). Pass query for case-insensitive full-text search inside response texts: total becomes the exact count of matching responses, and each item returns snippet and match_count instead of the full response.

Params:
  • project_idrequired
  • model
  • collection_id
  • promptprompt ID
  • country_code
  • language_code
  • from
  • to
  • page
  • per_page
  • queryfull-text search
  • mention_filter
  • citation_filter
  • competitors

The last three are the two-axis matrix from the Responses page: mention_filter takes mentions_you, not_mentions_you, mentions_competitor, not_mentions_competitor, you_and_competitor, competitor_not_you, you_not_competitor or no_brands (no tracked brand appears at all); citation_filter takes the same cells against cited domains (cites_you, not_cites_you, cites_competitor, not_cites_competitor, you_and_competitor, competitor_not_you, you_not_competitor, cites_no_brands). Both combine, and competitors (CSV of IDs) narrows the competitor side to those rivals. Unknown presets return ERR_INVALID_PARAM.

GET/answers/:id

Get a single AI response with full details including mentions, citations, sentiments, and sources.

Params:
  • project_idrequired
  • idanswer ID in URL

Detailed Sentiments

Access detailed sentiment analysis with comments, topics, and scores. This is different from /dimensions/sentiments which only returns sentiment categories.

GET/sentiments

List detailed sentiment records with full analysis context.

Params:
  • project_idrequired
  • model
  • competitor_id
  • brand_only
  • analysisvery_positive/positive/neutral/negative/very_negative
  • collection_id
  • promptprompt ID
  • country_code
  • language_code
  • from
  • to
  • page
  • per_page

Prompts (Bulk Create + Delete)

Add prompts to a project in bulk via the API. Validates against account prompt limits and deduplicates automatically.

POST/prompts

Create up to 100 prompts per request. Existing prompts (same text + locale) are skipped.

Body (JSON):
  • project_idrequired
  • promptsarray, required, max 100
  • country_coderequired
  • language_coderequired

DELETE/prompts/:id

Delete a prompt. Irreversible; the prompt disappears immediately, frees a prompt slot, and its history (executions, mentions, citations, sentiment) is purged by a background job. Requires a writable API key.

Params:
  • project_idrequired
  • :idin URL

Returns ERR_NOT_FOUND for prompts outside the project.

GEO Writer

Create and manage AI-powered GEO Writer tasks via the API. Tasks are processed asynchronously and results can be polled.

POST/intelligence_tasks

Create a GEO Writer task. Two modes: prompt-based (provide prompt_id) or agentic (provide custom_topic and/or user_instructions).

Body (JSON):
  • project_idrequired
  • task_typerequired: brief, create, update, pr_insights, custom
  • prompt_id
  • custom_topic
  • user_instructions
  • output_language_code
  • existing_content
  • existing_content_url

GET/intelligence_tasks

List GEO Writer tasks for a project with optional filtering.

Params:
  • project_idrequired
  • task_type
  • status
  • page
  • per_page

GET/intelligence_tasks/:id

Get full task details including result data when completed. Accepts numeric ID or public_id.

Params:
  • project_idrequired
  • :idtask ID or public_id in URL

Agent Write Endpoints

These endpoints accept POST/PATCH/PUT/DELETE and require an API key with the read_write scope. A token with the read scope receives 403 ERR_INSUFFICIENT_SCOPE. Writes share a tighter rate limit (60/min/key) in addition to the global 300/min/key budget.

POST/projects

Create a complete project in one call (fast mode): project, prompts (queued for execution + categorization), competitors, weekly email subscription. Idempotent when external_identifier is provided. The project always belongs to the account owner.

  • Body (JSON): website_url (required public HTTP(S) URL with a DNS hostname or public IP address; credentials, private and special IP addresses, localhost and internal hostnames are rejected), name (required), main_country (required), main_language (required), brand_name, description, industry (array), matching_names (array), prompts (array, max 100), competitors (array of {domain, brand_name, matching_names}), owned_media (object, Growth+), use_subdomain, weekly_email_subscribed, external_identifier (embed-enabled accounts only; idempotency key, [a-z0-9_-]{1,64}), execute_prompts_immediately (default true).

Project Drafts wizard

Multi-step project wizard with AI suggestions: POST /project_drafts starts a draft (returns suggested name/description/industry for the URL), PATCH submits each step (details, prompts, competitors, owned_media) with strict forward gating and returns suggestions for the next step, POST /project_drafts/:id/finalize creates the real project. Drafts expire after 24h.

  • The initial website_url must be a public HTTP(S) URL with a DNS hostname or public IP address. Credentials, private and special IP addresses, localhost and internal hostnames are rejected. Steps: details (name required), prompts (max 100, quota-validated), competitors (plan-capped), owned_media (optional, Growth+). Suggestions per step with suggest=false opt-out; cold URLs can take up to ~2 minutes, set client timeout to 180s. Finalize is idempotent and re-validates every gate.

POST/competitors

Add a competitor (brand_name + domain) to a project. Honours the per-plan max competitors cap.

Body (JSON):
  • project_idrequired
  • brand_namerequired
  • domainrequired, URL is normalised
  • matching_namesoptional array

PATCH/DELETE /competitors/:id

Update a competitor (brand_name, matching_names, color; the domain is immutable after creation) or delete it. Name changes re-run mention/citation matching in the background (processing: true for a few minutes, edits blocked meanwhile). Deleting is irreversible and purges the competitor data in the background.

PATCH body:
  • project_idrequired
  • brand_name
  • matching_namesfull replacement array
  • colorhex

DELETE: project_id + :id in URL.

POST/collections

Create a tag (Collection) in a project. Optionally attach existing prompts in the same call. Tag name is case-insensitive unique per project.

Body (JSON):
  • project_idrequired
  • namerequired
  • descriptionoptional
  • prompt_idsoptional array, must belong to the project

PATCH/DELETE /collections/:id

Rename a tag or change its description, or delete it. Deleting a tag keeps the prompts inside it; only the grouping disappears. Prompt membership is managed via POST /prompts/assign_tags.

  • PATCH body: project_id (required), name and/or description. DELETE: project_id + :id in URL.

POST/prompts/assign_tags

Idempotent bulk attachment of tags to existing prompts. Tags can be resolved by id or name.

Body (JSON):
  • project_idrequired
  • prompt_idsrequired array
  • tag_idsone-of
  • tag_namesone-of
  • create_missingoptional bool, auto-create unknown tag names

POST/annotations

Mark a date in the project timeseries with a title + description. Available on every plan.

Body (JSON):
  • project_idrequired
  • titlerequired
  • annotation_dateoptional ISO YYYY-MM-DD; default today
  • descriptionoptional
  • coloroptional hex
  • annotation_category_idoptional, must belong to the project

GET /annotations + PATCH/DELETE /annotations/:id

List, update, and delete annotations on every plan. GET returns manual, automatic, GEO test, and platform annotations newest first. The origin field distinguishes them, and editable says whether the requesting user may modify a row. PATCH and DELETE only work on manual annotations belonging to your own user (403 otherwise).

  • GET query: project_id (required), from/to (YYYY-MM-DD), annotation_category_id, page, per_page. PATCH body: any of title, description, annotation_date, color, annotation_category_id. DELETE: project_id + :id in URL.

POST/technical_geo_reports

Launch the full technical GEO analysis bundle (crawlability, schema, content readiness, discoverability, site structure, robots.txt, llms.txt, AI visibility) for a URL + country. Each report runs as a background job.

Body (JSON):
  • project_idrequired
  • urlrequired
  • country_codeoptional, defaults to the project country

Webhooks

Receive a signed HTTP POST every time something happens in a project, with no polling. Webhooks power the LLM Pulse connectors for Zapier, Make and n8n, and work with any custom backend. Available on the Scale plan and above. Each delivery is a JSON envelope: { "event", "occurred_at", "project_id", "subscription_id", "data" }.

  • Event types: mention.created, competitor_mention.created, citation.created, prompt_execution.completed, sentiment.negative_detected (negative or very negative brand sentiment), recommendation.completed, intelligence_task.completed.
  • Security: every delivery carries X-LLMPulse-Event, X-LLMPulse-Delivery (unique id) and X-LLMPulse-Signature (sha256=<hex>, HMAC-SHA256 of the raw body computed with the subscription secret). Verify the signature to authenticate deliveries.
  • Delivery: a 2xx response acknowledges the event; anything else is retried 5 times with exponential backoff. Subscriptions auto-disable after 20 consecutive failed deliveries.

POST/webhooks

Create a subscription. Idempotent: re-posting the same project + event + URL returns the existing subscription. The signing secret (whsec_...) is only returned by this endpoint, store it to verify delivery signatures. Requires a read_write scope key.

Body (JSON):
  • project_idrequired
  • event_typerequired, see event list above
  • target_urlrequired, public HTTPS URL; private IPs, localhost and internal hostnames are rejected

Max 100 active subscriptions per account.

GET/webhooks

List active subscriptions for the account. Items match the create response without the secret.

Params:
  • project_idoptional filter
  • page
  • per_pagemax 100

DELETE/webhooks/:id

Delete a subscription. The target URL stops receiving events immediately. Requires a read_write scope key.

Path:
  • :idsubscription id

Returns ERR_NOT_FOUND for subscriptions that do not belong to the account.

GET/webhooks/sample/:event_type

Up to 3 example event payloads for the event type, built from the project''s most recent real data (or a static sample when the project has no data yet). Used by integration editors such as the Zapier sample loader. Also available as the MCP tool get_webhook_sample.

Params:
  • :event_typepath
  • project_idrequired

Filters & Common params

  • project_id required for all project-scoped endpoints.
  • metrics or metric: CSV of mentions, citations, responses, mention_rate (or visibility), citation_rate, ai_visibility_score, avg_position, avg_mention_position, sentiment_very_positive, sentiment_positive, sentiment_neutral, sentiment_negative, sentiment_very_negative, net_sentiment
  • granularity: day|week|month (weeks start Monday)
  • Time window: either range (days) or from & to (ISO8601). If you send to, from is required. Defaults with from/to: missing from = 30 days ago (start of day); missing to = now (end of day).
  • Filters: model, collection_id (tag id), prompt (prompt ID), country_code, language_code, competitors (CSV IDs)
  • include_project (default true): set false to exclude your project (return only competitors).

Output Formats for BI Tools

Read endpoints return nested JSON by default, which is convenient for code but unreadable for business intelligence tools. Pass the optional output parameter to get the same data as a rectangular table that Tableau, Excel, Google Sheets or a warehouse loader can consume directly.

  • output omitted (default): the nested JSON documented for each endpoint. Unchanged, so existing integrations are unaffected.
  • output=flat: the same metadata plus columns (ordered column names), rows (one flat object per row) and row_count.
  • output=csv: the same rows as text/csv, with columns as the header row.

Supported on /metrics/timeseries, /metrics/summary, /metrics/sov, /metrics/prompt_summary, /metrics/top_sources, the /search_console/* series and the list-returning /dimensions/* endpoints. Endpoints whose payload is not a single table (/metrics/agent_traffic, /metrics/ai_traffic, /search_console/summary, /dimensions/models, /dimensions/locales) reject output instead of ignoring it.

/metrics/sov also accepts view=over_time (default), view=current or view=breakdown: its payload holds several different shapes and a table can only hold one at a time.

Columns by endpoint

Endpoint Columns
/metrics/timeseries date, actor_type, actor_id, actor_name, actor_domain, metric, value
/metrics/summary actor_type, actor_id, actor_name, actor_domain, metric, aggregation, total, min, max, last
/metrics/sov date, actor_type, actor_id, actor_name, actor_domain, share
/metrics/sov?view=current actor_type, actor_id, actor_name, actor_domain, share
/metrics/sov?view=breakdown rank, actor_type, actor_id, actor_name, actor_domain, share, others
/metrics/prompt_summary, /metrics/top_sources, /search_console/*, /dimensions/* The keys of the endpoint's own data rows

Example

GET /api/v1/metrics/timeseries?project_id=1&range=30&metrics=mentions&output=csv

date,actor_type,actor_id,actor_name,actor_domain,metric,value
2025-01-01,project,1,My Brand,mybrand.com,mentions,10
2025-01-01,competitor,2,Competitor A,competitor.com,mentions,5

Notes:

  • Errors are always returned as JSON, never as CSV, so a failure is never mistaken for data.
  • Percentages stay on the raw 0-100 scale, exactly as in the JSON response.
  • Text cells that begin with an equals, plus, minus or at sign are escaped so spreadsheets do not execute them as formulas.
  • Paginated endpoints also return their paging metadata in the X-Total-Count, X-Page and X-Per-Page response headers, which a CSV body cannot carry.
  • Flat output is capped at 200,000 rows. Above that, narrow the date range, request fewer metrics, or use granularity=week.
  • Endpoints without a flat projection reject output with ERR_INVALID_PARAM instead of ignoring it.

Metrics: Semantics & aggregation

These semantics are aligned 1:1 with the Overview UI.

  • mentions: daily sums of mentions_count. For week/month we compute the PERIOD TOTAL (Mon-Sun for weeks) and repeat that same total for every day in the period. If a period’s total is 0, we “carry” the last non-zero period total (sticky).
  • citations: response-level count that includes visible citations and background source references. Each actor counts at most once per response. Uses the same period-total and sticky-carry behavior as mentions.
  • responses: total number of prompt executions (API calls to LLMs). Uses project-level execution count regardless of actor. • day: daily sum. • week/month: period total (no sticky carry, days with 0 executions show 0).
  • Mention Rate mention_rate (also accepted as visibility): percentage per actor, using the project-level executions as denominator under the same filters (mentions_count / prompt_executions_count × 100). • day: compute the daily ratio. • week/month: compute the ratio-of-sums for the period (Σ mentions / Σ executions) and repeat that value for every day in the period. If the period's denominator is 0, carry forward the last non-null value.
  • citation_rate: percentage of responses that include a visible or background citation for the actor (citations_count / prompt_executions_count × 100). • day: daily ratio. • week/month: ratio-of-period-sums with sticky carry, same as visibility.
  • AI Visibility Score ai_visibility_score: position-weighted visibility metric that accounts for mention prominence. Uses reciprocal position weighting (position 1 = 100%, position 2 = 50%, position 3 = 33%, etc.). Higher scores indicate both more mentions AND better positioning. • day: compute daily weighted score / executions. • week/month: ratio-of-period-sums with sticky carry, same as visibility.
  • avg_position: average visible citation position. Background citations have no visible position and are excluded. • day: daily average excluding nulls. • week/month: average within the period (ignoring nulls) and then propagate (carry) the last known value to days without data, matching the Overview chart smoothing.
  • avg_mention_position: average position of the brand when mentioned in AI responses (position 1 = first mentioned, position 2 = second, etc.). Lower is better. • day: daily average excluding nulls. • week/month: average within the period with sticky carry.
  • Sentiment metrics sentiment_very_positive,sentiment_positive,sentiment_neutral,sentiment_negative,sentiment_very_negative: for each actor and day, percentage of sentiments in that bucket over all sentiments for that actor. • day: daily ratio (bucket_count / total_sentiments * 100). Days with no sentiments return null. • week/month: we compute a ratio-of-period-sums (Σ bucket / Σ total * 100) and repeat that percentage for every day in the period. If the period’s denominator is 0, we carry forward the last non-null value (sticky), matching the Overview smoothing.
  • Net Sentiment Score net_sentiment: para cada actor y día, calculamos un score en [-100, 100]: ( (very_positive + positive) − (negative + very_negative) ) / total_sentiments × 100. • day: usamos los porcentajes diarios de cada bucket (las métricas sentiment_*) y calculamos net = (pos+very_pos) − (neg+very_neg). • week/month: el score hereda las mismas semánticas de agregación/smoothing que los buckets de sentiment, porque se calcula a partir de esas series.

In /metrics/summary, total is a sum for count metrics and an average for avg_position, avg_mention_position, and net_sentiment.

GET /metrics/timeseries

Returns time series for one or more metrics, grouped by actor (your project + selected competitors). Weekly/monthly values follow the period semantics above. Optional prompt_type (search intent) and brand_kind filters scope every metric to a prompt category.

GET /metrics/summary

Aggregates per actor and metric (total/min/max/last). Ideal for KPI tiles.

GET /metrics/prompt_summary

Returns paginated per-prompt aggregated metrics (responses, mentions, citations, mention_rate, citation_rate, avg_mention_position, avg_position). Supports breakdown=model to add the AI model dimension to each row, returning per-prompt per-model metrics. Params: sort (responses, mentions, citations, mention_rate or visibility, citation_rate, avg_mention_position, avg_position), sort_dir (asc/desc), breakdown (model), page, per_page (max 100).

GET /metrics/sov

Share of Voice based on mentions, aligned with Overview.

  • over_time: for each date, SOV = (actor_mentions / sum_all_mentions) × 100. If the daily sum is 0, the last value is carried forward (sticky).
  • current: uses the latest date with non-zero total; if none, it uses totals over the whole range.
  • breakdown: top 4 actors + an aggregated Others row (and a detailed others list).

GET /metrics/top_sources

Ranks source domains by number of responses and average mention rate (% of executions that surfaced that domain).

  • The dataset includes non-rejected sources linked to prompt executions within the window and current filters.
  • total_responses: number of unique prompt executions that produced at least one source on that domain.
  • avg_mention_rate (also returned as avg_visibility): (count of source rows for the domain / total executions) × 100.
  • Sorting: sort=total_responses (default), sort=avg_mention_rate, or sort=avg_visibility.
  • Pagination: page (>=1), per_page (default 20, max 100).
  • Filter by domain: query (case-insensitive LIKE), e.g. query=github.

GET /metrics/ai_traffic

Returns the AI-referred traffic measured from a project's connected web analytics provider (Google Analytics 4, Adobe Analytics, PostHog, Plausible or Piano): per-day users, sessions and conversions grouped by AI source (ChatGPT, Perplexity, Gemini, Claude and others), with totals and a conversion rate. Requires the Scale plan or above and a connected provider; projects without one return ERR_AI_TRAFFIC_NOT_CONNECTED (404).

Params:
  • project_idrequired
  • range
  • from
  • to
  • granularityday|week|month
  • sourcerestrict to one AI source

Cache & Conditional GET

Metrics endpoints (timeseries, summary, sov, top_sources) support conditional GET. We compute an ETag from the project version and a hash of your query params, and use the project’s updated_at as Last-Modified.

Send If-None-Match or If-Modified-Since to receive 304 Not Modified when nothing changed.

Errors

Errors are consistent and machine-parsable:

Code HTTP Meaning
ERR_MISSING_AUTH 401 Missing or malformed Authorization header
ERR_INVALID_API_KEY 401 Token not recognized
ERR_REVOKED_API_KEY 403 Key revoked
ERR_PROJECT_NOT_FOUND 404 project_id not accessible by this user
ERR_NOT_FOUND 404 Resource not found
ERR_INVALID_PARAM 422 Validation failed (see message)
ERR_LIMIT_REACHED 422 Account prompt limit reached
ERR_QUOTA_EXCEEDED 422 Monthly GEO Writer task quota exceeded

Error body shape:

Typical 422 cases:

  • invalid metrics: only mentions, citations, responses, mention_rate (or visibility), citation_rate, ai_visibility_score, avg_position, avg_mention_position, sentiment_very_positive, sentiment_positive, sentiment_neutral, sentiment_negative, sentiment_very_negative, net_sentiment are allowed.
  • invalid granularity: must be day|week|month.
  • from/to must be ISO8601, or from is required with to.
  • range is required when neither from nor to are sent.
  • unknown competitor ids: ...: IDs not found under the project.

Client snippets

Examples in multiple languages are shown in the code panel on the right.

Postman: Download & Environment

Use this curated Postman collection to explore the API quickly and securely. It mirrors the examples and metric semantics described above (period totals with sticky carry, ratio-of-period-sums for visibility, and propagation for avg_position), so you can validate responses and prototype integrations in minutes.

Download the collection

Download LLMPulse API v1 Postman Collection

Import the file in Postman (File → Import), then select or create the environment shown below. The collection uses variables, so you won’t need to edit each request manually.

Environment (placeholders, keep your IDs private)

Create a new Environment in Postman with the following variables. Use placeholders instead of real IDs or keys in any public context (docs, screenshots, etc.):

How it’s used:

  • The collection reads {{base_url}} and injects Authorization: Bearer {{api_key}} automatically.
  • Set {{project_id}} to a project you own; {{competitors}} is CSV (e.g. 1,2,3).
  • You can override per request (e.g. send from/to instead of range) and add filters like model, collection_id, country_code, language_code.
  • Keep your API key in your private environment only; do not paste it into shared documents.

MCP (AI Integration)

MCP (Model Context Protocol) allows AI assistants like ChatGPT, Claude and Gemini to access your LLM Pulse data directly. Available on every plan via OAuth, no API key required. Ask questions in natural language and let the AI fetch and analyze your visibility data.

What is MCP?

MCP is an open protocol that lets AI assistants connect to external data sources. Instead of copying data or making API calls manually, you can simply ask your AI assistant questions like "What's my visibility trend this month?" and it will fetch the data automatically.

Endpoint

Configuration

Recommended for every plan: paste the MCP URL into your AI client. The client handles OAuth automatically, no token to copy. API-key auth (Bearer header) is available on the Scale plan and above for headless integrations.

Struggling to connect?

MCP and OAuth support is still uneven across AI clients, so connections sometimes fail to establish. On the Scale plan and above, the easiest fallback is to give your AI assistant a Bearer API key plus a link to these API docs. It can then query every endpoint directly over plain HTTP, with no MCP client setup at all.

Available Tools

These tools are available to your AI assistant.

Live list rendered from Mcp::LlmPulseServer::TOOLS (74 tools registered). The MCP server filters tools/list per user plan.

Tool Description Plan
list_projects List all projects accessible to the authenticated user. Returns project id and name. All
list_competitors List all competitors for a specific project. Returns competitor id, name, domain, and matching_names (the aliases used for mention matching). With include_project_brand=true a synthetic first row represents the tracked brand itself: its id is the PROJECT id (not a competitor id, so do not pass it to get_competitor_details) and it carries actor_type=project / is_own=true. All
list_collections List all collections (tags) for a specific project. Returns collection id and name. Collections and tags are the SAME underlying object: this returns identical data to list_tags. All
list_tags List all tags for a specific project. Tags and collections are the SAME underlying object in LLM Pulse: this returns identical data to list_collections, and create_collection / assign_prompt_tags(create_missing) write to the same set. All
list_models List all AI models that have data for a specific project. Returns model identifiers (e.g., chatgpt, perplexity, gemini, ai_mode, ai_overview). Note: get_project_details data_coverage already includes this, so a separate call is rarely needed. All
list_locales List all countries and languages that have data for a specific project. Returns lists of country codes (e.g., US, ES) and language codes (e.g., en, es). All
list_sentiments List all sentiment categories with their metric keys, labels, and colors. Used for understanding sentiment data structure. All
list_prompts List prompts for a project with optional filtering by collection, locale, prompt_type, brand_kind, and date range. Returns paginated results with prompt id, prompt_text, tags (the authoritative tag/collection memberships as {id, name} pairs; use this to audit tagging), collection_ids, country_code, language_code, prompt_type, brand_kind, and last_executed_at. The legacy collection_id field can be null even when the prompt HAS tags; never conclude a prompt is untagged from collection_id. All
list_prompt_executions List prompt executions with model, success, execution timing, fan-out queries, and mention/citation presence. duration_ms measures internal processing time of the answer pipeline, NOT the AI model latency, and can be near zero. fan_out_queries is only populated for models/providers that expose query fan-out (mainly chatgpt), null elsewhere. All
list_mentions List OWN mentions of the project brand only (no competitors). Use list_all_mentions for brand + competitors with an actor_type field. Returns paginated results with mention id, name, prompt_id, prompt_execution_id, and created_at. All
list_citations List OWN URL citations of the project brand only (no competitors; effectively one citation per answering response). Use list_all_citations for brand + competitors, and list_sources / list_citation_groups for per-URL granularity with url_sha256. position 0 means unranked/background (real positions are 1-indexed). Returns paginated results with citation id, name, domain, prompt_id, prompt_execution_id, url, position, and created_at. All
list_competitor_mentions List competitor mentions for a project with optional competitor and prompt filters. All
list_competitor_citations List competitor citations for a project with optional competitor and prompt filters. All
list_all_mentions List all mentions (brand + competitor) for a project with actor_type field. Returns paginated results combining project and competitor mentions. The competitors filter narrows which competitor rows are included, but project rows are ALWAYS included. All
list_all_citations List all citations (brand + competitor) for a project with actor_type field. Returns paginated results combining project and competitor citations. The competitors filter narrows which competitor rows are included, but project rows are ALWAYS included. position 0 means unranked/background (real positions are 1-indexed). All
list_sources List sources (URLs cited by AI models) for a project with optional filtering. Returns paginated results with source id, prompt_execution_id, domain, url, position, source_type (owned, competitor or third_party), and app-store link flags. All
list_citation_groups List grouped citation intelligence data by URL, domain, or host, including citation rates, model breakdowns, and page-cache awareness. Rows are compact by default; pass include_page_details=true to embed crawled page content details (url view only), and keep per_page moderate when you do. All
get_cited_url_details Get detailed URL-level citation intelligence for one cited URL, including page-cache metadata and mention evidence. All
list_cited_url_occurrences List every prompt execution where a specific cited URL appeared, with prompt text, answer preview, model, and citation position. All
get_cited_url_content Get sanitized cached page content plus page-cache metadata and mention snippets for one cited URL. Text longer than 15,000 characters is truncated (content.text_truncated=true, full length in content.text_total_chars); use max_chars to shrink the slice and offset to page through the rest. All
get_mentions_by_citing_domain For responses where a given source domain is cited, returns the share of those responses that mention the brand vs each competitor (brand + competitors sum to 100% per domain). Accepts a list of domains so the whole matrix is one call. Answers questions like "when gmac.com is cited, which brands get mentioned?". All
get_timeseries Get time series metrics data for a project. Supports metrics like mentions, citations, mention_rate (also accepted as visibility), citation_rate, responses, ai_visibility_score (position-weighted visibility, unbounded: it can exceed 100 when several brand mentions rank high in one period), avg_position, net_sentiment, and sentiment breakdowns. Returns data points over time for the project; competitor series are only included when you pass competitors (ids from list_competitors). With week/month granularity the first bucket covers only the in-window days (partial periods are clipped, not back-filled). When comparing the project against competitors 1:1, set brand_kind=non_brand (the in-app Overview default) so brand-focused prompts do not skew the comparison. All
get_summary Get summary statistics for metrics over a time period. Returns one row per metric and actor with total (count metrics are summed; percentage/rate metrics are averaged across periods, never summed), min, max, and last values. Use group_by to get one summary per AI model or per collection in a single call instead of fanning out multiple filtered calls. When comparing the project against competitors 1:1, set brand_kind=non_brand (the in-app Overview default) so brand-focused prompts do not skew the comparison. All
get_prompt_summary Get per-prompt aggregated metrics (responses, mentions, citations, mention_rate, citation_rate, avg_mention_position, avg_position) with pagination and sorting. mention_rate (also accepted as visibility) is the percentage of responses mentioning the brand. Returns brand-only metrics broken down by individual prompt. Supports breakdown=model to get per-prompt per-model metrics. Field notes: visibility and mention_rate are the same value (historical alias, both kept for compatibility); avg_mention_position is the average position of the brand WITHIN the answers that mention it, while avg_position is the position-weighted metric used by ai_visibility_score. All
get_sov Get Share of Voice metrics - shows the relative share of mentions between the project and competitors over time. Returns current share percentages and breakdown by actor, plus a periods array with the sample size (mentions) and a partial flag per bucket: shares in a bucket with 1-3 mentions read as 100/50/33.33 and should be treated as low-sample noise, and partial buckets are still collecting data. Use group_by=model to get the per-model share comparison in ONE call instead of one filtered call per model. For a fair brand-vs-competitor comparison, set brand_kind=non_brand (the in-app Overview default): brand-focused prompts skew the share toward the brand they name. All
get_top_sources Get top performing source domains for a project. Returns domains ranked by citing responses; avg_visibility (alias avg_mention_rate) is the percentage of all responses in the window that cite the domain at least once (bounded 0-100). All
get_ai_model_summary Per-AI-model breakdown of mentions, citations, sentiment and weighted visibility for the brand and competitors, in a single call. USE THIS for any question that compares performance across AI models ("which model do I rank best on?", "ChatGPT vs Perplexity vs Gemini", "where am I most visible across models?"). Prefer this over calling get_summary multiple times with different model filters: get_ai_model_summary returns all models at once and avoids hitting the step limit. The in-app AI Model Insights Overview tab defaults to non-brand prompts, so pass brand_kind=non_brand to match its numbers and for fair brand-vs-competitor comparisons. NOTE: mentions_market_share values are the independent mention rate of each actor within a model (mentions divided by the responses of that model); one response can mention several actors, so the values do NOT sum to 100 and must not be charted as a share pie. For a true share partition use get_sov. All
get_ai_model_position_distribution Get the AI Model Insights position-distribution comparison for the project brand and an optional competitor. For a fair head-to-head, pass brand_kind=non_brand (the in-app AI Model Insights default): brand-focused prompts skew positions toward the brand they name. When brand2 is omitted it defaults to the largest competitor by mentions. Weekly/monthly buckets are aligned to full calendar periods: the first bucket covers the whole week/month containing the range start (so its counts can differ from get_timeseries, which clips partial periods). All
get_ai_overview_results Get aggregate Google AI Overview result availability over time plus per-prompt breakdowns. All
list_answers List AI answers/responses with their content, prompt text, model, and basic metrics. Returns paginated results; response text is truncated to 1,500 characters per row by default (response_truncated flags it). Pass full_text=true for up to 10,000 characters per row, or use get_answer for one complete response. Pass query to full-text search the response texts: total then equals the exact number of matching responses (use it for counting questions instead of reading pages), and each row returns a short snippet around the match instead of the full text. All
get_answer Get detailed information about a single AI answer/response including full response text, mentions, citations, sentiments, and sources. All
list_detailed_sentiments List detailed sentiment analysis records with comments, topics, scores, and competitor information. This is different from list_sentiments which only returns sentiment categories. All
list_recommendations List read-only recommendation runs for a project, including type, status, summary, and counts. All
get_recommendation Get full details for one recommendation run, including items, source references, and report data. Each item carries source_refs codes (e.g. P1, C2); resolve them against the report_data indices (prompts_index, citations_index, own_content_index), which are always included once per response. All
get_project_details Get detailed information about a project: matching names, industry, business model, primary products, target audience, prompt counts per brand focus (brand / brand_other / non_brand), and data_coverage (the AI models, countries and languages that actually have data). Call this right after list_projects: it replaces separate list_models / list_locales calls and tells you the non_brand prompt pool size before filtered queries. All
get_competitor_details Get detailed information about a competitor including matching names, mobile app IDs, and icon URLs. All
create_prompts Add prompts to a project in bulk. Validates against available prompt limits. Skips duplicates. New prompts run ONCE within minutes of creation (so results appear fast) and then join the weekly schedule. brand_kind / prompt_type are classified asynchronously; fetch them via list_prompts a little later. In the response, prompts_available=null means unlimited. All
delete_prompt Delete a prompt from a project (same as Delete on the Prompts page). IRREVERSIBLE: the prompt disappears immediately, frees a prompt slot, and its whole history (executions, mentions, citations, sentiment, and any GEO Writer tasks created for this prompt) is purged by a background job. Never call this speculatively: only when the user explicitly asked to delete this specific prompt, and confirm the exact prompt text with them first. In the in-app chat the user gets a Confirm/Cancel card; external MCP clients delete immediately. Find prompt ids via list_prompts. All
create_intelligence_task Create a GEO Writer (formerly Content Intelligence) task. task_type selects what is produced: "brief" = content brief/outline for a topic, "create" = full draft article, "update" = rewrite/improve existing content (requires existing_content or existing_content_url), "pr_insights" = PR/media angle analysis, "custom" = freeform output driven by user_instructions. Pass prompt_id to base the task on an existing prompt, or omit it for agentic mode (then custom_topic or user_instructions is required). Returns task ID for polling status with get_intelligence_task. All
create_competitor Add a competitor to a project. Validates against the max competitor limit of the plan. Triggers async association recalculation: the competitor row returns processing=true immediately, and mentions/SOV/dashboards include it once the recalculation finishes (typically minutes, longer on large projects). competitors_remaining=null in the response means unlimited. All
update_competitor Update a competitor: brand_name, matching_names (the name variants used to detect mentions; REPLACES the whole list), and/or chart color. The domain is immutable after creation (delete and re-create to change it). Changing brand_name or matching_names re-runs mention/citation matching in the background: the competitor shows processing=true for a few minutes and edits are blocked meanwhile. Find competitor ids via list_competitors. All
delete_competitor Delete a competitor from a project (same as Delete on the Competitors page). IRREVERSIBLE: the competitor disappears immediately, frees a competitor slot, and its tracked data (mentions, citations, sentiment, share-of-voice history) is purged by a background job. Never call this speculatively: only when the user explicitly asked to remove this specific competitor, and confirm the brand with them first. In the in-app chat the user gets a Confirm/Cancel card; external MCP clients delete immediately. Find competitor ids via list_competitors. All
create_collection Create a tag (Collection) in a project. Optionally attach existing prompts in the same call. Tag name is unique per project (case-insensitive). All
update_collection Rename a tag/collection or change its description (tags and collections are the same object). Prompt membership is managed separately via assign_prompt_tags / remove_prompt_tags. Find tag ids via list_tags / list_collections. All
delete_collection Delete a tag/collection from a project (same as Delete on the Tags page; tags and collections are the same object). IRREVERSIBLE for the tag itself, but the prompts inside it are NOT deleted: only the grouping disappears. Never call this speculatively: only when the user explicitly asked to delete this specific tag, and confirm its name with them first. In the in-app chat the user gets a Confirm/Cancel card; external MCP clients delete immediately. Find tag ids via list_tags / list_collections. All
assign_prompt_tags Attach tags (collections) to existing prompts in bulk. BATCH your calls: pass ALL prompt_ids sharing the same tag set in ONE call (up to 500 prompt_ids and 50 tags per call); never call once per prompt. Provide tag_ids for known tags, or tag_names to look up by name (case-insensitive). Pass create_missing=true to create tag names that do not exist yet. Idempotent: re-running with the same input does not duplicate assignments. All
remove_prompt_tags Detach tags (collections) from existing prompts in bulk: the inverse of assign_prompt_tags, e.g. to undo a tagging mistake. BATCH your calls: pass ALL prompt_ids sharing the same tag set in ONE call (up to 500 prompt_ids and 50 tags per call). Only removes the prompt-tag links; never deletes the tags themselves or the prompts. Idempotent: links that do not exist are reported as skipped. All
list_annotations List the timeline annotations of a project (the markers shown on dashboard charts), newest first. Includes manual annotations, project automations, GEO test markers, and platform-wide events. The origin field distinguishes them; editable tells you whether update_annotation / delete_annotation can touch the row. Filter by date window (from/to or range) and annotation_category_id. Available on every plan. All
create_annotation Mark a date in the project timeseries with a title + description. Useful when the agent detects a notable change (campaign launch, product update, news event) and wants to flag it. Annotations are scoped to the project and visible to all members. All
update_annotation Update a timeline annotation (title, description, date, color, category). Only user-created annotations that belong to your own user can be updated (system annotations and other members annotations cannot; check the editable flag in list_annotations). Available on every plan. All
delete_annotation Delete a timeline annotation from a project. Only user-created annotations that belong to your own user can be deleted (system annotations and other members annotations cannot). Never call this speculatively: only when the user explicitly asked to delete this specific annotation. In the in-app chat the user gets a Confirm/Cancel card; external MCP clients delete immediately. Find annotation ids via list_annotations. Available on every plan. All
launch_recommendations Launch a new AI-powered recommendations generation for a project (same engine as the in-app Recommendations page). This is a REAL, quota-consuming action: it spends the project weekly recommendation-item budget (shared across all types, admins exempted) and runs a 1-3 minute background job. Never call it speculatively: only when the user explicitly asked to (re)generate recommendations, and after telling them it consumes the weekly budget. In the in-app chat the user gets a Confirm/Cancel card first; external MCP clients launch immediately, so get the user approval in YOUR conversation before calling. Track progress via get_recommendation / list_recommendations (status pending -> processing -> completed). All
create_technical_geo_report Run the full technical GEO analysis bundle (crawlability, schema, content readiness, discoverability, site structure, robots.txt, llms.txt, AI visibility) for a given URL + country. This is a REAL, quota-consuming action: it launches multiple scraping and AI analysis jobs (3-10 minutes, counts against a daily report cap per account). Never call it speculatively: only when the user explicitly asked for a technical GEO analysis, and tell them it consumes report quota. In the in-app chat the user gets a Confirm/Cancel card first; external MCP clients launch immediately, so get the user approval in YOUR conversation before calling. Finished reports appear on the Technical GEO page in the app and are emailed to the requesting user. All
list_intelligence_tasks List GEO Writer (formerly Content Intelligence) tasks for a project with optional filtering by type and status. All
get_intelligence_task Get a GEO Writer (formerly Content Intelligence) task by ID, including status and result data when completed. All
get_agent_traffic Get aggregated AI bot traffic for a project from Cloudflare or uploaded server logs. Returns per-day request counts grouped by bot or by company. Available on Scale and above plans. Scale
list_agent_bots List the catalog of known AI bots (crawlers, assistants, search fetchers) and their parent companies. Use this to discover valid bot slugs and company names for the bot/company filters of get_agent_traffic. Returns each bot's slug, display name, company, category, and description. Scale
get_ai_traffic AI traffic for a project: the human visits arriving from AI assistants (ChatGPT, Perplexity, Gemini, Claude, Copilot, Grok, Mistral, Meta AI, DeepSeek), measured from the connected web analytics provider (Google Analytics 4, Adobe Analytics, PostHog, Plausible or Piano). Returns per-day users, sessions and conversions grouped by AI source, plus totals and conversion rate. Requires a connected web analytics provider. Available on Scale and above plans. Scale
get_search_console_summary Google Search Console headline totals (impressions, clicks, CTR, average position) for a project over a date range. Pass dimension=country or dimension=device to also get the breakdown aggregated over the range (country values are lowercase ISO alpha-3 as returned by Google, e.g. usa, gbr, plus the zzz unknown-country sentinel). The response data_through field marks the last day with synced data: Google publishes with a 2-3 day lag, so later days are missing, not zero. Requires the project to have a Search Console connection. Growth
get_search_console_timeseries Google Search Console property-wide time series (impressions, clicks, CTR, average position) bucketed by day, week or month. The response data_through field marks the last day with synced data: Google publishes with a 2-3 day lag, so trailing days are missing rows, not real zero-drops. Requires the project to have a Search Console connection. Growth
get_search_console_queries Top Google Search Console search queries for a project over a date range, ranked by impressions, clicks, CTR or average position, with pagination. Knowingly undercounts anonymized queries; for exact headline numbers use get_search_console_summary. Requires a Search Console connection. Growth
get_search_console_pages Top Google Search Console landing pages for a project over a date range, ranked by impressions, clicks, CTR or average position, with pagination. For exact property totals use get_search_console_summary. Requires a Search Console connection. Growth
create_webhook_subscription Subscribe a public HTTPS URL to a project event. LLM Pulse will POST a signed JSON payload to the URL every time the event occurs (new mention, new citation, execution completed, negative sentiment detected, recommendation or intelligence task completed). Available on Scale and above plans. Deliveries are signed: the X-LLMPulse-Signature header carries sha256=<HMAC-SHA256 hex of the raw body> using the whsec_ secret returned ONCE by this call (store it; it is never shown again; rotating requires delete + recreate). X-LLMPulse-Event and X-LLMPulse-Delivery headers identify the event and delivery. Scale
create_project Create a complete project in one call (fast mode): project fields, prompts (queued for execution), competitors, weekly email subscription. Idempotent via external_identifier (embed accounts). Same plan gates and quotas as the in-app wizard. Use this fast mode when you already have every field; use start_project_draft for the step-by-step wizard with AI suggestions. All
update_project Update a project profile (same fields as Project Settings > General): brand_name, description, industry, business_model, target_audience, primary_products, brand_voice, goals and matching_names. matching_names REPLACES the whole list, so always send the full set including the ones already there (read them first with get_project_details). Changing matching_names re-runs mention/citation matching over the project history in the background, which can move visibility numbers for past weeks; a brand_name change applies to future runs only. Returns an error while a previous rematch is still running. The project name, website URL, country/language, app-store and social profiles are NOT editable here: those stay in Project Settings. In the in-app chat the user gets a Confirm/Cancel card. All
start_project_draft Start the multi-step project-creation wizard. Returns a draft_id plus AI suggestions (name, description, industry, aliases) for the URL. First call for a new URL may take up to 2 minutes; pass suggest=false to skip AI. Drafts expire after 24h and there is no list endpoint, so STORE the draft_id; a lost id means waiting for expiry. Use this wizard when you want AI suggestions step by step; use create_project instead when you already have all fields and want one call. All
get_project_draft Read a project draft: state, current step, accumulated data. include_suggestions returns cached suggestions for the current step (never triggers AI). All
update_project_draft Submit one wizard step (details, prompts, competitors, owned_media). Strict forward gating: a step is only accepted when every previous step is complete; completed steps can be resubmitted. Returns the updated draft plus AI suggestions for the next step (suggest=false to skip). Per-step required fields beyond draft_id+step: details requires name (industry optional but validated); prompts requires a non-empty prompts array of strings within your plan slots; competitors requires an array of {domain, brand_name?, matching_names?} with valid domains within plan limits; owned_media accepts its documented keys. All
finalize_project_draft Create the real project from a completed draft (same effects as create_project). Idempotent: finalizing an already-finalized draft returns the existing project. Re-validates every plan gate and quota. All
list_webhook_subscriptions List active webhook subscriptions for the account, optionally filtered by project. Available on Scale and above plans. Scale
delete_webhook_subscription Delete a webhook subscription by ID. The target URL stops receiving events immediately. Available on Scale and above plans. Scale
get_webhook_sample Get sample webhook payloads for an event type, built from the project's most recent real data (or a static sample when no data exists). Use this to preview the exact payload shape before creating a webhook subscription with create_webhook_subscription. Available on Scale and above plans. Scale
send_feedback Send feedback about LLM Pulse to the product team: a bug report, a feature request, or general product feedback. Use it when the user wants to report a problem or suggest an improvement, or when a tool clearly misbehaved. This channel is one-way (no reply); for questions about how the product works use ask_support instead. All
ask_support Ask the LLM Pulse support assistant a question about the product: features, plans, metric definitions, setup, or API usage. Answers come from the official LLM Pulse knowledge base. Use send_feedback instead to report a bug or request a feature; email support@llmpulse.ai for account-specific issues (billing, invoices). All

Protocol

MCP uses JSON-RPC 2.0 over Streamable HTTP. Requests return a JSON-RPC response. Accepted notifications return HTTP 202 with an empty body.

For a simpler guide, see the MCP Setup page.

OAuth 2.1 (ChatGPT Apps SDK, MCP clients)

OAuth 2.1 authorization server with PKCE-S256, Dynamic Client Registration (RFC 7591), and discovery metadata (RFC 8414 + RFC 9728). Used by ChatGPT Apps SDK and any other MCP client that supports OAuth. Available to all plans for the MCP resource at /api/v1/mcp. RS256-signed JWT access tokens and the reusable refresh token share a fixed one-year authorization deadline.

OAuth 2.1 Overview

Use OAuth 2.1 when your client needs per-user delegated access to the MCP endpoint and you cannot ship an API key (e.g., a multi-tenant AI assistant). Use API keys when you control both ends and want a simpler integration (Scale plan and above). MCP via OAuth is available on every plan including the free trial.

Endpoints: /oauth/authorize, /oauth/token, /oauth/register, /oauth/jwks.json, /.well-known/oauth-authorization-server, /.well-known/oauth-protected-resource.

GET/.well-known/oauth-authorization-server

Authorization-server metadata at /.well-known/oauth-authorization-server (RFC 8414) and protected-resource metadata at /.well-known/oauth-protected-resource (RFC 9728). The JWKS used to verify access-token signatures lives at /oauth/jwks.json. Clients should fetch these to discover the authorize, token, and registration endpoints, never hard-code them.

No parameters. Returns JSON with issuer, authorization_endpoint, token_endpoint, registration_endpoint, jwks_uri, scopes_supported, code_challenge_methods_supported, and related metadata.

POST/oauth/register

Dynamic Client Registration per RFC 7591. Unauthenticated and rate-limited to 5/hour per IP. Only RFC 7591 fields are persisted (extra fields are dropped). Redirect URIs must be HTTPS (any host) or HTTP loopback (localhost / 127.0.0.1); custom schemes like javascript:, data:, file: are rejected. Maximum 10 redirect URIs per client; client_name capped at 200 chars; URIs capped at 2048 chars.

JSON body: redirect_uris (required array), client_name, grant_types (defaults to authorization_code refresh_token), token_endpoint_auth_method (none for public PKCE clients, client_secret_post for confidential), scope.

GET/oauth/authorize

Renders an in-app consent screen. On approval, redirects the user back to redirect_uri with a single-use code (10-minute TTL) and the original state. PKCE-S256 is mandatory; plain challenges are rejected.

Params: response_type=code (required), client_id (required), redirect_uri (required, must match a registered URI exactly), code_challenge (required), code_challenge_method=S256 (required), scope (space-separated: mcp:read mcp:write), state, resource (RFC 8707 resource indicator).

POST/oauth/token

Exchanges an authorization code for an access token + refresh token, or refreshes an access token. Uses application/x-www-form-urlencoded. Rate-limited to 60/minute per IP. Refresh responses return the same reusable refresh token, and all credentials expire at the fixed one-year authorization deadline.

Body: grant_type (authorization_code or refresh_token), client_id (required), client_secret (required for confidential clients), and either {code, code_verifier, redirect_uri} OR {refresh_token, optional scope for downscoping}.

Scopes & Audience Verification

Two scopes are defined. mcp:read grants access to every read tool (list_*, get_*). mcp:write additionally grants the write tools (create_prompts, create_competitor, create_collection, assign_prompt_tags, create_annotation, create_intelligence_task, launch_recommendations, create_technical_geo_report). A token issued with only mcp:read cannot invoke write tools, both tools/list hides them and direct tools/call returns an error. The JWT aud claim must equal the resource server URL; tokens with a different audience are rejected at /api/v1/mcp.

When refreshing a token, you MAY pass a narrower scope, anything broader than the original grant returns invalid_grant.

Changelog

The three most recent API changes. The full history lives on its own page.

  • 2026-08: Native Rust CLI and official SDKs. CLI v2 replaces the JavaScript implementation with native binaries for macOS, Linux and Windows while preserving the existing configuration and profile format. Typed commands cover all 71 REST operations, with JSON, table and CSV output plus a direct REST command. Official generated clients are now maintained for TypeScript, Python, Go, Java, Kotlin, C#, PHP, Ruby, Rust, Swift, Dart and R. The OpenAPI document uses OpenAPI 3.0-compatible nullable fields so every client can be generated with the same pinned toolchain.
  • 2026-08: Automatic annotations and all-plan access (v1.23.0). Annotations are now available on every plan, including Starter and trial accounts. Rows returned by GET /annotations and the MCP list_annotations tool include origin: manual, automation, geo_test, or platform. Automatic project annotations record daily prompt-set changes, enabled AI model changes, and tracking frequency changes. Existing fields and write behavior are unchanged.
  • 2026-08: Share of Voice sample sizes and per-model grouping (v1.22.0). GET /metrics/sov now returns a periods array with, per bucket, the total mentions the shares were computed on (the sample size: a bucket with 1-3 mentions reads as 100/50/33.33 and should be treated as low-sample) and a partial flag marking buckets still collecting data or clipped by the requested window. Each current row also carries precomputed deltas: previous_share (last complete bucket) and avg_share (mean over complete buckets with data; partial buckets excluded). Existing fields are unchanged. The MCP get_sov tool gains group_by=model returning one compact per-model share comparison per call (add include_series=true for per-model trend series), every project-scoped MCP tool now accepts the project domain or exact name/brand name in project_id besides the numeric id, MCP metric responses include an app_url source link, and MCP metric tools render interactive widgets in hosts that support them: share-of-voice donut, visibility summary card, metric-over-time line chart (get_timeseries) and top cited domains (get_top_sources).

View the full API changelog