AI Visibility API
Export published AI Visibility metrics for a project and one page of the monitored answers behind them. Use it to report brand visibility, compare periods and inspect saved answer/citation evidence. This endpoint does not generate new AI answers or export Claims Trends.
Create with POST https://app.wheremore.com/api/v2/exports/visibility . Retrieve with GET https://app.wheremore.com/api/v2/exports/{export_id} . This guide describes default data contract 2026-09-19 . See API Access and API Keys for credentials and the shared export lifecycle.
Select the scope
Copy the public workspace ID from API Access → Your Workspaces and Markets. Supply the numeric project ID. Optionally supply config_id to select a persona configuration within that project. Obtain these IDs from your Wheremore configuration or workspace administrator; this export API does not provide a project/persona listing endpoint.
Metrics describe the complete selected date/persona/platform/phase/depth scope. Answer pagination affects the evidence returned and its billing, not the scope of those metrics.
Request fields
| Field | Required | Accepted value |
|---|---|---|
workspace_id |
Yes | Public ws_... ID. |
project_id |
Yes | Positive project ID belonging to that workspace. |
date_from , date_to |
Yes | Inclusive UTC YYYY-MM-DD dates; 1–366 days, no future end date. |
config_id |
No | Positive persona configuration ID within the project. Omit for the project scope. |
platform |
No | all (default) or a supported provider key below. |
phase |
No | all (default), awareness , consideration or decision . |
provider_depth |
No | any (default), top1 or top3 . |
page |
No | Positive answer-page number, default 1, maximum 10,000. |
limit |
No | Answers per page, 1–100; default 50. |
data_contract |
No | 2026-09-19 (default) or 2026-09-10 . |
callback_url |
No | Public HTTPS readiness callback. |
Supported platform keys are chatgpt , chatgpt-web , chatgpt-adaptive , claude , claude-web , claude-adaptive , gemini , gemini-web , gemini-adaptive , perplexity , perplexity-web , perplexity-adaptive and google-ai-mode . Search-enabled and non-search variants are distinct identifiers.
Unknown fields are rejected. The old config_name selector is not supported; config_id alone no longer replaces the required project_id and dates.
Create and retrieve the export
Replace the example IDs and dates. WHEREMORE_API_KEY must already be set securely.
curl --fail-with-body -X POST \
"https://app.wheremore.com/api/v2/exports/visibility" \
-H "X-API-Key: ${WHEREMORE_API_KEY}" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: visibility-report-20260919-001" \
-d '{
"workspace_id": "ws_your_workspace_id",
"project_id": 123,
"config_id": 42,
"date_from": "2026-09-01",
"date_to": "2026-09-18",
"platform": "all",
"phase": "all",
"provider_depth": "top3",
"page": 1,
"limit": 50,
"data_contract": "2026-09-19"
}'
Save the returned export.id . POST returns 201 when ready or 202 when pending; neither charges credits or returns the report. Retrieve it using:
curl --fail-with-body \
"https://app.wheremore.com/api/v2/exports/exp_0123456789abcdef0123456789abcdef" \
-H "X-API-Key: ${WHEREMORE_API_KEY}"
A pending GET returns 202. A ready GET returns 200 with the frozen data . Retry the same POST with its original idempotency key; use a new key for another page or report.
Returned report
Field inside data |
Meaning |
|---|---|
data_contract , workspace_id |
API response format and public workspace ID. |
snapshot |
Reader/metric versions, status, updating/error indicators, pending/failed slices, coverage dates and generation information. |
filters |
Effective project, workspace, persona, platform, phase, depth and dates. |
sections |
kpis , shareOfVoice , customerJourney , sentiment , citationRate and conversationVisibility . |
responses |
Answer rows, counts, billing-unit count and page metadata. |
consistency |
Statement that metrics and this response page were read in one consistent database snapshot. |
definitions |
Interpretation notes for populations, missing evidence, citations and pagination. |
Response filter names follow the shared reader: persona selection is reflected in config_filter ; phases can appear as phase_filter: "phase1" , "phase2" or "phase3" , corresponding to awareness, consideration and decision. Use the public request values when making subsequent requests rather than copying the response filter object verbatim.
The six KPI entries in sections.kpis.metrics cover Brand Visibility, Share of Voice, Top Recommendation Rate, Cited Answer Rate, Owned Website Evidence and Third-party Evidence. Preserve the returned current/comparison values, units, setup flags and comparison warnings. Different monitored populations can make a period comparison less reliable even where both periods contain observations.
This export includes those six sections; other dashboard panels, saved analysis reports and Claims inventory/verification results are outside its response.
Answer evidence
Each item in responses.answers includes:
| Field or group | Meaning |
|---|---|
observation_id , run_id , config_id , query_id |
Stored observation, run, persona and monitored-question identifiers. |
platform_key , phase_key , observed_at |
Provider, stored phase and observation time. |
question , answer_text , text_available |
Question and available full answer text. Missing text is identified explicitly. |
brand_matches_selected_depth |
Whether an own-brand mention meets the chosen rank depth. |
brands |
Stored brand keys/names/roles, minimum ranks and sentiment keys. |
citations |
Citation ID, title, URL, rank and scope. An unavailable/unsupported URL can be null. |
web_sources |
Separate web-search sources, each with title and URL. |
An illustrative pagination fragment is:
{
"total_answers": 75,
"returned_answers": 50,
"billable_conversations": 20,
"pagination": {"page": 1, "limit": 50, "has_more": true}
}
These counts belong inside responses . Fifty answer rows can represent fewer than fifty conversation/persona pairs because different platforms or observations can relate to the same monitored question.
Depth, missing data and interpretation
top1 and top3 describe the rank of stored provider mentions, not the number of answers to return. Answers without a qualifying own-brand mention remain in the evaluated denominator and the evidence page; brand_matches_selected_depth annotates the match. Missing or unprocessed answers are not evaluated zero-visibility answers.
Read snapshot.status , isUpdating , hasProjectionErrors and coverage metadata. A ready export can contain the last available committed reporting data while processing continues. Before the first usable publication, an export can remain pending. A published selection with no answer rows can return an empty, free first page.
A citation, brand mention or recommendation does not establish truth, endorsement, a purchase or commercial impact. Answer citations and web-search sources are separate evidence. Escape all question/answer text when displaying it and handle null URLs.
Pagination and charges
If responses.pagination.has_more is true, create a new export using the same filters and limit with page increased by one. Give that POST a new idempotency key. A page beyond the selected answer population is rejected, except that page 1 can represent an empty selection.
Each page is a separate snapshot. Source data can change between page requests, so pages are not a frozen dataset-wide cursor and can overlap or shift. Store observation IDs to recognize repeated evidence; do not assume all pages share one publication.
The first successful GET costs 0.5 credits per distinct (config_id, query_id) pair on that page, shown as responses.billable_conversations . In the example fragment, the charge is 10 credits. Multiple answers for one pair on the same page count once; the same pair on another export page is billable again. Full-scope metrics are not charged as additional units.
Repeat GETs of the same paid export are free and return identical data. An answer-empty export has zero billable units. Exports expire seven days after creation. The 8 MiB payload cap still applies; long answers may require a smaller limit or narrower scope.
Troubleshooting
- 400: check required project/dates, exact filter identifiers, page bounds and obsolete fields.
- 403 after a successful earlier retrieval: workspace/project access may have changed, or the selected persona may have moved or been removed. Saved data does not override current permissions.
- 503: a required published reader or permission service may be unavailable. Retain the request ID for support.
- Brand-setup flags: configure the project's own brands and, where required, brand websites before interpreting those metrics.
- Page contains answers without your brand: expected; they remain part of the evaluated denominator.
- 413: reduce
limit, dates, platform or persona scope, then create a new export. - Data does not change on GET: the export is immutable; create another report for a later publication.
Use API Access and API Keys for key errors, insufficient credits, callbacks and retention.