Skip to main content
GET
Get score series

Authorizations

Authorization
string
header
required

A Surfais API key — an organisation key or a partner key. Issued by Surfais; shown once. Rotate by creating a new key, then revoking the old one.

Path Parameters

orgId
string<uuid>
required

Organisation id. Org keys: the key's own org. Partner keys: any org with an active link. Anything else is 404.

Pattern: ^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$
brandId
string<uuid>
required

Brand id within the org (own brand or competitor row); 404 when not in the org. Writes that add tracking need an own (400 validation_error with details[].code = "own_brand_only"), non-archived (409 brand_archived) brand.

Pattern: ^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$

Query Parameters

limit
integer
default:50

Page size (1–200). Default 50.

Required range: 1 <= x <= 200
cursor
string

Opaque cursor from a previous page's pagination.next_cursor. It pins the walk — its sort anchor, the resolved date window and the FILTERS the first page ran under — so continue with the cursor alone: omitted filters are restored from it. Naming a different value for one of them is 400 invalid_cursor (details.reason = "filter_changed", details.parameter the one that differs); start again from the first page to change a filter.

Maximum string length: 2048
from
string<date>

Window start (inclusive). Default: to minus 30 days.

Pattern: ^\d{4}-\d{2}-\d{2}$
to
string<date>

Window end (inclusive). Default: today (UTC). Max span 366 days; from after to is 400 validation_error. On a paginated endpoint the resolved window is pinned by the first page and carried in the cursor — continue with the cursor alone; naming a different from/to on a continuation is 400 invalid_cursor (details.reason = "window_changed").

Pattern: ^\d{4}-\d{2}-\d{2}$
platform
enum<string>

Omit for the all-platform aggregate series (the AIS Score; with country, the market's all-platform visibility_index); set for one platform's series (its composite score; with country, that platform's visibility_index in the market).

Available options:
perplexity,
chatgpt,
gemini,
claude,
ai_overviews
country
string

Per-market series: data items are CountryScorePoint (score = visibility_index, score_kind = visibility_index) instead of ScorePoint. Must be a market Surfais scans (400 validation_error, details[].code = "unsupported_country" otherwise); a supported market with no rows is an empty series. Own brands only (400 validation_error with details[].code = "own_brand_only" for a competitor id). Bound into that series' cursor: continue with the cursor alone and the market is restored, and naming a different one is 400 invalid_cursor with details.reason = "filter_changed".

Pattern: ^[A-Za-z]{2}$

Response

Score points — ScorePoint items, or CountryScorePoint items when country is set.

data
object[]
required
pagination
object
required