This guide covers everything you need to access and use the Live Linear Program Dataset API
What You’ll Learn |
|
Overview
The Live Linear Program Dataset API provides program-grain viewership data for your Prime Video live linear and FAST channels. Each record represents one viewing session of one scheduled program on one channel.
Data is delivered as a changelog with is_deleted signals for schedule corrections. Two feeds are available: Channels (linear_program_event_log) and FAST (fast_linear_program_event_log).
This data lets you:
- Track program-level viewership (hours viewed, sessions) across stations, territories, devices, and time.
- Analyze performance by station, program, series, and content type.
- Follow schedule corrections accurately without stale rows in your data.
- Integrate live linear viewership with your internal systems and data sources.
For dashboard-based analysis, see: Linear Programming on Slate Analytics
Key Features
Feature |
Details |
|---|---|
Program-grain detail |
One row per viewing session, program, and schedule. Includes title, station, series, airing window, and watch time. |
Removal signal |
Superseded or withdrawn schedules are re-sent with is_deleted = 1, signaling they are no longer valid. |
Stable unique key |
Every row carries session_program_schedule_id. Use it to deduplicate and MERGE. |
Simplified ingestion |
Changelog model. Schedule recurring calls, then MERGE. Upsert on is_deleted = 0. Hard- or soft-delete on is_deleted = 1. |
Consistency |
Standardized formatting across all territories in a single source. No per-territory dimensional tables needed. |
Key Concepts
Concept |
Description |
|---|---|
Session-program-schedule row |
A viewing session of one program in one scheduled slot. Identified by session_program_schedule_id. |
Changelog model |
Data is a changelog. If a row’s attributes change, a new version is published with the same session_program_schedule_id and a newer last_update_time_utc. |
Primary key |
session_program_schedule_id is the unique identifier. Always deduplicate on this field. |
is_deleted signal |
is_deleted = 0 means the schedule is active. is_deleted = 1 signals the schedule is no longer active or valid. |
Applying the signal |
is_deleted = 0: insert or update the row. is_deleted = 1: make it stop appearing in your current data. Drop the row, or keep it flagged and filter it out. |
Getting Started
How to Onboard
The Live Linear Program Dataset API is part of the Analytics API Suite. When you onboard to the Analytics API Suite, you’ll receive access to all available APIs within that suite, including the Live Linear Program Dataset API (if requested during onboarding). For detailed onboarding instructions, visit the Analytics API Onboarding page.
Prerequisites
You need the following before making API requests:
- A Login with Amazon (LWA) Security Profile. Send your Client ID to your CAM to be added to the PV Internal Admin Page.
- An authorization code to request a token.
- A token for all API requests.
Base URI: https://videocentral.amazon.com/apis/v2
All requests must include a valid LWA authentication token in the authorization header. If the token is missing or expired, the API returns an unauthorized exception. |
Pagination
All responses are paginated. Use these parameters to navigate pages:
Parameter |
Default |
Description |
|---|---|---|
limit |
10 |
Number of documents returned per page. Maximum 1,000. |
offset |
0 |
Number of documents to skip before the first result. Follow the next URL instead of computing this yourself. |
All paginated responses include these fields:
Field |
Description |
|---|---|
total |
Total document count across all pages. |
next |
URL to the next page. Null if this is the last page. |
Retrieving Dataset Files
Endpoint
Use this curl command to retrieve a list of downloadable dataset file links:
curl -X GET \
-H "Authorization: Bearer Atza|auth_token" \
"https://videocentral.amazon.com/apis/v2/accounts/{ACADIA_ID}/{REPORT_GROUP}/{IDENTIFIER_ID}/datasets/{REPORT_ID}\
?startDateTime=YYYY-MM-DDThh:mm:ssZ\
&endDateTime=YYYY-MM-DDThh:mm:ssZ\
&offset=0&limit=1000"
Note: This endpoint returns links to downloadable gzip-compressed CSV files, not the rows directly. |
Parameters
Parameter |
Description |
|---|---|
ACADIA_ID |
Your Slate account ID. Find it at /v2/accounts. |
REPORT_GROUP |
The business line segment. Use channels for the Channels feed or fast for the FAST feed. Discover yours with GET /v2/accounts/{ACADIA_ID}. |
IDENTIFIER_ID |
The id value returned by the identifiers endpoint. For Channels, it is an opaque hash. Use the id field as given. For FAST, it is your vendor code, returned unhashed. |
REPORT_ID |
Which report to pull. Use linear_program_event_log for Channels or fast_linear_program_event_log for FAST. |
startDateTime |
Set to the last time you pulled. Format: YYYY-MM-DDThh:mm:ssZ (UTC). |
endDateTime |
Set to the current time. Format: YYYY-MM-DDThh:mm:ssZ (UTC). |
limit |
Minimum 1, maximum 1,000 links per page. |
Available Reports
Two reports are available. Pull each one separately by putting its report ID in the datasets/{REPORT_ID} path segment:
Report |
Report ID |
Contents |
|---|---|---|
Channels |
linear_program_event_log |
SVOD/subscription linear (3P_SUBS, and FREE/PRIME where applicable). |
FAST |
fast_linear_program_event_log |
Free-ad Supported Television / Ad-supported (AVOD) linear channels |
Note: Maximum data retention is 2 years. Requests older than 2 years will not return results. |
Discovery Endpoints
Use these endpoints to find your account ID, report groups, identifiers, and available datasets:
Endpoint |
Returns |
|---|---|
GET /v2/accounts |
List of Slate accounts you can access. |
GET /v2/accounts/{ACADIA_ID} |
Business lines available (for example, channels, fast). |
GET /v2/accounts/{ACADIA_ID}/channels |
Report identifiers available to you. Each entry has an id and a friendly name. |
GET /v2/accounts/{ACADIA_ID}/channels/{IDENTIFIER_ID}/datasets |
Available datasets for that identifier. |
Data Columns
The following columns are present in the linear_program_event_log (Channels) feed. The fast_linear_program_event_log (FAST) feed has the same shape, with vendor_code added and subscription columns delivered as NULL.
Column |
Type |
Nullable |
Description |
|---|---|---|---|
session_program_schedule_id |
STRING |
No |
Primary key. Unique ID (encodes session, program, and airing window). Deduplicate and MERGE on this field. Changes when the program or airing time changes due to updated EPG metadata. |
session_id |
STRING |
No |
Anonymized unique viewing session identifier. |
is_deleted |
INT |
No |
Status signal. 0 = schedule is active. 1 = schedule is no longer active (superseded or withdrawn). Exclude is_deleted = 1 rows from your current data. |
last_update_time_utc |
TIMESTAMP |
No |
Record version time. Always use to deduplicate. Keep the row with the most recent value for a given ID. |
create_time_utc |
TIMESTAMP |
No |
When the row was first created. |
program_id |
STRING |
No |
Program identifier, e.g. TMS ID. |
pv_title_id |
STRING |
Yes |
Prime Video Global Title Identifier (GTI) for the program. Same as pv_title_id in the TVOD feed. |
program_title |
STRING |
Yes |
Program title. |
station_name |
STRING |
Yes |
Channel or station name. |
content_type |
STRING |
No |
live_broadcast or scheduled_tv. |
airing_start_utc |
TIMESTAMP |
No |
Program airing start (UTC). |
airing_end_utc |
TIMESTAMP |
No |
Program airing end (UTC). |
start_segment_utc |
TIMESTAMP |
No |
Viewing session start (UTC). |
end_segment_utc |
TIMESTAMP |
No |
Viewing session end (UTC). |
seconds_viewed |
LONG |
No |
Seconds viewed in this session. |
vendor_sku |
STRING |
Yes |
Content SKU (for example, Gracenote identifiers). |
parent_channel_label |
STRING |
Yes |
Hashed parent channel identifier. |
cid |
STRING |
Yes |
Channel ID (effective). |
benefit_id |
STRING |
Yes |
Entitlement/benefit identifier. |
subscription_offer_id |
STRING |
Yes |
Subscription offer identifier. |
subscription_event_id |
STRING |
Yes |
Subscription event identifier. |
subscription_offer_time_zone |
STRING |
Yes |
Subscription offer time zone. |
marketplace_id |
INT |
No |
Marketplace identifier. |
marketplace_desc |
STRING |
Yes |
Marketplace description. |
territory |
STRING |
Yes |
Territory or country code (US, GB, DE, AU, and others). |
device_class |
STRING |
Yes |
Device category. |
device_sub_class |
STRING |
Yes |
Device sub-category. |
connection_type |
STRING |
Yes |
Connection type (wifi, wired, and others). |
playback_method |
STRING |
Yes |
How the session was consumed: online (streaming) or offline (download). Live linear is effectively always online. |
geo_dma |
STRING |
Yes |
Geographic DMA. |
stream_type |
STRING |
No |
Always LINEAR_TV. |
FAST feed note: The fast_linear_program_event_log feed has the same shape. The vendor_code (partner code) column is present. Subscription columns (subscription_offer_id, subscription_event_id, subscription_offer_time_zone) are delivered as NULL. |
Understanding is_deleted
Every row carries is_deleted. It is a signal about the schedule’s status. There are two values:
Value |
Meaning |
How to Apply It |
|---|---|---|
0 |
Schedule is active (the current version). |
Insert it, or overwrite the existing row for this key. |
1 |
Schedule is no longer active (superseded or withdrawn). |
Make it stop appearing in your current data. Drop the row, or keep it flagged and filter it out. |
When Does is_deleted = 1 Occur?
- Schedule correction. The program or airing time was corrected. The old session_program_schedule_id arrives as is_deleted = 1. A new ID arrives as is_deleted = 0. Apply the old as no longer active, and insert the new.
- Airing removed. The airing was withdrawn entirely. Its ID arrives as is_deleted = 1.
Important Notes
- A given session_program_schedule_id is never both 0 and 1 in the same batch. A corrected airing becomes a different key.
- Rows that never met the feed’s eligibility criteria are not delivered. Do not expect an is_deleted = 1 for a row you never received.
Deduplication
You may receive the same session_program_schedule_id more than once. These are updated versions of the same row. Handle deduplication in three steps:
- Keep the latest version of each ID. For each ID, keep only the row with the newest last_update_time_utc and drop the older ones. This value only moves forward, so the latest always wins.
SELECT *
FROM (
SELECT *,
ROW_NUMBER() OVER (
PARTITION BY session_program_schedule_id
ORDER BY last_update_time_utc DESC
) AS rn
FROM your_staging_table
) t
WHERE rn = 1;
- MERGE the deduped rows into your table. Use the MERGE pattern below. Act on is_deleted every time you load data.
MERGE INTO your_table AS target USING dedup_staging AS source ON target.session_program_schedule_id = source.session_program_schedule_id WHEN MATCHED AND source.is_deleted = 1 AND source.last_update_time_utc > target.last_update_time_utc THEN DELETE WHEN MATCHED AND source.is_deleted = 0 AND source.last_update_time_utc > target.last_update_time_utc THEN UPDATE SET program_title = source.program_title, seconds_viewed = source.seconds_viewed, airing_start_utc = source.airing_start_utc, airing_end_utc = source.airing_end_utc, last_update_time_utc = source.last_update_time_utc -- ... all other columns WHEN NOT MATCHED AND source.is_deleted = 0 THEN INSERT (session_program_schedule_id, session_id, program_id, ..., last_update_time_utc) VALUES (source.session_program_schedule_id, source.session_id, source.program_id, ..., source.last_update_time_utc);
Use a MERGE, not a bulk insert. If you load every file as new rows, the is_deleted = 1 rows sit in your table as active data instead of being applied. Always act on the flag. |
- Soft-delete alternative. Replace the DELETE branch with UPDATE SET is_deleted = 1, then filter WHERE is_deleted = 0 in your queries. Both methods give the same result.
Recommended Ingestion Cadence
New datasets are published incrementally through the day.
Recommendation |
Details |
|---|---|
Recommended cadence |
1 to 4 times per day to stay current. |
Incremental strategy |
Set startDateTime to the last retrieved timestamp and endDateTime to the current time. Download and process all returned files, then MERGE. |
Daily/Weekly consumers |
If you fetch daily or weekly, process all files for the period. This ensures you do not miss updates or deletes. |
Note: Each batch mixes active rows (is_deleted = 0) and no-longer-active rows (is_deleted = 1) together. They are not delivered in separate files. The is_deleted column tells them apart. |
Example API Usage
Follow these steps to discover your account, identify your report group and identifiers, and retrieve dataset files.
Step 0: List Your Accounts
Call GET /v2/accounts to list the Slate accounts you can access.{
"total": 1,
"next": null,
"data": [
{ "id": "12345678", "name": "MGM" }
]
}
Step 1: Business Lines for the Account
Call GET /v2/accounts/12345678 to see the business lines available.{
"total": 2,
"next": null,
"data": [
{ "id": "channels", "name": "Channels" },
{ "id": "fast", "name": "FAST" }
]
}
The id field is the {REPORT_GROUP} path segment to use in subsequent calls.
Step 2a: Channels Identifiers
Call GET /v2/accounts/12345678/channels?offset=0&limit=100 to list your Channels identifiers.{
"total": 2,
"next": null,
"data": [
{ "id": "3f6c1b9d-8a2d-4e7f-9c31-0d5b7b2e6f14", "name": "MGM+" },
{ "id": "a91d4c21-57e0-4b8a-b6f3-2e9c0e1f8b77", "name": "MGM+ Espanol" }
]
}
Step 2b: FAST Identifiers
Call GET /v2/accounts/12345678/fast?offset=0&limit=100 to list your FAST identifiers.{
"total": 1,
"next": null,
"data": [
{ "id": "ABC123", "name": "MGM FAST" }
]
}
Step 2c: Datasets Available for an Identifier
Call GET /v2/accounts/12345678/fast/ABC123/datasets to list the datasets available.{
"total": 1,
"next": null,
"data": [
{ "id": "fast_linear_program_event_log", "name": "FAST Linear Program Event Log" }
]
}
Step 3a: Channels Dataset Files
Call the dataset files endpoint for your Channels identifier. The response returns a list of download URLs for gzip-compressed CSV files.GET /v2/accounts/12345678/channels/3f6c1b9d-8a2d-4e7f-9c31-0d5b7b2e6f14
/datasets/linear_program_event_log
?startDateTime=2026-09-14T00:00:00Z&endDateTime=2026-09-15T00:00:00Z&offset=0&limit=1000
{
"total": 3,
"next": null,
"data": [
{ "downloadUrl": "https://pvreporting-datasets-prod.s3.amazonaws.com/linear_program_event_log/
3f6c1b9d.../2026/09/14/06/...linear_2f0c...e91a.csv.gz?X-Amz-Algorithm=..." },
{ "downloadUrl": "https://pvreporting-datasets-prod.s3.amazonaws.com/linear_program_event_log/
3f6c1b9d.../2026/09/14/14/...linear_7b41...03cd.csv.gz?..." },
{ "downloadUrl": "https://pvreporting-datasets-prod.s3.amazonaws.com/linear_program_event_log/
3f6c1b9d.../2026/09/14/22/...linear_c8d9...5e60.csv.gz?..." }
]
}
Step 3b: FAST Dataset Files
Call the dataset files endpoint for your FAST identifier.GET /v2/accounts/12345678/fast/ABC123/datasets/fast_linear_program_event_log
?startDateTime=2026-09-14T00:00:00Z&endDateTime=2026-09-15T00:00:00Z&offset=0&limit=1000
{
"total": 1,
"next": null,
"data": [
{ "downloadUrl": "https://pvreporting-datasets-prod.s3.amazonaws.com/fast_linear_program_event_log/
ABC123/2026/09/14/15/...fast_linear_c258fb25...758add.csv.gz?X-Amz-Algorithm=..." }
]
}
Sample Queries
These queries assume you have already MERGEd your data. If you keep is_deleted rows in a raw table, add WHERE is_deleted = 0 to each query.
Hours Viewed by Station Over a PeriodSELECT station_name,
COUNT(*) AS sessions,
SUM(seconds_viewed) / 3600.0 AS hours_viewed
FROM your_table
WHERE start_segment_utc BETWEEN '[START_DATE]' AND '[END_DATE]'
GROUP BY station_name
ORDER BY hours_viewed DESC;
Top X Programs by Hours ViewedSELECT program_title, station_name,
SUM(seconds_viewed) / 3600.0 AS hours_viewed
FROM your_table
WHERE start_segment_utc BETWEEN '[START_DATE]' AND '[END_DATE]'
GROUP BY program_title, station_name
ORDER BY hours_viewed DESC
LIMIT [X];
Daily Viewing SummarySELECT DATE(start_segment_utc) AS view_date,
COUNT(*) AS sessions,
SUM(seconds_viewed) / 3600.0 AS hours_viewed
FROM your_table
WHERE start_segment_utc BETWEEN '[START_DATE]' AND '[END_DATE]'
GROUP BY DATE(start_segment_utc)
ORDER BY view_date DESC;
Hours Viewed by TerritorySELECT territory,
SUM(seconds_viewed) / 3600.0 AS hours_viewed
FROM your_table
WHERE start_segment_utc BETWEEN '[START_DATE]' AND '[END_DATE]'
GROUP BY territory
ORDER BY hours_viewed DESC;
ETL Pipeline
Use this four-step pattern to build your ETL pipeline for the Live Linear Program Dataset.
- Initial Data Pull. Pull all files for your channel within the desired time range using the API endpoint. Download all returned files. Each contains rows in gzip-compressed CSV.
- Deduplicate. When multiple records exist for the same session_program_schedule_id across the files you pulled, keep only the row with the latest last_update_time_utc. See the Deduplication section for the full SQL pattern.
- Apply to Destination. MERGE the deduplicated records into your destination table keyed on session_program_schedule_id. Upsert on is_deleted = 0. On is_deleted = 1, make the ID stop appearing in your current data. Hard-delete it, or keep the row flagged and filter it out.
- Incremental Processing. For ongoing loads, set to the last time you pulled and endDateTime to the current time. Process all returned files and MERGE into your destination.
startDateTime = {last_successful_pull_timestamp}
endDateTime = {current_utc_timestamp}
Quick Tips
Keep these tips in mind when you integrate the API into your pipeline.
- session_program_schedule_id is your unique key. Always deduplicate using last_update_time_utc.
- Use a MERGE, not a bulk insert. Act on is_deleted signals every time you load data.
- Pull 1 to 4 times per day for the freshest data.
- Set your startDateTime to the last successful pull timestamp for incremental loads.
- Use the discovery endpoints to find your account, identifiers, and available datasets.
- Pull both Channels and FAST feeds if your partnership covers both.
- Add WHERE is_deleted = 0 to all queries if you use the soft-delete approach.
- Maximum data retention is 2 years. Plan your historical pulls accordingly.
Did You Know? |
Programmatic access to program-level viewership data lets you build custom reports, feed your scheduling systems, and combine linear data with your other business data. Partners who integrate this API into their workflows make faster, more informed decisions about programming and content acquisition. For visual analysis and quick insights, visit the Linear Programming dashboard on Slate Analytics. |