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:

Paket API Portal: Credentials

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:

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.

Custom Schema Definition

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:

media_type string
The item's media type, which can be one of the following enum values:

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:

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:

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.

Platform Work Flow Diagram

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.

Publisher Work Flow Diagram

Sessions

Sessions are the primary means by which Platforms interact with the Paket UpNext API.

It is through this API that Platforms can:

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:

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:

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:

Including unfinished movies and TV shows

Please add an up_next_continue item if:

Including new and next episode from a tv series

Remove finished items from the UpNext List

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:

action* string
The item action, which can be one of the following enum values:

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:

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.

Webhooks Configuration

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:

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:

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.