Introduction
Welcome to Paket! This documentation explains key concepts and describes how Platforms and Publishers engage with the Paket Watch APIs.
So, what is it?
Paket is a universal engagement platform for Connected TVs and subscription marketplaces. We facilitate, through our suite of APIs, device and platform-agnostic features that help drive engagement through personalization, enhanced discovery, and advanced analytics.
The Paket API is organized around REST. Our API has predictable resource-oriented URLs, accepts JSON-encoded request bodies, returns JSON-encoded responses, and uses standard HTTP response codes, authentication, and verbs.
Base URL
https://api.paket.tv/v1
There are two primary types of API consumers:
Platforms
Platform partners are typically TV OEMs, platforms, operating systems, and marketplaces.
Publishers
Publisher partners are typically publishers of streaming media or other subscription-based apps.
How a partner engages with the API depends largely on whether they are a Platform or a Publisher. This designation is assigned in the Paket Developer Portal at the time of the Company's account setup.
Clients
To begin working with the Paket API, Partners must first create a Client in the Paket Developer Portal.
Clients are used by Platforms and Publishers, respectively, to communicate with the Paket API and to exchange data with other Clients.
It is at the Client level that API credentials are issued, webhooks are delivered, and API products - such as UpNext or Bundles - are configured.
Clients should correlate broadly to an operating system or platform, in the case of Platform accounts; or to an application, in the case of Publisher accounts.
Authentication
The Paket API uses basic access authentication to authenticate all incoming API requests (please note there are additional Security protocols used to secure API requests).
Authenticated Request:
curl https://api.paket.tv/v1 \
-H "Authorization: Basic [Base64 encoding of username and password]"
Authenticating via Basic Auth involves passing a Base64 encode of your Client's username
and password
, prefixed with Basic
within the request's Authorization
header.
API credentials be found in the Paket Developer Portal within the Client's API Credentials tab. The username
and password
are itemized as 'API Username' and 'API Secret Key,' respectively:
Testing
API requests may be tested in a live environment simply by using the API Test Key provided in the Paket Developer Portal. Test keys begin with the prefix test_sk
and inherit the same behaviors as live API Secret Keys, save that they call test responses.
Test API requests are validated identically to live requests and although the response schema are identical to live requests, the responses themselves are dynamically generated.
The Paket-Response-Type: Test
header indicates whether or not the response is via the API Test Key.
Security
Securing API requests is critical to ensure data integrity. The Paket API employs the following methods to ensure that requests made to its API are authenticated and secure:
- Forced HTTPS: Connections are strictly enforced over HTTPS at
https://api.paket.tv/v1
. - TLS/SSL: X.509 server certificates to validate server requests are authenticated as Paket Media, Inc.
- Basic Auth: Basic authentication required for all API requests w/unique Client username and rollable secret keys.
- IP Whitelisting: Restrict access to API requests to your server IP addresses designated at the Client level.
- Encryption-at-rest: All data stored is encrypted-at-rest.
Errors
Paket uses conventional HTTP response codes to indicate the success or failure of an API request. In general: Codes in the 2xx
range indicate success. Codes in the 4xx
range indicate an error that failed given the information provided (e.g., a required parameter was omitted, etc.). Codes in the 5xx
range indicate an error with Paket's servers.
Error Code | Meaning |
---|---|
400 | Bad Request -- Your request is invalid. |
401 | Unauthorized -- Your API credentials are wrong. |
403 | Forbidden -- You do not have permission to access the requested resource. |
404 | Not Found -- The specified resource could not be found. |
500 | Internal Server Error -- We had a problem with our server. Try again later. |
503 | Service Unavailable -- We're temporarily offline for maintenance. Please try again later. |
Idempotency
The Paket API supports idempotency for safely retrying requests without accidentally performing the same operation twice. When creating or updating an object, use an idempotency key. Then, if a connection error occurs, you can safely repeat the request without risk of creating a second object or performing the update twice.
To perform an idempotent request, provide an additional Idempotency-Key
element to the request header.
Paket's idempotency works by saving the resulting status code and body of the first request made for any given idempotency key, regardless of whether it succeedes or fails. Subsequent requests with the same key return the same result.
A requesting Client generates an idempotency key, which is a unique key that the server uses to recognize subsequent retries of the same request. How you create unique keys is up to you, but we suggest using V4 UUIDs, or another random string with enough entropy to avoid collisions. Idempotency keys are up to 255 characters long.
We remove keys from the system automatically after they’re at least 72 hours old and will generate a new request if a key is reused after the original is pruned. The idempotency layer compares incoming parameters to those of the original request and errors if they’re the same to prevent accidental misuse.
We save results only after the execution of an endpoint begins. If incoming parameters fail validation, or the request conflicts with another request that’s executing concurrently, we don’t save the idempotent result because no API endpoint initiates the execution. You can retry these requests.
All POST
and PUT
requests accept idempotency keys. Don’t send idempotency keys in GET
and DELETE
requests because it has no effect. These requests are idempotent by definition.
Platform Data
Some Platforms will require custom attributes and schemas that are not available in an API product's default attribute set.
To address this requirement, Platforms are able to configure custom app-level schemas and attributes to be provided by Publisher partners; as well as to define the regional availability of a Platform Client by region or specific countries.
For example, a Platform Client may require a custom app identifier, custom_app_id
, is returned in UpNext API responses. In order to ensure such custom app identifier is provided by a Publisher Client, the Platform will configure this custom attribute from within the Client in the Paket Developer Portal.
Example
platform_data
attribute:
{
...,
platform_data: {
custom_app_id: 12345,
deep_link: "app://12345/cid12345"
}
}
When preparing to integrate with the Platform, the Publisher will configure the requested custom attribute, in this case the custom_app_id
. This data will then be returned in subsequent Platform API responses under the platform_data
attribute.
Taking this example further, perhaps the Platform Client also requires a deep_link
url attribute comprised of the custom attribute custom_app_id
and the default attribute content_id
. In this example, the data must be returned using the following schema: app://custom_app_id/content_id
.
The Platform will also define this schema under the custom attribute deep_link
and by using handlebars to define the schema: app://{{custom_app_id}}/{{content_id}}
.
If the value of an Publisher's custom_app_id
is 12345
and an item's content_id
is cid12345
, the resulting platform_data
attribute returned in an API response to the requesting Platform will look something like the example to the right.
Pagination
Response
{
"total": 24,
"next_key": 6,
"items": [
{...},
{...},
{...},
{...},
{...},
]
}
Many of our top-level API resources have support for bulk fetches through “list” API methods. For example, you can list Session Participants, Session Lists, and Participant Lists. These list API methods share a common structure and can accept the following two parameters: limit
, and next_key
.
The limit
parameter is provided at the time of the request and limits the number of items returned in the API response. By default, this value is 50
.
The next_key
parameter is returned in a response in which the total results exceed the default or specified limit
and specifies the next item to be returned in a subsequent API request. Alternatively, a request can be made with any next_key
value, however, there is no guarantee such an object will exist.
Versioning
When backwards-incompatible changes are made to the API, we release a new, dated version. The current version is 2023-12-01
. For information on all API updates, view our API changelog.
By default, requests made to the Paket API use your account’s default API version (controlled in the Developer Portal) unless you override it by setting the Paket-Version header.
Webhook events also use your account’s API version by default, unless you set an API version during endpoint creation.
You can upgrade your API version in the Paket Developer Portal. As a precaution, use API versioning to test a new API version before committing to an upgrade.
Core API
The Core API includes requests that are used for more than one API product and, in many instances, across all of Paket's API products.
API Status
Endpoint
GET https://api.paket.tv/v1
Retrieves the API status by making an authenticated GET
request to the API's root path.
The Status Object
The Status Object
{
"message": "The API is healthy!",
"client_id: "fab3d02606122a08"
}
Attributes
message
string
The API Status message.
client_id
string
The unique identifier of the requesting Client.
Retrieve API Status
GET https://api.paket.tv/v1
curl --location 'https://api.paket.tv/v1' \
--header 'Accept: application/json' \
--header 'Authorization: Basic <credentials>'
Response
{
"message": "The API is healthy!"
}
Parameters
No parameters.
Returns
Returns a status object.
Sessions
Endpoint
POST https://api.paket.tv/v1/sessions
A Session represents a Platform end user either at the account or profile level. Whether the Session is associated to the account or profile is, ultimately, up to the Platform to determine. For optimal flexibility, however, a Session ID should be created and stored by a Platform at the profile level.
Ideally, a Session should be indefinitely associated with an end-user's account or profile. So long as the Session ID persists, all items associated with the Session will remain active.
The Session Object
The Session Object
{
"session_id": "faa37296-dc32-4cce-b8c0-47ac4bc032c1",
"client_type": "platform",
"client_id": "fab3d02606122a08",
"created_at": "2024-02-16T04:41:06.596Z"
}
Attributes
session_id
string
A unique Session identifier.
client_type
string
The requesting Client type.
client_id
string
The requesting Client ID.
created_at
string
The ISO 8601 timestamp when the Session was created.
The Session Participant Object
The Session Participant Object is created when a Participant is added to a Session and contains useful information related to a Participant's relationship to a Session.
The Session Participant Object
{
"app_id": "417f3625d067cbe3",
"participant_id": "6b0af623-2923-4997-92a6-73f94bbe321e",
"session_id": "faa37296-dc32-4cce-b8c0-47ac4bc032c1",
"client_id": "fab3d02606122a08",
"created_at": "2024-02-16T04:41:06.596Z"
}
Attributes
app_id
string
The Publisher's Client ID to which the participant_id
belongs.
participant_id
string
A unique Participant identifier.
session_id
string
A unique Session identifier.
client_type
string
The requesting Client type.
client_id
string
The requesting Client ID.
created_at
string
The ISO 8601 timestamp when the Session was created.
Create a new Session
POST https://api.paket.tv/v1/sessions
curl --location --request POST 'https://api.paket.tv/v1/sessions' \
--header 'Accept: application/json' \
--header 'Authorization: Basic <credentials>'
Response
{
"session_id": "faa37296-dc32-4cce-b8c0-47ac4bc032c1",
"client_type": "platform",
"client_id": "fab3d02606122a08",
"created_at": "2024-02-16T04:41:06.596Z"
}
Parameters
No parameters.
Returns
Returns a Session object.
Participants
Endpoint
POST https://api.paket.tv/v1/participants
A Participant represents a Publisher (or app's) end user either at the account or profile level. Whether the Participant is associated to the account or profile is, ultimately, up to the Publisher to determine. For optimal flexibility, however, a Participant ID should be created and stored by a Publisher at the profile level.
Ideally, a Participant should be indefinitely associated with an end-user's account or profile. So long as the Participant ID persists, all items associated with the Participant will remain active.
Generally, a Publisher interacts with a Platform by explicitly sharing the Participant ID with a Platform and it being matched to an active Session.
The Participant Object
The Participant Object
{
"participant_id": "6e5060c3-7df4-488e-9e9a-67cd5077b352",
"client_type": "publisher",
"client_id": "fe4a9ed381e8e376",
"created_at": "2024-02-16T04:41:06.596Z"
}
Attributes
participant_id
string
The newly generated Participant ID.
client_type
string
The requesting Client type.
client_id
string
The requesting Client ID.
created_at
string
The ISO 8601 timestamp when the Session was created.
Create a new Participant
POST https://api.paket.tv/v1/participants
curl --location --request POST 'https://api.paket.tv/v1/participants' \
--header 'Accept: application/json' \
--header 'Authorization: Basic <credentials>'
Response
{
"participant_id": "6e5060c3-7df4-488e-9e9a-67cd5077b352",
"client_type": "publisher",
"client_id": "fe4a9ed381e8e376",
"created_at": "2024-02-16T04:41:06.596Z"
}
Parameters
No parameters.
Returns
Returns a Participant object.
UpNext API
Overview
The Paket UpNext API is a powerful connected TV (CTV) engagement tool through which Platforms and Publishers can offer users a consistent, highly personalized feed of their recently watched items, new content availability, watchlist items, and more.
While similar features currently exist across many best-in-class tv and OEM platforms, the resulting data is, invariably, inconsistent - and the means by which the data is retrieved are often varied, making it challenging for app developers to build and maintain such feature across an array of platforms.
The goal with the Paket UpNext API is to offer CTV Platforms and Publishers a platform-agnostic experience that is as consistent and reliable - across devices - as is currently available exclusively on identity-based, ecosystem-wide platforms such as Google TV and Apple TV.
For Platforms, the UpNext API offers a timely snapshot of what a user is watching on any Paket-integrated service across any platorm or device. In addition to providing an aggregated view of a user's most relevant content, the data provided can be used to drive personalized recommendations, ads, and merchandising opportunities from within the Platform's native environment.
For Publishers, the UpNext API ensures its highly relevant content is featured consistently across Paket-integrated tv platforms and within the context of a user's cross-device viewing - something that has proven to be a top driver of engagement on connected tvs. Further, a Publisher needs to integrate only once to have its users' continue watching data syndicated to any Paket-integrated platform. Adding new Platforms is simply a matter of configuration from within the Paket Developer Portal.
The List Object
At the core of the UpNext API is the Session List object, which is an aggregated, chronological feed up UpNext items added by all Participants attached to a Session.
For example, if Apps A, B, and C have shared their respective Participant IDs with a Platform - and such Participant IDs have been added to a Session - a request to this API endpoint will return an aggregated, chronological list of items across all Apps attached to the Session.
An individual Participant's feed (i.e., a specific App) can also be requested simply by calling the Session API along with the requested Participant ID included in the path parameters.
The List Object
{
"total": 271,
"next_key": 4,
"items": [
{...},
{...},
{...},
{...},
}
]
}
Attributes
total
integer
The total number of list items returned from request.
next_key
integer
The index of the next available item. Returned only if the total
results exceeds the requested number of results.
items
array
An array of list items.
The List Item Object
The List Item Object
{
"content_id": "1iwousk12i008d9",
"app_id": "df79418d4e6d5325",
"participant_id": "6b0af623-2923-4997-92a6-73f94bbe321e",
"updated_at": "2023-12-20T19:02:28.285Z",
"action": "up_next_continue",
"media_type": "tv_episode",
"title": "The Colt",
"description": "Jeff ignores Lassie when Gramps brings home a new colt.",
"season": 1,
"episode": 3,
"poster_art_uri": "https://media.paket.tv/1iwousk12i008d9/thumb.png",
"poster_art_aspect_ratio": "aspect_ratio_16_9",
"preview_video_uri": "https://media.paket.tv/1iwousk12i008d9/preview.m3u8",
"last_interaction": 1702766417,
"position": 654,
"duration": 1308,
"hidden": false,
"platform_data": {
"platform_app_id": "internalAppId12345"
},
"app_media": {
"icon_1x": "https://media.paket.tv/media/df79418d4e6d5325/icon@1x.png",
"icon_2x": "https://media.paket.tv/media/df79418d4e6d5325/icon@2x.png",
"icon_3x": "https://media.paket.tv/media/df79418d4e6d5325/icon@3x.png",
"tile_1x": "https://media.paket.tv/media/df79418d4e6d5325/tile@1x.png",
"tile_2x": "https://media.paket.tv/media/df79418d4e6d5325/tile@2x.png",
"logo_dark_1x": "https://media.paket.tv/media/df79418d4e6d5325/logo_dark@1x.png",
"logo_light_1x": "https://media.paket.tv/media/df79418d4e6d5325/logo_light@1x.png"
}
}
Attributes
content_id
string
The unique identifier of the respective item. Typically, this is an internal identifier provided by the Publisher.
app_id
string
The Publisher's Client ID to which the item is associated.
participant_id
string
The Participant ID to which the item is associated.
updated_at
string
The ISO 8601 timestamp when the item was created or last updated.
action
string
The item action, which can be one of the following enum values:
up_next_continue
up_next_next
up_next_new
up_next_watchlist
media_type
string
The item's media type, which can be one of the following enum values:
movie
tv_episode
title
string
The title of the movie or TV show item.
description
string
The item description.
season
integer
The tv series season number. Returned only if item media_type
is tv_episode
.
episode
integer
The tv series episode number. Returned only if item media_type
is tv_episode
.
poster_art_uri
string
Uri of item's thumbnail image.
poster_art_aspect_ratio
string
Aspect ratio of media provided at poster_art_uri
, which can be one of the following enum values:
aspect_ratio_16_9
aspect_ratio_4_3
aspect_ratio_1_1
aspect_ratio_2_3
preview_video_uri
string
Uri of item's preview video, if provided.
last_interaction
integer
UTC
timestamp of Participant's last interaction with media item.
position
integer
Last recorded position of media playback in seconds (returned if action
is up_next_continue
).
duration
integer
Item's total running time in seconds.
hidden
boolean
Indicates whether item is hidden or visible.
platform_data
object
Custom object containing custom attributes provided by the requesting Platform in the form of key-value pairs.
app_media
object
Object containing URIs to app media provided by the integrated Publisher.
Media URIs are constructed using the following shchema: <base_url>/media/<app_id>/<file_name>.png
. Media will return provided the respective file has been uploaded by the Publisher. Note: this can be reviewed and verified by the Platform via the UpNext API avails configuration in the Paket Developer Portal.
Below is a list of available keys and its respective file_name
:
icon_1x
corresponds toicon@1x.png
(240x240, PNG)icon_2x
corresponds toicon@2x.png
(480x480, PNG)icon_3x
corresponds toicon@3x.png
(960x960, PNG)tile_1x
corresponds totile@1x.png
(400x240, PNG)tile_2x
corresponds totile@2x.png
(800x480, PNG)logo_dark_1x
corresponds tologo_dark@1x.png
(400x240, PNG, Transparency)logo_light_1x
corresponds tologo_light@1x.png
(400x240, PNG, Transpareny)
The Session Participants Object
Returned when requesting a list of all Parcticipants associated with an active Session.
The Session Participants Object
{
"participant_id": "6b0af623-2923-4997-92a6-73f94bbe321e",
"app_id": "df79418d4e6d5325",
"created_at": "2023-12-23T23:38:50.303Z"
}
Attributes
participant_id
string
The corresponding Participant ID.
app_id
string
The Publisher's Client ID to which the Participant belongs.
created_at
array
The ISO 8601 timestamp when the Participant was added to the Session.
Platform Work Flow
Before beginning, Platform partners should familiarize themselves with the Sessions object. Additionally, Platforms should leverage the platform_data
configuration as described in the Platform Data section of the documentation.
The diagram below is an overview of how Platform Clients interact with the Paket UpNext API.
Publisher Work Flow
Before beginning, Publisher partners should familiarize themselves with the Participants object.
The diagram below is an overview of how Publisher Clients interact with the Paket UpNext API.
Sessions
Sessions are the primary means by which Platforms interact with the Paket UpNext API.
It is through this API that Platforms can:
- Add or remove Participants to a Session
- Fetch an aggregated UpNext list
- Fetch a specific Participant's UpNext list
- Fetch a list of a Session's Participants
- Hide items from a list
- Remove an existing Session
Add a Participant
Endpoint
PUT https://api.paket.tv/v1/upnext/sessions/:session_id
Adds or updates a Participant to an active Session.
PUT https://api.paket.tv/v1/upnext/sessions/:session_id
curl --location --request PUT 'https://api.paket.tv/v1/upnext/sessions/:session_id' \
--header 'Content-Type: application/json' \
--header 'Accept: application/json' \
--header 'Authorization: Basic <credentials>' \
--data '{
"app_id": "fe4a9ed381e8e376",
"participant_id": "6e5060c3-7df4-488e-9e9a-67cd5077b352"
}'
Response
{
"message": "Success"
}
Parameters
app_id
string
The Publisher's Client ID to which the Participant being added belongs.
participant_id
string
The Participant ID to be added to the Session.
Returns
Returns a 200
Success response.
Remove a Participant
Endpoint
DELETE https://api.paket.tv/v1/upnext/sessions/:session_id/:participant_id
Removes a Participant from an active Session.
DELETE https://api.paket.tv/v1/upnext/sessions/:session_id/:participant_id
curl --location --request DELETE 'https://api.paket.tv/v1/upnext/sessions/:session_id/:participant_id' \
--header 'Accept: application/json' \
--header 'Authorization: Basic <credentials>'
Response
{}
Parameters
No parameters.
Returns
Returns a 204
No Content response.
Get an Aggregated List
Endpoint
GET https://api.paket.tv/v1/upnext/sessions/:session_id
Retrieves aggregated Session list from all registered Participants.
GET https://api.paket.tv/v1/upnext/sessions/:session_id
curl --location 'https://api.paket.tv/v1/upnext/sessions/:session_id' \
--header 'Accept: application/json' \
--header 'Authorization: Basic <credentials>'
Response
{
"total": 271,
"next_key": 4,
"items": [
{
"content_id": "1iwousk12i008d9",
"app_id": "df79418d4e6d5325",
"participant_id": "6b0af623-2923-4997-92a6-73f94bbe321e",
"updated_at": "2023-12-20T19:02:28.285Z",
"action": "up_next_continue",
"media_type": "tv_episode",
"title": "The Colt",
"description": "Jeff ignores Lassie when Gramps brings home a new colt.",
"season": 1,
"episode": 3,
"poster_art_uri": "https://media.paket.tv/1iwousk12i008d9/thumb.png",
"poster_art_aspect_ratio": "aspect_ratio_16_9",
"preview_video_uri": "https://media.paket.tv/1iwousk12i008d9/preview.m3u8",
"last_interaction": 1702766417,
"position": 654,
"duration": 1308,
"hidden": false,
"platform_data": {
"platform_app_id": "internalAppId12345"
},
"app_media": {
"icon_1x": "https://media.paket.tv/media/df79418d4e6d5325/icon@1x.png",
"icon_2x": "https://media.paket.tv/media/df79418d4e6d5325/icon@2x.png",
"icon_3x": "https://media.paket.tv/media/df79418d4e6d5325/icon@3x.png",
"tile_1x": "https://media.paket.tv/media/df79418d4e6d5325/tile@1x.png",
"tile_2x": "https://media.paket.tv/media/df79418d4e6d5325/tile@2x.png",
"logo_dark_1x": "https://media.paket.tv/media/df79418d4e6d5325/logo_dark@1x.png",
"logo_light_1x": "https://media.paket.tv/media/df79418d4e6d5325/logo_light@1x.png"
}
},
{...},
{...},
{...}
]
}
Parameters
limit
integer
Optional. Limits items returned (default is 50
, maximum is 200
).
next_key
integer
Optional. Key returned in previous call if additional items are available.
Returns
Returns a List Object containing an array of List Item Objects.
Get a Specific List
Endpoint
GET https://api.paket.tv/v1/upnext/sessions/:session_id/:participant_id
Retrieves the Session list of a specified Participant.
GET https://api.paket.tv/v1/upnext/sessions/:session_id/:participant_id
curl --location 'https://api.paket.tv/v1/upnext/sessions/:session_id/:participant_id' \
--header 'Accept: application/json' \
--header 'Authorization: Basic <credentials>'
Response
{
"total": 271,
"next_key": 4,
"items": [
{
"content_id": "1iwousk12i008d9",
"app_id": "df79418d4e6d5325",
"participant_id": "6b0af623-2923-4997-92a6-73f94bbe321e",
"updated_at": "2023-12-20T19:02:28.285Z",
"action": "up_next_continue",
"media_type": "tv_episode",
"title": "The Colt",
"description": "Jeff ignores Lassie when Gramps brings home a new colt.",
"season": 1,
"episode": 3,
"poster_art_uri": "https://media.paket.tv/1iwousk12i008d9/thumb.png",
"poster_art_aspect_ratio": "aspect_ratio_16_9",
"preview_video_uri": "https://media.paket.tv/1iwousk12i008d9/preview.m3u8",
"last_interaction": 1702766417,
"position": 654,
"duration": 1308,
"hidden": false,
"platform_data": {
"platform_app_id": "internalAppId12345"
},
"app_media": {
"icon_1x": "https://media.paket.tv/media/df79418d4e6d5325/icon@1x.png",
"icon_2x": "https://media.paket.tv/media/df79418d4e6d5325/icon@2x.png",
"icon_3x": "https://media.paket.tv/media/df79418d4e6d5325/icon@3x.png",
"tile_1x": "https://media.paket.tv/media/df79418d4e6d5325/tile@1x.png",
"tile_2x": "https://media.paket.tv/media/df79418d4e6d5325/tile@2x.png",
"logo_dark_1x": "https://media.paket.tv/media/df79418d4e6d5325/logo_dark@1x.png",
"logo_light_1x": "https://media.paket.tv/media/df79418d4e6d5325/logo_light@1x.png"
}
},
{...},
{...},
{...}
]
}
Parameters
limit
integer
Optional. Limits items returned (default is 50
, maximum is 200
).
next_key
integer
Optional. Key returned in previous call if additional items are available.
Returns
Returns a List Object containing an array of List Item Objects.
Get Session Participants
Endpoint
GET https://api.paket.tv/v1/upnext/sessions/:session_id/participants
Retrieves a list of all Participant's associated with a Session.
GET https://api.paket.tv/v1/upnext/sessions/:session_id/participants
curl --location 'https://api.paket.tv/v1/upnext/sessions/:session_id/participants' \
--header 'Accept: application/json' \
--header 'Authorization: Basic <credentials>'
Response
{
"total": 12,
"next_key": 4,
"items": [
{
{
"participant_id": "6b0af623-2923-4997-92a6-73f94bbe321e",
"app_id": "df79418d4e6d5325",
"created_at": "2023-12-23T23:38:50.303Z"
}
},
{...},
{...},
{...}
]
}
Parameters
limit
integer
Optional. Limits items returned (default and maximum is 50
).
next_key
integer
Optional. Key returned in previous call if additional items are available.
Returns
Returns a List Object containing an array of Session Participants Objects.
Hide an Item in a List
Endpoint
PUT https://api.paket.tv/v1/upnext/sessions/:session_id/:participant_id
PUT https://api.paket.tv/v1/upnext/sessions/:session_id/:participant_id
curl --location --request PUT 'https://api.paket.tv/v1/upnext/sessions/:session_id/:participant_id' \
--header 'Content-Type: application/json' \
--header 'Accept: application/json' \
--header 'Authorization: Basic <credentials>' \
--data '{
"content_id": "1iwousk12i008d9",
"action": "hide"
}'
Response
{
"message": "Success"
}
If hiding list items is supported within a Platform's user interface, this action allows the Platform to set the hidden
parameter of a list item to true
. Once the action is completed, an item_hidden
notification is delivered to the Publisher's webhook endpoint.
While it is up to the Publisher to decide whether or not to remove the item from the Participant's list, the item will remain hidden within the List Item Object unless the hidden
attribute is set to false
by a Publisher action.
Parameters
content_id
string
The content ID of the item to be hidden.
action
string
The hide action, which (presently) can be one of a single enum value:
hide
Returns
Returns a 200
Success response.
Remove a Session
Endpoint
DELETE https://api.paket.tv/v1/upnext/sessions/:session_id
DELETE https://api.paket.tv/v1/upnext/sessions/:session_id
curl --location --request DELETE 'https://api.paket.tv/v1/upnext/sessions/:session_id' \
--header 'Accept: application/json' \
--header 'Authorization: Basic <credentials>'
Response
{}
Deletes a Session and all Participant associations.
Parameters
No parameters.
Returns
Returns a 204
No Content response.
Participants
Participants are the primary means by which Publishers interact with the Paket UpNext API.
It is through this API that Publishers can:
- Add or remove items from a Participant's list
- Fetch a specific Participant's UpNext list
- Remove a Participant's Sessions
Publisher Guidelines
It is likely that most Publishers who will be integrating with the Paket UpNext API will have an existing back-end service dedicated to making continue watching, new episodes, and related requests. In such cases - and to ensure as consistent a user experience as possible - it is recommended that such partners post data to the UpNext API in a way that is consistent with its existing guidelines and best practices.
For those Publishers who will be integrating exclusively with the Paket API, please refer to the following guidelines as to when items should be added to a Participant's UpNext List.
When to add an item to the UpNext List
Please determine whether or not to add an up_next_continue
item if:
- The user exits an app client during playback
- The user pauses or stops playback of a media item for more than five (5) minutes
Including unfinished movies and TV shows
Please add an up_next_continue
item if:
- A movie or TV show is started and the user has watched more than two (2) minutes; or
- A movie or TV show is is started and the user has watched more that 3% of its total duration (whichever is earlier)
Including new and next episode from a tv series
- Please add an
up_next_next
item if a user finishes an episode in a series and the next episode is available on your service - Please add an
up_next_new
item if a user is caught up on all available episodes of a tv series and a new season or episode becomes availables - Please add an
up_next_watchlist
item if an item in a user's watchlist was previously unavailable but has since been made available to watch on the service
Remove finished items from the UpNext List
- A media item is considered 'finished' when the end credits begin
- If the end credits cannot be determined, a media item is considered 'finished' when 3% or less the total duration of the media is remaining to be watched
Add Item to List
Endpoint
PUT https://api.paket.tv/v1/upnext/participants/:participant_id
PUT https://api.paket.tv/v1/upnext/participants/:participant_id
curl --location --request PUT 'https://api.paket.tv/v1/upnext/participants/:participant_id' \
--header 'Content-Type: application/json' \
--header 'Accept: application/json' \
--header 'Authorization: Basic <credentials>' \
--data '{
"action": "up_next_continue",
"media_type": "tv_episode",
"content_id": "1iwousk12i008d9",
"title": "The Colt",
"poster_art_uri": "https://media.paket.tv/1iwousk12i008d9/thumb.png",
"poster_art_aspect_ratio": "aspect_ratio_16_9",
"description": "Jeff ignores Lassie when Gramps brings home a new colt.",
"season": 1,
"episode": 3,
"preview_video_uri": "https://media.paket.tv/1iwousk12i008d9/preview.m3u8",
"last_interaction": 1702766417,
"position": 654,
"duration": 1308
"hidden": false
}'
Response
{
"message": "Success"
}
Adds or updates an Item to the Participant list. Please refer to the UpNext Guidelines to learn more about how to determine when to add an Item to the Participant's list.
Parameters
* required parameter.
content_id
* string
The content ID of the item being added. Typically, this is an internal identifier provided by the Publisher.
media_type
* string
The item's media type, which can be one of the following enum values:
movie
tv_episode
action
* string
The item action, which can be one of the following enum values:
up_next_continue
up_next_next
up_next_new
up_next_watchlist
title
* string
The title of the movie or TV show item.
description
* string
The item description.
poster_art_uri
* string
Uri of item's thumbnail image.
poster_art_aspect_ratio
* string
Aspect ratio of media provided at poster_art_uri
, which can be one of the following enum values:
aspect_ratio_16_9
aspect_ratio_4_3
aspect_ratio_1_1
aspect_ratio_2_3
season
integer
The tv series season number. Required only if item media_type
is tv_episode
.
episode
integer
The tv series episode number. Required only if item media_type
is tv_episode
.
preview_video_uri
string
Uri of item's preview video, if provided.
last_interaction
integer
UTC
timestamp of Participant's last interaction with media item.
position
integer
Last recorded position of media playback in seconds (required if action
is up_next_continue
).
duration
* integer
Item's total running time in seconds.
hidden
boolean
Indicates whether item is hidden or visible.
Returns
Returns a 200
Success response.
Remove Item from List
Endpoint
DELETE https://api.paket.tv/v1/upnext/participants/:participant_id/:content_id
DELETE https://api.paket.tv/v1/upnext/participants/:participant_id/:content_id
curl --location --request DELETE 'https://api.paket.tv/v1/upnext/participants/:participant_id/:content_id' \
--header 'Accept: application/json' \
--header 'Authorization: Basic <credentials>'
Response
{}
Removes an Item from the Participant list.
Parameters
No parameters.
Returns
Returns a 204
No Content response.
Get a Participant List
Endpoint
GET https://api.paket.tv/v1/upnext/participants/:participant_id
Retrieves the list of a specified Participant.
GET https://api.paket.tv/v1/upnext/participants/:participant_id
curl --location 'https://api.paket.tv/v1/upnext/participants/:participant_id' \
--header 'Accept: application/json' \
--header 'Authorization: Basic <credentials>'
Response
{
"total": 271,
"next_key": 4,
"items": [
{
"content_id": "1iwousk12i008d9",
"app_id": "df79418d4e6d5325",
"participant_id": "6b0af623-2923-4997-92a6-73f94bbe321e",
"updated_at": "2023-12-20T19:02:28.285Z",
"action": "up_next_continue",
"media_type": "tv_episode",
"title": "The Colt",
"description": "Jeff ignores Lassie when Gramps brings home a new colt.",
"season": 1,
"episode": 3,
"poster_art_uri": "https://media.paket.tv/1iwousk12i008d9/thumb.png",
"poster_art_aspect_ratio": "aspect_ratio_16_9",
"preview_video_uri": "https://media.paket.tv/1iwousk12i008d9/preview.m3u8",
"last_interaction": 1702766417,
"position": 654,
"duration": 1308,
"hidden": false
},
{...},
{...},
{...}
]
}
Parameters
limit
integer
Optional. Limits items returned (default is 50
, maximum is 200
).
next_key
integer
Optional. Key returned in previous call if additional items are available.
Returns
Returns a List Object containing an array of List Item Objects.
Remove Participant's Sessions
Endpoint
DELETE https://api-dev.paket.tv/v1/upnext/participants/:participant_id/sessions
Removes all sessions associated with a Participant.
DELETE https://api-dev.paket.tv/v1/upnext/participants/:participant_id/sessions
curl --location --request DELETE 'https://api.paket.tv/v1/upnext/participants/:participant_id/sessions' \
--header 'Accept: application/json' \
--header 'Authorization: Basic <credentials>'
Response
{}
Parameters
No parameters.
Returns
Returns a 204
No Content response.
Bundle API
Documentation for the Bundle API is coming soon.
Webhooks
Webhooks play a key role in communicating critical information (in the form of events) among Platform and Publisher Clients and the Paket service. While not technically a part of the Paket API, this section explains how to set up and secure your webhooks endpoints; and serves as a reference as to which notifications are sent and on which triggering events.
Configure your endpoints
Webhooks are configured discretely under each Client object in the Paket Developer Portal. You may configure multiple endpoints, however, please note that at present all events will be sent to all active endpoints.
Webhook endpoints must be secured using TLS/SSL certificates over HTTPS and are signed using a signing secret, provided on creation of each endpoint. While it is possible to receive events without verifying the webhook signature, it is highly recommended that each event is verified before taking any programmatic action.
Verify webhook signature
The Paket-Signature
header included in each signed event contains a timestamp and one or more signatures that you must verify. The timestamp is prefixed by t=
, and each signature is prefixed by a scheme. Schemes start with v
, followed by an integer. Currently, the only valid live signature scheme is v1
. To aid with testing, Paket sends an additional signature with a fake v0
scheme.
Example
Paket-Signature
header
Paket-Signature:
t=1709156882568,
v1=f03a63e17d5720d7d01974d115059c8ec05b0f425828a2d0d341020f431bbafa,
v0=3e3be55cd51ef0476ddf7fe83e72f10cf7358e54dd8eab17560dfb879b9d485a
Paket generates signatures using a hash-based message authentication code (HMAC) with SHA-256. To prevent downgrade attacks, ignore all schemes that aren’t v1
.
You can have multiple signatures with the same scheme-secret pair when you roll an endpoint’s secret, and keep the previous secret active for up to 24 hours. During this time, your endpoint has multiple active secrets and Paket generates one signature for each secret.
To create a manual solution for verifying signatures, you must complete the following steps:
Step 1: Extract the timestamp and signatures from the header
Split the header using the ,
character as the separator to get a list of elements. Then split each element using the =
character as the separator to get a prefix and value pair.
The value for the prefix t
corresponds to the timestamp, and v1
corresponds to the signature (or signatures). You can discard all other elements.
Step 2: Prepare the signed_payload
string
Example
signed_payload
1709156882568.{"idempotency_key":"62a0152b-6ac4-49f7-b605-5e18cbf70ed8","data":{"participant_id":"6b0af623-2923-4997-92a6-73f94bbe321e","client_id":"286d2a536a5d6b6b","app_id":"417f3625d067cbe3","created_at":"2024-03-05T17:56:26.265Z","session_id":"4c682b9e-65b4-4e43-a5e9-96f58a967240"},"type":"participant.session.created","api_version":"2023-12-10","created":1709661388431,"object":"event","id":"req_ad8a67d675a71a89"}
The signed_payload
string is created by concatenating:
- The timestamp (as a string)
- The character
.
- The actual JSON payload (that is, the request body)
Step 3: Determine the expected signature
Example Hashed result
f03a63e17d5720d7d01974d115059c8ec05b0f425828a2d0d341020f431bbafa
Compute an HMAC with the SHA256 hash function. Use the endpoint’s signing secret as the key, and use the signed_payload string as the message.
Step 4: Compare the signatures
Compare the signature (or signatures) in the header to the expected signature. For an equality match, compute the difference between the current timestamp and the received timestamp, then decide if the difference is within your tolerance.
To protect against timing attacks, use a constant-time-string comparison to compare the expected signature to each of the received signatures.
Paket IP addresses
To further protect your endpoints, it is recommended that you implement IP whitelisting of the Paket servers from which you may receive webhook events.
Paket IP Addresses:
54.185.102.16
52.40.235.54
35.83.22.57
Retry behavior
Paket attempts to deliver a given event to your webhook endpoint up to fifteen (15) times over the course of 3 days with an exponential back off. In the Webhooks logs section of the Paket Publisher Portal, you can view when the next retry will occur as well as the event and event data itself.
Events
Events are our way of letting you know when something interesting happens in your account. When an interesting event occurs, we create a new Event
object. For example, when a Participant is added to a Session, we create a participant.session.participant_added
event, and when a bundle subscription is canceled, we create an participant.subscription.canceled
event.
The Event object
Example webhook event
{
"id": "evt_a75f6d23be8c17b1",
"object": "event",
"type": "participant.session.participant_added",
"created": 1709679883853,
"api_version": "2023-12-10",
"request": {
"id": "req_2442fd8627bedb77",
"idempotency_key": null
},
"data": {
"participant_id": "6b0af623-2923-4997-92a6-73f94bbe321e",
"client_id": "286d2a536a5d6b6b",
"app_id": "417f3625d067cbe3",
"created_at": "2024-03-05T23:04:43.684Z",
"session_id": "4c682b9e-65b4-4e43-a5e9-96f58a967240"
}
}
Attributes
id
string
The unique identifier of the webhook event.
object
string
Description of the object type (e.g., event
).
type
string
Description of the event (e.g., participant.session.participant_added
or participant.subscription.canceled
)
created
integer
UTC
timestamp when the event was created.
api_version
string
The Paket API version through which the triggering API request was made.
request
object
An object containing details of the event's triggering API request.
request.id
string
The unique identifier of the event's triggering API request.
request.idempotency_key
string
The idempotency_key
, if any, of the original request. Otherwise null
.
data
object
An object containing the data associated with the event.
Types of events
This is a list of all the types of events we currently send. We may add more at any time, so in developing and maintaining your code, you should not assume that only these types exist.
You’ll notice that these events follow a pattern: resource.event
. Our goal is to design a consistent system that makes things easier to anticipate and code against.
Event
participant.session.deleted
data.object
is a session participant
Occurs when a Session is removed. Sent to the related Publishers only.
participant.session.participant_added
data.object
is a session participant
Occurs when a Participant is added to a Session. Sent to the related Publishers only.
participant.session.participant_removed
data.object
is a session participant
Occurs when a Participant is removed from a Session. Sent to the related Publishers only.
participant.list.item_hidden
data.object
is a list item
Occurs when a Participant user removes or hides an item from their List via the Platform. Sent to the related Publisher only.