CTV integration

Connected TV runs the same two-key model as the web: a delivery report, a device confirmation, a match, and a claim — except the claim usually happens on the viewer's phone. There are three integration paths, depending on how your app is built.

Path 1 — Web-based apps (works today)

If your TV app is HTML5/JavaScript (the common case on smart-TV and streaming-stick platforms), the integration is the publisher integration, unchanged: include the tag, call trackVideo() with your completion threshold, and the tag reports delivery plus a completion_confirm carrying completion_pct and view_duration_ms. Give the slot a name containing ctv (for example slot: "ctv-preroll") so verified views are treated as CTV pairs for phone notifications. The earn mark can render on the TV UI as well, but the phone claim below is the primary surface.

Path 2 — Ad-server beacons, server-to-server (works today)

Native apps and SSAI setups report through the ad server instead. Both keys are plain posts to the same ingest endpoint — no session required:

POST https://api.myadrewards.com/v1/events

{ "v": 1, "event_type": "delivery_report", "source": "publisher",
  "publisher_id": "pub_123", "app_id": "ctv_app_1",
  "identity_token": "…the screen's server-minted token…",
  "creative_id": "adv_42:cre_7", "campaign_id": "cmp_9",
  "slot": "ctv-preroll", "nonce": "…16 hex, one per break…",
  "ts": "2026-09-27T20:00:00Z" }

{ "v": 1, "event_type": "completion_confirm", "source": "device",
  "publisher_id": "pub_123", "app_id": "ctv_app_1",
  "identity_token": "…same token…", "nonce": "…same nonce…",
  "completion_pct": 100, "view_duration_ms": 30000,
  "ts": "2026-09-27T20:00:30Z" }

The binding rules are the same as the web: both halves must carry the same nonce, publisher_id, and identity_token, and arrive within the 10-minute match window; timestamps are rejected if older than 24 hours or more than 5 minutes in the future. The field table in the publisher guide, §4 applies as-is.

Device binding. The identity_token is what ties the break to a household screen. For a screen to earn, its token must be server-minted — issued by the API for the viewer's account and that screen (see API reference) — and the screen must be paired to the account, next section. A self-generated token still lets you report and measure, but the screen is not registered, so no claim notification is created.

Roadmap

Native CTV SDKs (Android TV, tvOS, Roku, Fire TV) and a formal standalone CTV specification document are on the roadmap. Today, web-based apps use the JavaScript tag and native apps use the beacon path above — both are fully supported by the ingest API as documented here.

Pairing a screen to an account

Viewers link a TV to their account with a short code, from the wallet:

  1. 1

    The wallet mints a code (signed in): POST /v1/identity/pairing-codes → 201 { "code": "XXXX-XXXX" }. Codes are 8 characters from an unambiguous alphabet, live 10 minutes, and are single-use.

  2. 2

    The TV confirms the code the viewer types in (no session — the code itself is the capability): POST /v1/identity/pairing/confirm with { "code": "…", "device_id": "…", "label": "Living room TV", "kind": "ctv" }. The response is the registered screen: { device_id, user_id, label, kind, registered_at, revoked }.

  3. 3

    Manage screens in the wallet: list paired screens, revoke any of them. Re-confirming the same screen on the same account is idempotent; a screen already linked to a different account is refused.

The phone claim

When a CTV pair verifies on a registered screen, the viewer's wallet gets a claim notification. Notifications are created only for CTV pairs (a completion_confirm, or a slot containing ctv) on registered devices:

GET /v1/notifications            (wallet session)

{ "notifications": [
    { "id": "…", "nonce": "…", "points": 25, "status": "claimable",
      "created_at": "…", "expires_at": "…" } ],
  "total": 1 }

Tapping one claims it — POST /v1/claims/impressions/{nonce} with the wallet session — and the points land in the same wallet as every other surface. Outcomes: 200 claimed · 404 unknown view · 403 not the viewer's · 409 already claimed · 410 claim window closed · 402 funding couldn't cover it.

Unregistered TVs

Nothing changes for the viewer. Ads play exactly as before, no badge or prompt appears on the TV, no notification is created, and no reward accrues. Registration is what turns a screen into an earning screen — measurement via the beacon path works either way, but earning starts at pairing.