Contents

API reference

Every endpoint, field and response of the export API. Generated from openapi.yaml (OpenAPI 3.1, also as JSON).

  • Base URL: https://global-api.attentionpanel.com
  • Auth: Authorization: <api key> on every request, no scheme prefix.
  • Body: JSON in and out. Unknown request fields are rejected.
  • Errors: { "statusCode": 400, "message": "FROM_DATE_NOT_ALLOWED" }. The message is the code to branch on.
  • Two ways to export: the change feed for mobile v2 (feed: true for the first pull, then since with the last next_cursor), which keeps a copy of the export current; and the day export (from_date, to_date) for one-off pulls and desktop. Integration →
  • Cursors: treat next_cursor as an opaque string and pass it back unchanged. It does not expire.

Versions

The mobile export has two versions. Desktop has none: leave version out.

Version Days Status
v2 From 13 March 2026 in Sweden and Denmark, 26 March in Norway and 19 May in Finland The current export, and the only one with the change feed.
v1 Up to 11 November 2026 The legacy export, no longer updated. Moving from the legacy mobile export →
  • Send version on every mobile request. A version in the request always applies.
  • Without it, a request gets the version set for your key: v2, unless your key was set up on the legacy export. A change-feed pull is always v2.
  • Outside a version's days: a from_date before 13 March 2026 with v2 is a 400 V2_FROM_DATE_NOT_AVAILABLE, with the first day in available_from. A to_date after 11 November 2026 with v1 is a 400 V1_NOT_AVAILABLE_AFTER, with the last day in available_to.
  • Every job states its version: version in Get an export.

Create an export

POST /impressions/export

Starts an export job for one platform and market: a day export over an inclusive range of UTC dates (from_date, to_date), or, for mobile v2, the change feed. A feed starts with a first pull (feed: true), which returns every current impression and a cursor; each later pull passes the last cursor (since) and returns every impression added, changed or removed since. Upsert the rows on impression_id and treat removed: true as retired.

Request body

FieldTypeDescription
devicestring · requiredThe platform. One of mobile, desktop.
marketstring · requiredThe market. One of semarket, nomarket, dkmarket, fimarket.
from_datedateDay export: YYYY-MM-DD, inclusive. Not before the key's earliest allowed date.
to_datedateDay export: YYYY-MM-DD, inclusive. Not before from_date.
include_html_metadatabooleanDesktop only. Adds html_metadata when the key is entitled to it.
versionstringMobile only. The mobile data version. When omitted: the version set for the key, else v2; a feed pull is always v2. v2 data starts on a date set per deployment: an earlier from_date returns 400 V2_FROM_DATE_NOT_AVAILABLE with that date in available_from. Mobile v1 data ends on 2026-11-11: a later to_date returns 400 V1_NOT_AVAILABLE_AFTER with that date in available_to. One of v1, v2.
feedbooleanChange feed, mobile v2: the first pull. Returns every current impression from the key's earliest allowed date, and a cursor. Always true.
sincestringChange feed, mobile v2: the next_cursor of the last pull. Returns every impression added, changed or removed since. A cursor does not expire.

Response 200

FieldTypeDescription
export_idstring · requiredUse in the other endpoints. URL-encode it in paths.
statusstring · requiredAlways RUNNING.
versionstringThe data version the job exports. One of v1, v2.

Errors

Status · messageCause
400 (validation message)Missing or unknown field, bad date, from_date after to_date, or neither dates nor feed or since.
400 FROM_DATE_NOT_ALLOWEDfrom_date is before the key's earliest allowed date.
400 MAX_PARALLEL_RUNS_LIMIT_REACHEDThe key already has its maximum number of running jobs for this platform, market and version.
400 V2_FROM_DATE_NOT_AVAILABLEversion v2 with from_date before the first day of v2 data, which available_from gives (YYYY-MM-DD).
400 V1_NOT_AVAILABLE_AFTERMobile version v1 with to_date after the last day of v1 data, which available_to gives (YYYY-MM-DD); v1 is no longer built. Request v2 for later days. action says the same.
400 V2_ONLY_AVAILABLE_FOR_MOBILEversion v2 with a device other than mobile.
400 FEED_TAKES_NO_DATESfeed or since together with from_date or to_date.
400 FEED_OR_SINCEBoth feed and since: a pull is either the first one or one since a cursor.
400 FEED_MUST_BE_TRUEfeed other than true.
400 FEED_ONLY_AVAILABLE_FOR_MOBILEfeed or since with a device other than mobile.
400 FEED_ONLY_AVAILABLE_FOR_V2feed or since with a version other than v2.
400 CURSOR_INVALIDsince is not a cursor this API returned.
400 CURSOR_GAPChanges after since were lost on our side. Start a new feed with feed: true; impressions you hold that are not in it are retired. action says the same.
401No Authorization header.
403Invalid key, or platform or market outside its entitlements.
500 EXPORT_VERSION_MISCONFIGUREDThe default export version set for the key is not valid, and we have been alerted. A request that names its version is not affected.

Get an export

GET /exports/{export_id}

Returns the job's state, and the files once it has succeeded.

Response 200

FieldTypeDescription
statusstring · requiredOnly RUNNING changes. One of RUNNING, SUCCEEDED, FAILED, CANCELLED.
versionstringThe data version the job exports. One of v1, v2.
download_urlsstring[]On SUCCEEDED. Presigned, one archive per calendar month in the range (for a feed pull, per month of the impressions it returns; none when nothing changed), named <export_id>_<year>_<month>.tar.gz and holding a day=DD/ folder of gzipped JSON Lines per day. Valid 24 hours after completion. Send no Authorization header to them.
failure_reasonstringOn FAILED: NO_DATA (no rows for the request), CURSOR_INVALID or CURSOR_GAP (as the 400 codes of a feed request, found while the job ran), or INTERNAL_ERROR. One of NO_DATA, INTERNAL_ERROR, CURSOR_INVALID, CURSOR_GAP.
next_cursorstringOn SUCCEEDED, for a change-feed pull: pass it as since in the next pull.

Errors

Status · messageCause
400 EXPORT_EXPIREDThe download URLs are older than 24 hours. Create a new export.
404Unknown export_id, or one created with another key.

Cancel an export

POST /exports/{export_id}/cancel

Stops a running job.

Response 200

FieldTypeDescription
export_idstring · requiredThe cancelled job.
statusstring · requiredAlways CANCELLED.

Errors

Status · messageCause
400 EXPORT_NOT_IN_CANCELABLE_STATEThe job is no longer running.
404Unknown export_id, or one created with another key.