Player Events v2 (ODK)
Dedicated ODK routes. Path is the service identifier; the server stamps s=odk on every event regardless of what the client sends. Send s=odk, did, osdid, and mci (vod/shorts/short_drama) or ch (live/multiview) on all three events. No Continue Watching side effects.
First rendered frame
Once per ss, when the first video frame renders. A playlist without a matching firstplay is the drop-out (or Shorts swipe-away) signal. Carry did, osdid and mci or ch so the event is attributable on its own, without a join to playlist.
Validation: only missing required parameters return 422. All other parameters are stored as strings exactly as sent (types below are guidance). Undeclared query parameters are stored as well. Data-quality checks happen in the warehouse.
query Parameters
ssStream session id issued by the server in the playlist response. Missing = 422; any present value (even empty) is stored.
Stream session id issued by the server in the playlist response. Missing = 422; any present value (even empty) is stored.
dtClient send time, epoch milliseconds. Example: 1756971928000
Client send time, epoch milliseconds. Example: 1756971928000
sSend odk. The server overwrites this with odk whatever is sent.
Send odk. The server overwrites this with odk whatever is sent.
didClient-generated persistent device id: in an app, stable across app restarts and app updates; on web, a first-party UUID in localStorage with a cookie fallback. Send on every event, and send the same value on player events and telemetry — it is the join key between the two surfaces, so two separately minted UUIDs break the join silently. (Audience counting lives on the telemetry surface, not on player events.)
Client-generated persistent device id: in an app, stable across app restarts and app updates; on web, a first-party UUID in localStorage with a cookie fallback. Send on every event, and send the same value on player events and telemetry — it is the join key between the two surfaces, so two separately minted UUIDs break the join silently. (Audience counting lives on the telemetry surface, not on player events.)
osdidOS advertising identifier, raw, one kind per platform: idfa (ios/tvos), gaid (android/androidtv), rida (roku), afai (firetv), tifa (tizen), lgudid (webos), vida (vizio). Not applicable on web. Send the OS value as-is, never suppress; the pipeline honours islat.
OS advertising identifier, raw, one kind per platform: idfa (ios/tvos), gaid (android/androidtv), rida (roku), afai (firetv), tifa (tizen), lgudid (webos), vida (vizio). Not applicable on web. Send the OS value as-is, never suppress; the pipeline honours islat.
mciMediahub content id. Required by the ODK contract when st is vod, shorts or short_drama.
Mediahub content id. Required by the ODK contract when st is vod, shorts or short_drama.
chChannel slug. Required by the ODK contract when st is live or multiview.
Channel slug. Required by the ODK contract when st is live or multiview.
First rendered frame › Responses
Event accepted. Echoes ss.
stream_session_idServer-issued stream session id (ss). Carry it on firstplay and viewhour of the same session.
Start a playback session
Call once per playback session, before the CSAI preroll. The server issues stream_session_id (ss); carry it on every firstplay and viewhour of the same session. A client-sent ss is ignored.
Shorts and Short Drama: one clip or episode = one session, so a new playlist on every swipe or episode change.
The server stamps s=odk and records the client IP and receive time. Events land in raw_odkr_*.
Validation: only missing required parameters return 422. All other parameters are stored as strings exactly as sent (types below are guidance). Undeclared query parameters are stored as well. Data-quality checks happen in the warehouse.
query Parameters
dtClient send time, epoch milliseconds. Example: 1756971928000
Client send time, epoch milliseconds. Example: 1756971928000
sSend odk. The server overwrites this with odk whatever is sent.
Send odk. The server overwrites this with odk whatever is sent.
didClient-generated persistent device id: in an app, stable across app restarts and app updates; on web, a first-party UUID in localStorage with a cookie fallback. Send on every event, and send the same value on player events and telemetry — it is the join key between the two surfaces, so two separately minted UUIDs break the join silently. (Audience counting lives on the telemetry surface, not on player events.)
Client-generated persistent device id: in an app, stable across app restarts and app updates; on web, a first-party UUID in localStorage with a cookie fallback. Send on every event, and send the same value on player events and telemetry — it is the join key between the two surfaces, so two separately minted UUIDs break the join silently. (Audience counting lives on the telemetry surface, not on player events.)
osdidOS advertising identifier, raw, one kind per platform: idfa (ios/tvos), gaid (android/androidtv), rida (roku), afai (firetv), tifa (tizen), lgudid (webos), vida (vizio). Not applicable on web. Send the OS value as-is, never suppress; the pipeline honours islat.
OS advertising identifier, raw, one kind per platform: idfa (ios/tvos), gaid (android/androidtv), rida (roku), afai (firetv), tifa (tizen), lgudid (webos), vida (vizio). Not applicable on web. Send the OS value as-is, never suppress; the pipeline honours islat.
islatOS limit-ad-tracking flag as reported by the OS: 0 or 1. Apps and CTV. Same key on PEv2 (query string) and telemetry (JSON); both are stored as the string "0"/"1".
OS limit-ad-tracking flag as reported by the OS: 0 or 1. Apps and CTV. Same key on PEv2 (query string) and telemetry (JSON); both are stored as the string "0"/"1".
uLogged-in account (user) id. Not sent for guests.
Logged-in account (user) id. Not sent for guests.
pidViewing profile id within the account, int. Not sent for guests or when no profile.
Viewing profile id within the account, int. Not sent for guests or when no profile.
mMembership tier: basic, plus, premium, premium-box. Not sent for guests.
Membership tier: basic, plus, premium, premium-box. Not sent for guests.
muBilling interval: month, year.
Billing interval: month, year.
pPlatform, keep granular: web, android, androidtv, ios, tvos, roku, tizen, webos, firetv, vizio, hoteltv, box, chromecast. Web sends plain web.
Platform, keep granular: web, android, androidtv, ios, tvos, roku, tizen, webos, firetv, vizio, hoteltv, box, chromecast. Web sends plain web.
siHotel TV site identifier {hotel}_{hotelCode}_{si}. Hotel TV only.
Hotel TV site identifier {hotel}_{hotelCode}_{si}. Hotel TV only.
stStream type: vod, live, multiview, shorts, short_drama, promo_clips. (on-demand is now vod.)
Stream type: vod, live, multiview, shorts, short_drama, promo_clips. (on-demand is now vod.)
mciMediahub content id. Required by the ODK contract when st is vod, shorts or short_drama.
Mediahub content id. Required by the ODK contract when st is vod, shorts or short_drama.
chChannel slug. Required by the ODK contract when st is live or multiview.
Channel slug. Required by the ODK contract when st is live or multiview.
slInitial subtitle language: en, ko, zh-chs, zh-cht, vi, or empty.
Initial subtitle language: en, ko, zh-chs, zh-cht, vi, or empty.
rRecommendation engine name, empty when none. Required when attr_val=click_recommendation.
Recommendation engine name, empty when none. Required when attr_val=click_recommendation.
attrEntry surface: where the user started this playback chain. Set once at entry and sent unchanged on every chained playlist; it resets when the user starts a new playback from any surface on this list, a deeplink or push included. Values: search, main_banner, continue_watching (the rail, not "resumed"), startover, shorts_feed, shorts_feed:pinned, home_rail, favorite, category, category_banner, deeplink, push, tv_guide, live_channel_list. Start Over on a live channel begins a new chain: new playlist with attr=startover, st=live and ch (no mci). Shorts always sends shorts_feed or shorts_feed:pinned, even when a deeplink or push opened it. direct_play is an attr_val value, not an attr value. A surface not on this list: omit attr; never invent a value and never send unmapped. Registry: PM spec §8 (v2.1.7).
Entry surface: where the user started this playback chain. Set once at entry and sent unchanged on every chained playlist; it resets when the user starts a new playback from any surface on this list, a deeplink or push included. Values: search, main_banner, continue_watching (the rail, not "resumed"), startover, shorts_feed, shorts_feed:pinned, home_rail, favorite, category, category_banner, deeplink, push, tv_guide, live_channel_list. Start Over on a live channel begins a new chain: new playlist with attr=startover, st=live and ch (no mci). Shorts always sends shorts_feed or shorts_feed:pinned, even when a deeplink or push opened it. direct_play is an attr_val value, not an attr value. A surface not on this list: omit attr; never invent a value and never send unmapped. Registry: PM spec §8 (v2.1.7).
attr_valPlayback trigger, recorded fresh on every playlist and never inherited. Values: direct_play (the default; missing is read as direct_play, except on Shorts), next_episode, click_next_episode, episode_list_click, auto_next_play, click_recommendation (also send r). Shorts: the feed ordering mode (random, popularity_vh, recency) when the feed API reports it, otherwise omit; on st=shorts a missing attr_val means the ordering mode was not reported, not direct_play. Registry: PM spec §8 (v2.1.7).
Playback trigger, recorded fresh on every playlist and never inherited. Values: direct_play (the default; missing is read as direct_play, except on Shorts), next_episode, click_next_episode, episode_list_click, auto_next_play, click_recommendation (also send r). Shorts: the feed ordering mode (random, popularity_vh, recency) when the feed API reports it, otherwise omit; on st=shorts a missing attr_val means the ordering mode was not reported, not direct_play. Registry: PM spec §8 (v2.1.7).
fposShorts only. Position of the clip in the feed, int.
Shorts only. Position of the clip in the feed, int.
spShorts only. Full-screen sponsored item, bool true or false.
Shorts only. Full-screen sponsored item, bool true or false.
avApp version.
App version.
cStream delivery domain (CDN).
Stream delivery domain (CDN).
Start a playback session › Responses
Event accepted. Use stream_session_id on the rest of the session.
stream_session_idServer-issued stream session id (ss). Carry it on firstplay and viewhour of the same session.
Watch-time tick
Every 5 seconds while playing. v is the seconds watched in this tick: 5 by default, and the measured remainder on the final tick (a 2 second view ends with v=2).
Guaranteed last tick (mandatory for Shorts and Short Drama): measure locally and send on exit, swipe-away or background. Web: sendBeacon on visibilitychange; native: lifecycle hooks plus a persisted local queue re-sent on next launch.
Carry did, osdid and mci or ch on every tick. No Continue Watching side effects on this route.
Validation: only missing required parameters return 422. All other parameters are stored as strings exactly as sent (types below are guidance). Undeclared query parameters are stored as well. Data-quality checks happen in the warehouse.
query Parameters
ssStream session id issued by the server in the playlist response. Missing = 422; any present value (even empty) is stored.
Stream session id issued by the server in the playlist response. Missing = 422; any present value (even empty) is stored.
dtClient send time, epoch milliseconds. Example: 1756971928000
Client send time, epoch milliseconds. Example: 1756971928000
vSeconds watched in this tick, number. Default 5; the final tick carries the measured value. Stored as sent, not shape-validated (a malformed last tick must not be dropped).
Seconds watched in this tick, number. Default 5; the final tick carries the measured value. Stored as sent, not shape-validated (a malformed last tick must not be dropped).
sSend odk. The server overwrites this with odk whatever is sent.
Send odk. The server overwrites this with odk whatever is sent.
didClient-generated persistent device id: in an app, stable across app restarts and app updates; on web, a first-party UUID in localStorage with a cookie fallback. Send on every event, and send the same value on player events and telemetry — it is the join key between the two surfaces, so two separately minted UUIDs break the join silently. (Audience counting lives on the telemetry surface, not on player events.)
Client-generated persistent device id: in an app, stable across app restarts and app updates; on web, a first-party UUID in localStorage with a cookie fallback. Send on every event, and send the same value on player events and telemetry — it is the join key between the two surfaces, so two separately minted UUIDs break the join silently. (Audience counting lives on the telemetry surface, not on player events.)
osdidOS advertising identifier, raw, one kind per platform: idfa (ios/tvos), gaid (android/androidtv), rida (roku), afai (firetv), tifa (tizen), lgudid (webos), vida (vizio). Not applicable on web. Send the OS value as-is, never suppress; the pipeline honours islat.
OS advertising identifier, raw, one kind per platform: idfa (ios/tvos), gaid (android/androidtv), rida (roku), afai (firetv), tifa (tizen), lgudid (webos), vida (vizio). Not applicable on web. Send the OS value as-is, never suppress; the pipeline honours islat.
mciMediahub content id. Required by the ODK contract when st is vod, shorts or short_drama.
Mediahub content id. Required by the ODK contract when st is vod, shorts or short_drama.
chChannel slug. Required by the ODK contract when st is live or multiview.
Channel slug. Required by the ODK contract when st is live or multiview.
wpCurrent playback position in seconds. Recommended; completion and drop-off are derived from it.
Current playback position in seconds. Recommended; completion and drop-off are derived from it.
slCurrently selected subtitle language, empty when none.
Currently selected subtitle language, empty when none.
Watch-time tick › Responses
Event accepted. Echoes ss.
stream_session_idServer-issued stream session id (ss). Carry it on firstplay and viewhour of the same session.