Skip to main content
GET
One read-only endpoint returns a bare list of metric rows for one publisher. With a publisher key that is the key’s own publisher; with an organization key you choose it with publisher_id. Money is US dollars (floats): revenue, ecpm, and cpc (e.g. 5.0 = $5.00); ctr is a fraction (0.01 = 1%). revenue is your net share. How revenue accrues depends on your account’s payment model, configured by Thrad: CPM accounts (the default) earn a share of advertiser spend on viewable (confirmed on-screen) impressions; CPC accounts earn a fixed per-click rate × your revenue share on measured clicks. Clicks are measured on DSP-linked impressions, so CPC revenue is always consistent with the clicks metric shown.

Authorizations

string
required
One of two keys. Authorization: Bearer <key> is accepted as an alternative. A missing key returns 401 auth_required; an unknown, expired, or revoked key returns 401 invalid_api_key.
  • Publisher key (sk_...) — the same key you use to serve ads. It reads only its own publisher. Find it in the dashboard under Publisher → Configuration → Keys.
  • Organization key (sko_...) — one key for your whole organization that reads any of its publishers; name the one you want with publisher_id. An organization owner or admin creates, rotates, and revokes it under Settings → API key. It is read-only and can’t serve ads. Rotating keeps the old key working for a short grace window (30 minutes by default) so you can switch over; revoking stops it immediately. The full key is shown once, when it is created.

Choosing a publisher

string
The id of the publisher to read (a UUID — list yours with GET /v1/publisher/publishers).
  • Organization key: required. Without it you get 400 missing_required_parameter. A publisher outside your organization, or one that was deleted, returns 404 not_found.
  • Publisher key: optional. When sent, it must be the key’s own publisher; any other id returns 404 not_found.
A value that isn’t a UUID returns 400 invalid_value.

Query parameters

Repeated parameters use the name[] convention (e.g. fields[]=impressions&fields[]=revenue).
string
default:"daily"
How rows are bucketed over time: hourly, daily (default), monthly, or none. With none a single row covers the whole requested range and has no readable_time. Any other value returns invalid_value. Not applicable in breakdown mode (see segments[]).
array
One or more JSON window objects; each may span at most 366 days (range_too_wide). When omitted, a trailing 30-day window is used.
end must be after start (invalid_time_range). With time_granularity=hourly, each window must be 25 hours or less (hourly_range_too_wide).
array
Which metrics to project onto each row: impressions, clicks, revenue, ctr, ecpm, cpc, fill_nominal, fill_real, fill_requests, fill_rate, nominal_fill_rate. Defaults to impressions, clicks, revenue (fill metrics are opt-in — the default response is unchanged). An unknown metric returns unknown_field.
array
Roll the whole range up by one dimension — country, intent, or device — returning one row per value (ordered by impressions). At most one (too_many_segments); an unrecognized value returns invalid_segment.
A breakdown spans the whole range, so it can’t be combined with an explicit time_granularity (segment_time_conflict). On breakdown rows, clicks, ctr, and cpc are populated for CPC-model accounts (per-dimension revenue rides those clicks) and null for CPM-model accounts (clicks aren’t broken out per dimension there). Fill metrics are always null on breakdown rows.
array
One or more JSON { "field", "direction" } objects, applied in order. field is a metric; direction is asc or desc. A non-metric field or bad direction returns invalid_value. Row id is always the final deterministic tiebreak.
integer
default:"20"
Maximum rows in the page, 1–2000 (default 20). Out of range returns invalid_value.
string
Cursor for the previous page — pass a prior response’s first_id. Mutually exclusive with after (invalid_cursor if both). An unknown cursor returns invalid_cursor.
string
Cursor for the next page — pass a prior response’s last_id. Mutually exclusive with before.
The advertiser-only parameters aggregation_level, source, and filters[] are not supported here and return 400 unsupported_parameter — they are never silently ignored.

Response

The endpoint returns a bare list object — not the platform { success, data, error, meta } envelope.
string
Always "list".
array
The metric rows for this page. Each row is a flat object.
integer
Number of rows in data on this page.
string
Id of the first row — pass as before for the previous page. null for an empty page.
string
Id of the last row — pass as after for the next page. null for an empty page.
boolean
true if more rows exist beyond this page.

Errors

Errors use the bare OpenAI shape — { "error": { "message", "type", "param", "code" } }. type is one of invalid_request_error, authentication_error, rate_limit_error, or server_error.