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 that gives connected TV platforms, operators, and telcos access to:

Our suite of APIs is device- and platform-agnostic, designed to increase engagement through personalization, improve discovery, and provide actionable 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.

Tenants and Clients

To begin working with the Paket API, Partners must first create a Tenant in the Paket Developer Portal.

Once a Tenant is created, one or more API Clients can be provisioned. API Clients represent application instances that communicate with the Paket API and exchange data between Tenants. Clients are typically scoped at the application/environment level (e.g., iOS app, Android app, web app, OTT app, dev vs. prod).

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).

Basic Authentication

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.

Obtaining API Credentials

API credentials can 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

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 Request Behavior

Identifying Test Responses

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:

Security Features

Signing API Requests

In addition to Basic Authentication and IP whitelisting, Paket supports optional HMAC-SHA256 payload signing to ensure the integrity and authenticity of the request body. This feature is recommended for clients who want to protect against tampering or replay attacks at the payload level.

How It Works

Each API client uses its existing secret key (provided with the client credentials) to compute an HMAC signature of the request payload. Paket will verify the signature if present, but does not require it unless enforced at the client level.

When a signed request is received, Paket will:

If the headers are not present, the request is still accepted (unless signing is explicitly required for that client).

Headers To Include

To sign your request, add the following headers:

X-Paket-Timestamp string
Unix timestamp in milliseconds

X-Paket-Signature string
sha256= followed by HMAC of payload

Signature Format

Example HMAC-SHA256 payload signing (Node.js)

const crypto = require('crypto')

function signPaketRequest(secretKey, body, timestamp) {
  const payload = `${timestamp}.${body}`
  const signature = crypto
    .createHmac('sha256', secretKey)
    .update(payload)
    .digest('hex')

  return `sha256=${signature}`
}

const secretKey = 'your_client_secret_key'
const body = JSON.stringify({ plan_id: 'xyz', session_id: 'abc' })
const timestamp = Date.now().toString()

const headers = {
  'Authorization': 'Basic base64(username:secret)',
  'Content-Type': 'application/json',
  'X-Paket-Timestamp': timestamp,
  'X-Paket-Signature': signPaketRequest(secretKey, body, timestamp),
}

The signature is computed as:

HMAC_SHA256(secret_key, timestamp + '.' + request_body)

The result should be hex-encoded and prefixed with sha256=.

DELETE Requests Without a Body

When sending a DELETE request (or any request without a body), sign an empty string as the body:

const body = ''  // DELETE usually has no body
const payload = `${timestamp}.${body}`

Securing 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":{"context_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":"context.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.

Errors

Paket uses conventional HTTP response codes to indicate the success or failure of an API request.

HTTP Status Codes

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

Common Error Codes

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.

How It Works

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 succeeds or fails. Subsequent requests with the same key return the same result.

Generating Idempotency Keys

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.

Key Lifecycle

Important Notes

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.

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 by region or specific countries.

For example, a Platform may require a custom app identifier, custom_app_id, is returned in API responses. In order to ensure such custom app identifier is provided by a Publisher's service, the Platform will configure this custom attribute from within their Tenant environment 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 a Platform, the Publisher will configure the requested custom attribute, in this case the custom_app_id, from within their respective App Tenant environment. This data will then be returned in subsequent Platform API responses under the platform_data attribute.

Taking this example further, perhaps the Platform 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 App'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

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 Participants' Lists. These list API methods share a common structure and can accept the following two parameters: limit and next_key.

Pagination Response Format

Response Example

{
    "total": 24,
    "next_key": 6,
    "items": [
        {...},
        {...},
        {...},
        {...},
        {...}
    ]
}

Parameters

limit integer
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.

next_key string/integer
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 2024-12-01. For information on all API updates, view our API changelog.

Version Management

Default Version

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 Versioning

Webhook events also use your account's API version by default, unless you set an API version during endpoint creation.

Upgrading Your API Version

You can upgrade your API version in the Paket Developer Portal.

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",
    "app_id": "AP467777522151985152"
}

Attributes

message string
The API Status message.

client_id string
The unique identifier of the requesting Client.

app_id string
The unique identifier of the requesting Client's App (returned if requesting tenant is an App).

platform_id string
The unique identifier of the requesting Client's App (returned if requesting tenant is a Platform).

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

HTTP/1.1 200 OK
Content-Type: application/json
{
    "message": "The API is healthy!",
    "client_id: "fab3d02606122a08",
    "app_id: "AP467777522151985152"
}

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": "759077888463135026",
  "client_id": "907785425416524528",
  "platform_id": "PL442217472463772054",
  "created_at": "2024-02-16T04:41:06.596Z"
}

Attributes

session_id string
A unique Session identifier.

client_id string
The requesting Client ID.

platform_id string
The Platform to which the requesting Client belongs.

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

HTTP/1.1 200 OK
Content-Type: application/json
{
  "session_id": "759077888463135026",
  "client_id": "907785425416524528",
  "platform_id": "PL442217472463772054",
  "created_at": "2024-02-16T04:41:06.596Z"
}

Returns

Returns a status object.

Contexts

Endpoint

POST https://api.paket.tv/v1/contexts

A Context is a unique identifier representing a Publisher or app's end user either at the account or profile level. Also referred to as a "Participant," whether it is associated to the account or profile is, ultimately, up to the Publisher to determine. For optimal flexibility, however, a Context should be created and stored by a Publisher at the profile level.

Ideally, a Context should be indefinitely associated with an end-user's account or profile. So long as the Context ID persists, all items associated with the Context will remain active.

Generally, a Publisher interacts with a Platform by explicitly sharing the Context ID with a Platform and it being matched to an active Session.

The Context Object

The Context Object

{
  "context_id": "CX467798389036421120",
  "client_id": "f02d9e4750febfa4",
  "app_id": "AP463772054442217472",
  "created_at": "2024-02-16T04:41:06.596Z"
}

Attributes

context_id string
The newly generated Context ID.

client_id string
The requesting Client ID.

app_id string
The App to which the requesting Client belongs.

created_at string
The ISO 8601 timestamp when the Session was created.

Create a new Context

POST https://api.paket.tv/v1/contexts

curl --location --request POST 'https://api.paket.tv/v1/contexts' \
    --header 'Accept: application/json' \
    --header 'Authorization: Basic <credentials>'

Response

HTTP/1.1 200 OK
Content-Type: application/json
{
  "context_id": "CX467798389036421120",
  "client_id": "f02d9e4750febfa4",
  "app_id": "AP463772054442217472",
  "created_at": "2024-02-16T04:41:06.596Z"
}

Parameters

No parameters.

Returns

Returns a Context object.

Catalog API

Overview

The Paket Catalog API is a entitlements and subscription orchestration service that enables Platforms and Publishers to offer comprehensive subscription bundles through a unified catalog via their native billing and identity systems. This API provides access to curated plan offerings, subscription management, and invoice management capabilities that power the Paket subscription marketplace.

For Platforms, the Catalog API offers a seamless way to integrate third-party subscription services into their ecosystem, providing users with bundled offerings that combine multiple streaming services, apps, and digital content into single, manageable subscriptions.

For Publishers, the Catalog API ensures consistent subscription management across all Paket-integrated platforms, with unified billing, activation workflows, and revenue distribution handled automatically through the Paket infrastructure.

To get started, a Publisher must first configure their service via the Paket Publisher Portal. There, Publishers will be able to set up webhook endpoints, security, and API clients through which the service will communicate with the Paket service. It is in the Publisher Portal where Publishers will be able to set up product licenses and assign them for sale through approved Platform partners.

It is also in the Paket Publisher Portal where Platforms will configure API clients and configure plans and bundles for sale via the Paket API.

Subscription Activation Flow

Paket's subscription orchestration service works independently of the Platform's payment and identity services and the app Publishers' respective identity services. This affords both Platform and Publisher direct ownership of the respective user's accounts and enhanced privacy for the end user.

Create Sub Sequence Diagram

Create New Subscription

  1. Platform Creates Subscription: Platform calls POST /v1/catalog/subscriptions with user's session ID and selected plan
  2. Invoice Generation: Paket automatically generates the first invoice for the billing period
  3. Platform Processes Payment: Platform collects payment through their payment service provider (PSP)
  4. Payment Recording: Platform posts payment result to POST /v1/catalog/subscriptions/{subscription_id}/invoices/{invoice_id}/payments
  5. Subscription Activation: On successful payment, Paket returns activation URLs for each of the plan's products and triggers the app activation flow
  6. Publisher Notification: Publishers receive activation.session.created webhooks for new subscriptions requiring activation. The webhook includes a jti (JWT identifier) for security validation.

Product Activation

  1. User Arrives: User visits activation URL with their unique activation code
  2. Code Validation: Publisher validates the activation code via POST /v1/catalog/activation/exchange, which returns the purchased product details and the jti for cross-reference validation.
  3. Account Setup: Publisher validates the product and completes user sign-up or sign-in process
  4. Activation Confirmation: Publisher calls PUT /v1/catalog/activation/{session_id}/items/{item_id} to confirm activation.
  5. Service Provisioning: Publisher provisions the service for the activated user

Request to Exchange Activation Code

curl --location --request POST 'https://api.paket.tv/v1/catalog/activation/exchange' \
  --header 'Content-Type: application/json' \
  --header 'Authorization: Basic <credentials>' \
  --data '{
    "activation_code": "AC_A3F2B7C9_D4E1F8A2"
  }'

Response with Product Details

{
  "activation_session_id": "AS479027832456789123",
  "app_id": "AP468442205989113856",
  "product_id": "PR469716925099413504",
  "subscription_id": "SUB479027832035610624",
  "platform_id": "PL468440696748511232",
  "jti": "at_479027832567890234",
  "product": {
    "product_id": "PR469716925099413504",
    "product_name": "Disney+ Basic",
    "internal_id": "disney_basic_tier1"
  }
}

Important Notes

Subscription Renewal Flow

Paket handles subscription renewals automatically through its billing orchestration system. The renewal process ensures continuity of service and a single source of truth while maintaining proper billing cycles and platform revenue distribution.

Renew Sub Sequence Diagram

  1. Invoice Generation: On the billing date, Paket automatically generates a new invoice for the next billing cycle
  2. Platform Notification: Platform receives notification about the new invoice
  3. Payment Processing: Platform collects payment through their payment service provider (PSP)
  4. Payment Confirmation: Platform records payment result via POST /v1/catalog/subscriptions/{subscription_id}/invoices/{invoice_id}/payments
  5. Renewal Completion: On successful payment, subscription billing cycle advances and service continues
  6. Publisher Updates: Publishers receive subscription.renewed webhook confirming successful renewal

Subscription Cancellation Flow

Subscription cancellations can be initiated either by platforms (e.g., at user's request) or programmatically when an unpaid invoice lapses its grace period and are handled gracefully to ensure proper service termination and final billing reconciliation.

Cancel Sub Sequence Diagram

  1. Cancellation Request: Platform initiates cancellation via PUT /v1/catalog/subscriptions/{subscription_id} with status "canceled"
  2. Final Billing: Paket calculates any pro-rated charges or credits based on cancellation timing
  3. Publisher Notification: Publishers receive subscription.canceled webhook event with cancellation details
  4. Service Termination: Publishers deactivate services for the canceled subscription
  5. Grace Period: Optional grace period allows users to maintain access until the end of the current billing period
  6. Final Invoice: If applicable, Paket generates a final invoice for any outstanding charges
  7. Subscription Closure: Subscription status changes to "canceled" and no future invoices are generated

Plans

Plans define the subscription offerings available through the Paket catalog, including pricing, billing cycles, and bundled services.

The Plan Object

The Plan object represents the template from which a Subcription is created. It itemizes which licenses are include in the plan, pricing, availability, localizations, billing cycles, bundled services configuration, and more.

The Plan Object

{
  "plan_id": "427944e5ba9e",
  "name": "Disney+, Hulu, HBO Max Bundle",
  "plan_type": "sub_bundle",
  "status": "active",
  "platform_id": "PL468440696748511232",
  "billing_frequency": { 
    "unit": "month", 
    "value": 1 
  },
  "free_trial_days": 7,
  "grace_period_days": 7,
  "media": {
    "promo_4k_1x": "https://media.paket.tv/media/plans/PL468440696748511232/427944e5ba9e/promo_4k@1x.png",
    "promo_2k_1x": "https://media.paket.tv/media/plans/PL468440696748511232/427944e5ba9e/promo_2k@1x.png"
  },
  "prices": {
    "US": [
      {
        "order": 1,
        "billing_cycles": 3,
        "price": {
          "price_in_cents": 1699,
          "tier_id": "1699",
          "currency_code": "USD",
          "price": 16.99
        }
      }
    ]
  },
  "localizations": {
    "en-us": {
        "description": "The bundle with everything you need",
        "display_name": "Disney+, Hulu, HBO Max Bundle"
    }
  },
  "plan_items": [
    {
        "status": "active",
        "price_wholesale": {
            "price": 4.56,
            "price_in_cents": 456,
            "currency_code": "USD"
        },
        "name": "Disney+ Basic",
        "app_id": "AP468442205989113856",
        "product_id": "PR469716925099413504",
        "localizations": {
            "en-us": {
                "description": "Disney+ Basic With Ads",
                "display_name": "Disney+ Basic"
            }
        },
        "prices": {
            "US": {
                "price_in_cents": 999,
                "tier_id": "999",
                "currency_code": "USD",
                "price": 9.99
            }
        },
        "app": {
            "id": "AP468442205989113856",
            "name": "Disney+",
            "media": {
                "icon_1x": "https://media.paket.tv/media/apps/AP468442205989113856/icon@1x.png",
                "icon_2x": "https://media.paket.tv/media/apps/AP468442205989113856/icon@2x.png",
                "icon_3x": "https://media.paket.tv/media/apps/AP468442205989113856/icon@3x.png",
                "logo_dark_1x": "https://media.paket.tv/media/apps/AP468442205989113856/logo_dark@1x.png",
                "logo_light_1x": "https://media.paket.tv/media/apps/AP468442205989113856/logo_light@1x.png",
                "tile_1x": "https://media.paket.tv/media/apps/AP468442205989113856/tile@1x.png",
                "tile_2x": "https://media.paket.tv/media/apps/AP468442205989113856/tile@2x.png"
            },
            "status": "live"
        }
    },
    ...
  ],
  "metadata": {},
  "created_at": "2024-01-15T10:30:00.000Z",
  "updated_at": "2024-01-17T07:28:00.000Z"
}

Attributes

plan_id string
The unique identifier for the plan.

name string
The internal name of the plan.

plan_type string
The type of plan, which can be one of the following enum values:

status string
The current status of the plan:

platform_id string
The platform identifier associated with this plan.

billing_frequency object
The billing cycle configuration:

   unit string
   Billing unit (month, year)

   value integer
   Billing frequency value (1, 3, 6, 12)

free_trial_days integer
Number of free trial days offered (0 if no trial).

grace_period_days integer
Number of days after payment failure before subscription suspension.

media object
URLs to promotional media assets for the plan:

   promo_4k_1x string
   4K promotional image URL

   promo_2k_1x string
   2K promotional image URL

prices object
Regional pricing information organized by country code. Each region contains an array of pricing phases:

   order integer
   The sequence order of the pricing phase

   billing_cycles integer
   Number of cycles this price applies to (null if indefinite)

   price object
   Price object containing:

      price_in_cents integer
      Price in cents as an integer

      tier_id string
      Pricing tier identifier

      currency_code string
      Three-letter ISO currency code

      price number
      Price as a decimal

localizations object
Localized content organized by language code (e.g., "en-us"):

   description string
   Localized description of the plan

   display_name string
   Localized display name for the plan

plan_items array
Array of products or entitlements included in the plan. Each item contains:

   status string
   Item status (active, inactive)

   price_wholesale object
   Wholesale pricing information with price, price_in_cents, and currency_code

   name string
   Internal name of the product

   app_id string
   Associated app identifier

   product_id string
   Unique product identifier

   localizations object
   Localized content for the product (description and display_name)

   prices object
   Regional retail pricing by country

   app object
   App object containing:

      id string
      App identifier

      name string
      App name

      media object
      App media assets (icons, logos, tiles)

      status string
      App status (live, inactive)

created_at string
ISO 8601 timestamp when the plan was created.

updated_at string
ISO 8601 timestamp when the plan was last updated.

List Plans

Endpoint

GET https://api.paket.tv/v1/catalog/plans

Retrieves a list of available Plans from the catalog.

GET https://api.paket.tv/v1/catalog/plans

curl --location 'https://api.paket.tv/v1/catalog/plans' \
  --header 'Accept: application/json' \
  --header 'Authorization: Basic <credentials>'

Response

HTTP/1.1 200 OK
Content-Type: application/json
{
    "items": [
        {
            "billing_frequency": {
                "unit": "month",
                "value": 1
            },
            "free_trial_days": 0,
            "plan_type": "sub_bundle",
            "updated_at": "2025-08-15T14:59:34+00:00",
            "platform_id": "PL468440696748511232",
            "name": "Disney+, Hulu, HBO Max Bundle",
            "media": {
                "promo_4k_1x": "https://media-dev.paket.tv/media/plans/PL468440696748511232/427944e5ba9e/promo_4k@1x.png",
                "promo_2k_1x": "https://media-dev.paket.tv/media/plans/PL468440696748511232/427944e5ba9e/promo_2k@1x.png"
            },
            "plan_id": "427944e5ba9e",
            "status": "active",
            "localizations": {
                "en-us": {
                    "description": "The bundle with everything you need",
                    "display_name": "Disney+, Hulu, HBO Max Bundle"
                }
            },
            "prices": {
                "US": [
                    {
                        "order": 1,
                        "billing_cycles": null,
                        "price": {
                            "price_in_cents": 1699,
                            "tier_id": "1699",
                            "currency_code": "USD",
                            "price": 16.99
                        }
                    }
                ]
            }
            "created_at": "2025-07-20T04:17:16+00:00",
            "updated_at": "2025-08-20T02:11:13+00:00",
        }
    ],
    "total": 1,
    "next_key": null
}

* required

Headers

Authorization* string
Your API credentials for authentication.

Query Parameters

limit integer
Optional. Number of plans to return (1-100, default: 25).

next_key integer
Optional. Pagination key from previous response.

language string or array
Optional. Language code(s) for localized content (default: ["en-us"]).

region string or array
Optional. Region code(s) to filter plans by availability (e.g., "US", "CA").

Returns

Returns an array of Plan objects (without plan_items array) available in the catalog.

Get Plan

Endpoint

GET https://api.paket.tv/v1/catalog/plans/:plan_id

Retrieves detailed information about a specific plan.

GET https://api.paket.tv/v1/catalog/plans/:plan_id

curl --location 'https://api.paket.tv/v1/catalog/plans/427944e5ba9e' \
  --header 'Accept: application/json' \
  --header 'Authorization: Basic <credentials>'

Response

HTTP/1.1 200 OK
Content-Type: application/json
{
  "plan_id": "427944e5ba9e",
  "name": "Disney+, Hulu, HBO Max Bundle",
  "plan_type": "sub_bundle",
  "status": "active",
  "platform_id": "PL468440696748511232",
  "free_trial_days": 0,
  "grace_period_days": 7,
  "billing_frequency": {
    "unit": "month",
    "value": 1
  },
  "media": {
    "promo_4k_1x": "https://media.paket.tv/media/plans/PL468440696748511232/427944e5ba9e/promo_4k@1x.png",
    "promo_2k_1x": "https://media.paket.tv/media/plans/PL468440696748511232/427944e5ba9e/promo_2k@1x.png"
  },
  "prices": {
    "US": [
      {
        "order": 1,
        "billing_cycles": 3,
        "price": {
          "price_in_cents": 1699,
          "tier_id": "1699",
          "currency_code": "USD",
          "price": 16.99
        }
      }
    ]
  },
  "localizations": {
    "en-us": {
        "description": "The bundle with everything you need",
        "display_name": "Disney+, Hulu, HBO Max Bundle"
    }
  },
  "plan_items": [
    {
        "status": "active",
        "price_wholesale": {
            "price": 4.56,
            "price_in_cents": 456,
            "currency_code": "USD"
        },
        "name": "Disney+ Basic",
        "app_id": "AP468442205989113856",
        "product_id": "PR469716925099413504",
        "localizations": {
            "en-us": {
                "description": "Disney+ Basic With Ads",
                "display_name": "Disney+ Basic"
            }
        },
        "prices": {
            "US": {
                "price_in_cents": 999,
                "tier_id": "999",
                "currency_code": "USD",
                "price": 9.99
            }
        },
        "app": {
            "id": "AP468442205989113856",
            "name": "Disney+",
            "media": {
                "icon_1x": "https://media.paket.tv/media/apps/AP468442205989113856/icon@1x.png",
                "icon_2x": "https://media.paket.tv/media/apps/AP468442205989113856/icon@2x.png",
                "icon_3x": "https://media.paket.tv/media/apps/AP468442205989113856/icon@3x.png",
                "logo_dark_1x": "https://media.paket.tv/media/apps/AP468442205989113856/logo_dark@1x.png",
                "logo_light_1x": "https://media.paket.tv/media/apps/AP468442205989113856/logo_light@1x.png",
                "tile_1x": "https://media.paket.tv/media/apps/AP468442205989113856/tile@1x.png",
                "tile_2x": "https://media.paket.tv/media/apps/AP468442205989113856/tile@2x.png"
            },
            "status": "live"
        }
    },
    ...
  ],
  "created_at": "2024-01-15T10:30:00.000Z",
  "updated_at": "2024-01-17T07:28:00.000Z"
}

* required

Headers

Authorization* string
Your API credentials for authentication.

Path Parameters

plan_id* string
The unique identifier of the plan to retrieve.

Query Parameters

region string
Optional. Region for pricing information (default: "US").

Returns

Returns a detailed Plan object with complete pricing, plan items, and phase information.

Subscriptions

Subscriptions represent a relationship between users and plans, managing billing cycles, activation, invoices, and payments. In a typical configuration, Paket operates exclusively as the orchestration layer and the Platform acts as the Merchant of Record, determining when and if an invoice is taxable, in which juristiction, at what amount, and whether the tax should be applied exclusive or inclusive of the plan price.

The Subscription Object

The Subscription object represents an active or inactive Subscription to a Plan, tracking billing cycles, payment status, and activation state.

The Subscription Object

{
  "subscription_id": "SUB479027832035610624",
  "session_id": "SN468560588960960512",
  "plan_id": "427944e5ba9e",
  "platform_id": "PL468440696748511232",
  "status": "active",
  "activation_status": "pending",
  "payment_status": "paid",
  "billing": {
    "next_billing_date": "2025-09-14T20:45:35.064Z",
    "frequency": { "unit": "month", "value": 1 },
    "cycle_count": 1,
    "current_phase_id": "4282b4cfac23dc38",
    "grace_period_days": 7,
    "grace_period_end": "2025-09-21T20:45:35.064Z",
    "interval_days": 30
  },
  "trial": {
    "days": 7,
    "end_date": "2025-08-21T20:45:35.064Z"
  },
  "period": {
    "start": "2025-08-14T20:45:35.065Z",
    "end": "2025-09-14T20:45:35.064Z"
  },
  "tax": {
    "rate": 0.0875,
    "type": "sales_tax",
    "jurisdiction": "CA-Los Angeles",
    "behavior": "exclusive",
    "note": ""
  },
  "plan": {
    "name": "Disney+, Hulu, HBO Max Bundle",
    "type": "sub_bundle"
  },
  "cancellation": {
    "cancel_at_period_end": false,
    "canceled_at": null,
    "ended_at": null
  },
  "proration_credit": 0,
  "metadata": {},
  "device_info": {},
  "created_ip": "75.85.168.125",
  "updated_ip": "75.85.168.125",
  "created_at": "2025-08-14T20:45:35.065Z",
  "updated_at": "2025-08-14T21:00:00.000Z"
}

Attributes

subscription_id string
The unique identifier for the subscription (prefixed with SUB).

session_id string
The session identifier associated with this subscription.

plan_id string
The plan identifier this subscription is for.

billing object
Billing information:

   next_billing_date string
   ISO 8601 timestamp of the next billing date

   frequency object
   Billing frequency configuration with unit and value

   cycle_count number
   Total number of completed billing cycles

   current_phase_id string
   The current phase price identifier

   grace_period_days number
   Grace period during which subscription remains active after failed payment

   grace_period_end string
   ISO 8601 timestamp of the current grace period end

   interval_days number
   Billing interval in days

platform_id string
The platform identifier issuing the plan.

status string
Current subscription status:

activation_status string
Publisher activation status:

payment_status string
Current payment status:

trial object
Trial information (only present if trial exists):

   days number
   Days included in free trial

   end_date string
   ISO 8601 timestamp of the trial period end

period object
Billing period dates:

   start string
   ISO 8601 start of current billing period

   end string
   ISO 8601 end of current billing period

tax object
Tax information:

   rate number
   Applied tax rate (0-1, e.g., 0.0875 for 8.75%)

   type string
   Type of tax (sales_tax, vat, gst, pst, hst, none)

   jurisdiction string
   Tax jurisdiction code

   behavior string
   Tax collection behavior (inclusive, exclusive, none)

   note string
   Additional tax notes

plan object
Plan information:

   name string
   The plan name

   type string
   Plan type (sub_bundle, sub_single)

cancellation object
Cancellation information:

   cancel_at_period_end boolean
   Whether to cancel subscription at end of current period

   canceled_at string
   ISO 8601 timestamp of cancellation date (null if not canceled)

   ended_at string
   ISO 8601 timestamp of subscription end date (null if not ended)

proration_credit number
Amount to credit or add to first invoice if mid-cycle upgrade or downgrade.

metadata object
Additional custom metadata for the subscription.

device_info object
Additional device metadata for the subscription.

created_ip string
The IP address from where the subscription was created.

updated_ip string
The IP address from where subscription was last updated.

created_at string
ISO 8601 timestamp when the subscription was created.

updated_at string
ISO 8601 timestamp when the subscription was last updated.

Create Subscription

Endpoint

POST https://api.paket.tv/v1/catalog/subscriptions

Creates a new subscription for a session with automatic invoice generation.

POST https://api.paket.tv/v1/catalog/subscriptions

curl --location 'https://api.paket.tv/v1/catalog/subscriptions?region=US' \
  --header 'Content-Type: application/json' \
  --header 'Authorization: Basic <credentials>'
  --header 'Idempotency-Key: unique-operation-123' \
  --data '{
    "session_id": "session_456",
    "plan_id": "427944e5ba9e",
    "tax_rate": 0.0875,
    "tax_type": "sales_tax",
    "tax_jurisdiction": "CA-Los Angeles",
    "tax_behavior": "exclusive",
    "tax_note": "",
    "device_info": {
      "device_type": "roku",
      "device_id": "FA1234567890"
    },
    "metadata": {
      "source": "homepage_banner",
      "campaign": "summer_promo"
    }
  }'

Response

HTTP/1.1 201 Created
Content-Type: application/json
{
  "subscription": {
    "subscription_id": "SUB479027832035610624",
    "session_id": "session_456",
    "plan_id": "427944e5ba9e",
    "platform_id": "PL468440696748511232",
    "status": "pending",
    "activation_status": "pending",
    "payment_status": "unpaid",
    "billing": {
      "next_billing_date": "2025-09-14T20:45:35.064Z",
      "frequency": { "unit": "month", "value": 1 },
      "cycle_count": 0,
      "current_phase_id": "4282b4cfac23dc38",
      "grace_period_days": 7,
      "grace_period_end": "2025-09-21T20:45:35.064Z",
      "interval_days": 30
    },
    "trial": {
      "days": 0,
      "end_date": null
    },
    "period": {
      "start": "2025-08-14T20:45:35.065Z",
      "end": "2025-09-14T20:45:35.064Z"
    },
    "tax": {
      "rate": 0.0875,
      "type": "sales_tax",
      "jurisdiction": "CA-Los Angeles",
      "behavior": "exclusive",
      "note": ""
    },
    "plan": {
      "name": "Disney+, Hulu, HBO Max Bundle",
      "type": "sub_bundle"
    },
    "cancellation": {
      "cancel_at_period_end": false,
      "canceled_at": null,
      "ended_at": null
    },
    "activation": {
      "url": null,
      "token": null
    },
    "metadata": {
      "source": "homepage_banner",
      "campaign": "summer_promo"
    },
    "device_info": {
      "device_type": "roku",
      "device_id": "FA1234567890"
    },
    "created_ip": "75.85.168.125",
    "updated_ip": "75.85.168.125",
    "created_at": "2025-08-14T20:45:35.065Z",
    "updated_at": "2025-08-14T20:45:35.065Z"
  },
  "invoice": {
    "invoice_id": "INV479027832278880256",
    "invoice_number": "INV-2025-78880256",
    "subscription_id": "SUB479027832035610624",
    "session_id": "session_456",
    "status": "open",
    "payment_status": "unpaid",
    "currency": "USD",
    "region": "US",
    "amounts": {
      "subtotal": 1699,
      "proration_credit": 0,
      "tax_amount": 149,
      "total_amount": 1848,
      "amount_due": 1848,
      "amount_paid": 0
    },
    "tax": {
      "rate": 0.0875,
      "type": "sales_tax",
      "jurisdiction": "CA-Los Angeles",
      "behavior": "exclusive",
      "note": ""
    },
    "plan": {
      "plan_id": "427944e5ba9e",
      "name": "Disney+, Hulu, HBO Max Bundle",
      "type": "sub_bundle",
      "phase_id": "4282b4cfac23dc38",
      "phase_order": 1,
      "billing_cycle": 1,
      "platform_fee_rate": 0.15,
      "platform_fee_amount": 255
    },
    "period": {
      "start": "2025-08-14T20:45:35.065Z",
      "end": "2025-09-14T20:45:35.064Z",
      "invoice_date": "2025-08-14T20:45:35.122Z",
      "due_date": "2025-09-13T20:45:35.122Z"
    },
    "retries": {
      "count": 0,
      "max": 3,
      "next_date": null,
      "last_date": null,
      "delay_minutes": 60
    },
    "metadata": {},
    "created_ip": "75.85.168.125",
    "updated_ip": "75.85.168.125",
    "created_at": "2025-08-14T20:45:35.122Z",
    "updated_at": "2025-08-14T20:45:35.122Z"
  }
}

Headers

* required

Authorization* string
Your API credentials for authentication.

Idempotency-Key string
Optional but recommended. Unique key to prevent duplicate subscriptions.

Query Parameters

region string
Optional. Pricing region (default: "US").

Request Body

* required

session_id* string
The user session identifier.

plan_id* string
The plan to subscribe to.

tax_behavior string
Optional. Specifies whether tax should be collected and how (default: "none"). Valid values:

tax_rate number
Optional. Tax rate to apply as decimal percentage (0-1, default: 0).

tax_type string
Optional. Type of tax (default: "none"). Valid values:

tax_jurisdiction string
Optional. Tax jurisdiction code (e.g., "CA-Los Angeles").

tax_note string
Optional. Additional notes pertaining to the subscription tax.

device_info object
Optional. Device information for tracking and analytics.

metadata object
Optional. Additional metadata for the subscription.

Returns

Returns an Invoice object for the created subscription.

Update Subscription

Endpoint

PUT https://api.paket.tv/v1/catalog/subscriptions/:subscription_id

Updates an existing subscription's status, payment method, or other properties.

PUT https://api.paket.tv/v1/catalog/subscriptions/:subscription_id

curl --location --request PUT 'https://api.paket.tv/v1/catalog/subscriptions/SUB479027832035610624' \
  --header 'Content-Type: application/json' \
  --header 'Accept: application/json' \
  --header 'Authorization: Basic <credentials>'
  --header 'Idempotency-Key: unique-update-456' \
  --data '{
    "status": "active",
    "payment_method_id": "pm_123",
    "activation_url": "https://activate.disney.com/paket/abc123",
    "activation_token": "token_xyz789"
  }'

Response

HTTP/1.1 200 OK
Content-Type: application/json
{
  "subscription_id": "SUB479027832035610624",
  "session_id": "session_456",
  "plan_id": "427944e5ba9e",
  "platform_id": "PL468440696748511232",
  "status": "active",
  "activation_status": "pending",
  "payment_status": "paid",
  "billing": {
    "next_billing_date": "2025-09-14T20:45:35.064Z",
    "frequency": { "unit": "month", "value": 1 },
    "cycle_count": 1,
    "current_phase_id": "4282b4cfac23dc38",
    "grace_period_days": 7,
    "grace_period_end": null,
    "interval_days": 30
  },
  "period": {
    "start": "2025-08-14T20:45:35.065Z",
    "end": "2025-09-14T20:45:35.064Z"
  },
  "tax": {
    "rate": 0.0875,
    "type": "sales_tax",
    "jurisdiction": "CA-Los Angeles",
    "behavior": "exclusive",
    "note": ""
  },
  "plan": {
    "name": "Disney+, Hulu, HBO Max Bundle",
    "type": "sub_bundle"
  },
  "cancellation": {
    "cancel_at_period_end": false,
    "canceled_at": null,
    "ended_at": null
  },
  "activation": {
    "url": "https://activate.disney.com/paket/abc123",
    "token": "token_xyz789"
  },
  "metadata": {},
  "device_info": {},
  "created_ip": "75.85.168.125",
  "updated_ip": "75.85.168.125",
  "created_at": "2025-08-14T20:45:35.065Z",
  "updated_at": "2025-08-14T21:00:00.000Z"
}

Path Parameters

* required

subscription_id* string
The subscription ID to update.

Headers

* required

Authorization* string
Your API credentials for authentication.

Content-Type* string
Must be application/json.

Idempotency-Key string
Optional but recommended. Unique key to prevent duplicate updates.

Request Body

At least one field is required.

status string
Optional. Update subscription status. Valid values: - trialing - active - past_due - canceled - unpaid - paused

payment_method_id string
Optional. Payment method identifier.

cancel_at_period_end boolean
Optional. Schedule cancellation at end of current period.

plan_id string
Optional. Change to a different plan.

activation_url string
Optional. Publisher activation URL.

activation_token string
Optional. Token for activation process.

tax_rate number
Optional. Update tax rate (0-1).

tax_type string
Optional. Update tax type.

tax_jurisdiction string
Optional. Update tax jurisdiction.

tax_behavior string
Optional. Update tax behavior.

tax_note string
Optional. Update tax note.

metadata object
Optional. Update metadata.

Returns

Returns the updated Subscription object.

Get Subscription

Endpoint

GET https://api.paket.tv/v1/catalog/subscriptions/:subscription_id

Retrieves details of a specific subscription.

GET https://api.paket.tv/v1/catalog/subscriptions/:subscription_id

curl --location 'https://api.paket.tv/v1/catalog/subscriptions/SUB479027832035610624' \
  --header 'Accept: application/json' \
  --header 'Authorization: Basic <credentials>'

Response

HTTP/1.1 200 OK
Content-Type: application/json
{
  "subscription_id": "SUB479027832035610624",
  "session_id": "session_456",
  "plan_id": "427944e5ba9e",
  "platform_id": "PL468440696748511232",
  "status": "active",
  "activation_status": "pending",
  "payment_status": "paid",
  "billing": {
    "next_billing_date": "2025-09-14T20:45:35.064Z",
    "frequency": { "unit": "month", "value": 1 },
    "cycle_count": 1,
    "current_phase_id": "4282b4cfac23dc38",
    "grace_period_days": 7,
    "grace_period_end": null,
    "interval_days": 30
  },
  "trial": {
    "days": 0,
    "end_date": null
  },
  "period": {
    "start": "2025-08-14T20:45:35.065Z",
    "end": "2025-09-14T20:45:35.064Z"
  },
  "tax": {
    "rate": 0.0875,
    "type": "sales_tax",
    "jurisdiction": "CA-Los Angeles",
    "behavior": "exclusive",
    "note": ""
  },
  "plan": {
    "name": "Disney+, Hulu, HBO Max Bundle",
    "type": "sub_bundle"
  },
  "cancellation": {
    "cancel_at_period_end": false,
    "canceled_at": null,
    "ended_at": null
  },
  "metadata": {},
  "device_info": {},
  "created_ip": "75.85.168.125",
  "updated_ip": "75.85.168.125",
  "created_at": "2025-08-14T20:45:35.065Z",
  "updated_at": "2025-08-14T21:00:00.000Z"
}

Headers

Authorization* string
Your API credentials for authentication.

Path Parameters

* required

subscription_id* string
The subscription ID to retrieve.

Returns

Returns a complete Subscription object.

List Subscriptions

Endpoint

GET https://api.paket.tv/v1/catalog/subscriptions

Lists subscriptions for a specific session.

GET https://api.paket.tv/v1/catalog/subscriptions

curl --location 'https://api.paket.tv/v1/catalog/subscriptions?session_id=session_456&limit=50' \
  --header 'Accept: application/json' \
  --header 'Authorization: Basic <credentials>'

Response

HTTP/1.1 200 OK
Content-Type: application/json
{
  "subscriptions": [
    {
      "subscription_id": "SUB479027832035610624",
      "plan_id": "427944e5ba9e",
      "plan_name": "Disney+, Hulu, HBO Max Bundle",
      "status": "active",
      "payment_status": "paid",
      "next_billing_date": "2025-09-14T20:45:35.064Z",
      "total_amount_due": 1848,
      "currency": "USD",
      "created_at": "2025-08-14T20:45:35.065Z"
    },
    {
      "subscription_id": "SUB479025528242835456",
      "plan_id": "netflix_standard",
      "plan_name": "Netflix Standard",
      "status": "trialing",
      "payment_status": "no_payment_required",
      "next_billing_date": "2025-08-21T10:30:00.000Z",
      "total_amount_due": 0,
      "currency": "USD",
      "created_at": "2025-08-07T10:30:00.000Z"
    }
  ],
  "lastEvaluatedKey": null
}

Headers

* required

Authorization* string
Your API credentials for authentication.

Query Parameters

session_id* string
The session ID to list subscriptions for.

limit integer
Optional. Number of results to return (1-100, default: 25).

Returns

Returns an array of summarized Subscription objects.

Invoices

Invoices track billing statements for subscription periods.

The Invoice Object

The Invoice object represents a billing statement for a subscription period, tracking amounts, payment status, and retry logic.

The Invoice Object

{
  "invoice_id": "INV479027832278880256",
  "invoice_number": "INV-2025-78880256",
  "subscription_id": "SUB479027832035610624",
  "platform_id": "PL468440696748511232",
  "session_id": "session_456",
  "status": "open",
  "payment_status": "unpaid",
  "currency": "USD",
  "region": "US",
  "amounts": {
    "subtotal": 1699,
    "proration_credit": 0,
    "tax_amount": 149,
    "total_amount": 1848,
    "amount_due": 1848,
    "amount_paid": 0
  },
  "tax": {
    "rate": 0.0875,
    "type": "sales_tax",
    "jurisdiction": "CA-Los Angeles",
    "behavior": "exclusive",
    "note": ""
  },
  "payment": {
    "method_id": null,
    "intent_id": null,
    "date": null
  },
  "retries": {
    "count": 0,
    "max": 3,
    "next_date": null,
    "last_date": null,
    "delay_minutes": 60
  },
  "plan": {
    "plan_id": "427944e5ba9e",
    "name": "Disney+, Hulu, HBO Max Bundle",
    "type": "recurring",
    "phase_id": "4282b4cfac23dc38",
    "phase_order": 1,
    "billing_cycle": 1,
    "platform_fee_rate": 0.03,
    "platform_fee_amount": 51
  },
  "period": {
    "start": "2025-08-14T20:45:35.065Z",
    "end": "2025-09-14T20:45:35.064Z",
    "invoice_date": "2025-08-14T20:45:35.122Z",
    "due_date": "2025-09-13T20:45:35.122Z"
  },
  "metadata": {},
  "created_ip": "192.168.1.1",
  "updated_ip": "192.168.1.1",
  "created_at": "2025-08-14T20:45:35.122Z",
  "updated_at": "2025-08-14T20:45:35.122Z"
}

Attributes

Core Fields

invoice_id string
The unique identifier for the invoice (prefixed with INV).

invoice_number string
Human-readable invoice number.

subscription_id string
The subscription this invoice belongs to.

platform_id string
The platform identifier that created the subscription.

session_id string
The session identifier associated with this invoice's subscription.

status string
Invoice status: - open - Awaiting payment - paid - Fully paid - draft - Not yet finalized

payment_status string
Payment collection status: - unpaid - Not yet paid - paid - Successfully paid - failed - Payment failed - processing - Payment in progress - canceled - Payment canceled - scheduled - Payment scheduled for future date - no_payment_required - No payment needed (e.g., free trial)

currency string
Three-letter ISO currency code.

region string
Region code for pricing (e.g., "US").

amounts object
Grouped financial amounts:

   subtotal integer
   Pre-tax amount in cents

   proration_credit integer
   Proration credit applied in cents

   tax_amount integer
   Tax amount in cents

   total_amount integer
   Total amount including tax in cents

   amount_due integer
   Amount currently due in cents

   amount_paid integer
   Amount already paid in cents

tax object
Grouped tax information:

   rate number
   Applied tax rate (0-1, e.g., 0.0875 for 8.75%)

   type string
   Type of tax (sales_tax, vat, gst, pst, hst, none)

   jurisdiction string
   Tax jurisdiction code (e.g., "CA-Los Angeles")

   behavior string
   Tax collection behavior (inclusive, exclusive, none)

   note string
   Additional tax notes

payment_method_id string
Payment method identifier (only present if payment has been attempted).

payment_intent_id string
Payment processor intent identifier (only present if payment has been attempted).

payment_date string
ISO 8601 timestamp of payment (only present if payment has been attempted).

retries object
Payment retry information (only present if retries have been attempted):

   count integer
   Number of retry attempts made

   max integer
   Maximum retries allowed

   next_date string
   ISO 8601 timestamp of next retry

   last_date string
   ISO 8601 timestamp of last retry

   delay_minutes integer
   Delay before next retry

plan object
Plan and pricing information:

   plan_id string
   Plan identifier

   name string
   Display name of the plan

   type string
   Plan type (e.g., "recurring")

   phase_id string
   Active phase identifier

   phase_order number
   Phase order number (1-based)

   billing_cycle number
   Billing cycle number (0=trial, 1+=paid)

   platform_fee_rate number
   Platform fee rate (0-1)

   platform_fee_amount integer
   Platform fee in cents

period object
Billing period dates:

   start string
   ISO 8601 start of billing period

   end string
   ISO 8601 end of billing period

   invoice_date string
   ISO 8601 invoice creation date

   due_date string
   ISO 8601 payment due date

metadata object
Custom metadata key-value pairs.

created_ip string
IP address from which the invoice was created.

updated_ip string
IP address from which the invoice was last updated.

created_at string
ISO 8601 timestamp when the invoice was created.

updated_at string
ISO 8601 timestamp when the invoice was last updated.

platform_fee_amount integer
Platform fee amount in cents.

metadata object
Additional metadata associated with the invoice.

platform_id string
The platform identifier that created this invoice's subscription.

created_ip string
IP address from which the invoice was created.

updated_ip string
IP address from which the invoice was last updated.

created_at string
ISO 8601 timestamp when the invoice was created.

updated_at string
ISO 8601 timestamp when the invoice was last updated.

Update Invoice

Endpoint

PUT https://api.paket.tv/v1/catalog/subscriptions/:subscription_id/invoices/:invoice_id

Updates an invoice's payment status and related fields.

PUT https://api.paket.tv/v1/catalog/subscriptions/:subscription_id/invoices/:invoice_id

curl --location --request PUT 'https://api.paket.tv/v1/catalog/subscriptions/SUB479027832035610624/invoices/INV479027832278880256' \
  --header 'Content-Type: application/json' \
  --header 'Authorization: Basic <credentials>'
  --header 'Idempotency-Key: unique-payment-789' \
  --data '{
    "payment_status": "paid",
    "payment_method_id": "pm_123",
    "payment_intent_id": "pi_456"
  }'

Response (Standard)

HTTP/1.1 200 OK
Content-Type: application/json
{
  "invoice_id": "INV479027832278880256",
  "invoice_number": "INV-2025-78880256",
  "subscription_id": "SUB479027832035610624",
  "session_id": "session_456",
  "status": "paid",
  "payment_status": "paid",
  "currency": "USD",
  "region": "US",
  "amounts": {
    "subtotal": 1699,
    "proration_credit": 0,
    "tax_amount": 149,
    "total_amount": 1848,
    "amount_due": 0,
    "amount_paid": 1848
  },
  "tax": {
    "rate": 0.0875,
    "type": "sales_tax",
    "jurisdiction": "CA-Los Angeles",
    "behavior": "exclusive",
    "note": ""
  },
  "plan": {
    "plan_id": "427944e5ba9e",
    "name": "Disney+, Hulu, HBO Max Bundle",
    "type": "sub_bundle",
    "phase_id": "4282b4cfac23dc38",
    "phase_order": 1,
    "billing_cycle": 1,
    "platform_fee_rate": 0.15,
    "platform_fee_amount": 255
  },
  "period": {
    "start": "2025-08-14T20:45:35.065Z",
    "end": "2025-09-14T20:45:35.064Z",
    "invoice_date": "2025-08-14T20:45:35.122Z",
    "due_date": "2025-09-13T20:45:35.122Z"
  },
  "payment_method_id": "pm_123",
  "payment_intent_id": "pi_456",
  "payment_date": "2025-08-14T21:15:00.000Z",
  "retries": {
    "count": 0,
    "max": 3,
    "next_date": null,
    "last_date": null,
    "delay_minutes": 60
  },
  "metadata": {},
  "created_ip": "75.85.168.125",
  "updated_ip": "75.85.168.125",
  "created_at": "2025-08-14T20:45:35.122Z",
  "updated_at": "2025-08-14T21:15:00.000Z"
}

Response (First Invoice with Activation URLs)

HTTP/1.1 200 OK
Content-Type: application/json
{
  "invoice_id": "INV479027832278880256",
  "invoice_number": "INV-2025-78880256",
  "subscription_id": "SUB479027832035610624",
  "session_id": "session_456",
  "status": "paid",
  "payment_status": "paid",
  "currency": "USD",
  "region": "US",
  "amounts": {
    "subtotal": 1699,
    "proration_credit": 0,
    "tax_amount": 149,
    "total_amount": 1848,
    "amount_due": 0,
    "amount_paid": 1848
  },
  "tax": {
    "rate": 0.0875,
    "type": "sales_tax",
    "jurisdiction": "CA-Los Angeles",
    "behavior": "exclusive",
    "note": ""
  },
  "plan": {
    "plan_id": "427944e5ba9e",
    "name": "Disney+, Hulu, HBO Max Bundle",
    "type": "sub_bundle",
    "phase_id": "4282b4cfac23dc38",
    "phase_order": 1,
    "billing_cycle": 1,
    "platform_fee_rate": 0.15,
    "platform_fee_amount": 255
  },
  "period": {
    "start": "2025-08-14T20:45:35.065Z",
    "end": "2025-09-14T20:45:35.064Z",
    "invoice_date": "2025-08-14T20:45:35.122Z",
    "due_date": "2025-09-13T20:45:35.122Z"
  },
  "payment_method_id": "pm_123",
  "payment_intent_id": "pi_456",
  "payment_date": "2025-08-14T21:15:00.000Z",
  "retries": {
    "count": 0,
    "max": 3,
    "next_date": null,
    "last_date": null,
    "delay_minutes": 60
  },
  "metadata": {},
  "created_ip": "75.85.168.125",
  "updated_ip": "75.85.168.125",
  "created_at": "2025-08-14T20:45:35.122Z",
  "updated_at": "2025-08-14T21:15:00.000Z",
  "activation_urls": [
    {
      "app_id": "AP468442205989113856",
      "app_name": "Disney+",
      "product_id": "PR469716925099413504",
      "product_name": "Disney+ Basic",
      "activation_url": "https://disneyplus.com/activate?activation_code=AC_A3F2_B7C9",
      "expires_at": "2025-08-14T22:00:00.000Z"
    },
    {
      "app_id": "AP468442310876295168",
      "app_name": "Hulu",
      "product_id": "PR469716985421504512",
      "product_name": "Hulu Basic",
      "activation_url": "https://hulu.com/activate?code=AC_D4E1_F8A2",
      "expires_at": "2025-08-14T22:00:00.000Z"
    }
  ]
}

* required

Headers

Authorization* string
Your API credentials for authentication.

Idempotency-Key string
Optional but recommended. Unique key to prevent duplicate updates.

Path Parameters

subscription_id* string
The subscription ID.

invoice_id* string
The invoice ID to update.

Request Body

At least one field is required.

payment_status string
Optional. Update payment status. Valid values:

payment_method_id string
Optional. Payment method used.

payment_intent_id string
Optional. Payment processor intent ID.

Returns

Returns the updated Invoice object. When updating a first invoice (billing_cycle <= 1) to payment_status: "paid", the response may also include an activation_urls array containing activation URLs for each bundled service that requires activation.

Response Fields

All standard Invoice fields plus:

activation_urls array
Optional. Returned when payment_status is set to "paid" for first invoices. Contains activation URLs for bundled services. Each object includes: - app_id - The app/publisher ID - app_name - Display name of the app - product_id - The product being activated - product_name - Display name of the product - activation_url - URL to redirect user for activation - expires_at - When the activation URL expires

Get Invoice

Endpoint

GET https://api.paket.tv/v1/catalog/subscriptions/:subscription_id/invoices/:invoice_id

Retrieves details of a specific invoice.

GET https://api.paket.tv/v1/catalog/subscriptions/:subscription_id/invoices/:invoice_id

curl --location 'https://api.paket.tv/v1/catalog/subscriptions/SUB479027832035610624/invoices/INV479027832278880256' \
  --header 'Accept: application/json' \
  --header 'Authorization: Basic <credentials>'

Response

HTTP/1.1 200 OK
Content-Type: application/json
{
  "invoice_id": "INV479027832278880256",
  "invoice_number": "INV-2025-78880256",
  "subscription_id": "SUB479027832035610624",
  "session_id": "session_456",
  "status": "open",
  "payment_status": "unpaid",
  "currency": "USD",
  "region": "US",
  "amounts": {
    "subtotal": 1699,
    "proration_credit": 0,
    "tax_amount": 149,
    "total_amount": 1848,
    "amount_due": 1848,
    "amount_paid": 0
  },
  "tax": {
    "rate": 0.0875,
    "type": "sales_tax",
    "jurisdiction": "CA-Los Angeles",
    "behavior": "exclusive",
    "note": ""
  },
  "plan": {
    "plan_id": "427944e5ba9e",
    "name": "Disney+, Hulu, HBO Max Bundle",
    "type": "sub_bundle",
    "phase_id": "4282b4cfac23dc38",
    "phase_order": 1,
    "billing_cycle": 1,
    "platform_fee_rate": 0.15,
    "platform_fee_amount": 255
  },
  "period": {
    "start": "2025-08-14T20:45:35.065Z",
    "end": "2025-09-14T20:45:35.064Z",
    "invoice_date": "2025-08-14T20:45:35.122Z",
    "due_date": "2025-09-13T20:45:35.122Z"
  },
  "retries": {
    "count": 0,
    "max": 3,
    "next_date": null,
    "last_date": null,
    "delay_minutes": 60
  },
  "metadata": {},
  "platform_id": "PL468440696748511232",
  "created_ip": "75.85.168.125",
  "updated_ip": "75.85.168.125",
  "created_at": "2025-08-14T20:45:35.122Z",
  "updated_at": "2025-08-14T20:45:35.122Z"
}

* required

Headers

Authorization* string
Your API credentials for authentication.

Path Parameters

subscription_id* string
The subscription ID.

invoice_id* string
The invoice ID to retrieve.

Returns

Returns a complete Invoice object.

List Invoices

Endpoint

GET https://api.paket.tv/v1/catalog/subscriptions/:subscription_id/invoices

Lists all invoices for a specific subscription.

GET https://api.paket.tv/v1/catalog/subscriptions/:subscription_id/invoices

curl --location 'https://api.paket.tv/v1/catalog/subscriptions/SUB479027832035610624/invoices?limit=50' \
  --header 'Accept: application/json' \
  --header 'Authorization: Basic <credentials>'

Response

HTTP/1.1 200 OK
Content-Type: application/json
{
  "invoices": [
    {
      "invoice_id": "INV479027832278880256",
      "invoice_number": "INV-2025-78880256",
      "invoice_date": "2025-08-14T20:45:35.122Z",
      "due_date": "2025-09-13T20:45:35.122Z",
      "status": "open",
      "payment_status": "unpaid",
      "total_amount": 1848,
      "currency": "USD",
      "period_start": "2025-08-14T20:45:35.065Z",
      "period_end": "2025-09-14T20:45:35.064Z"
    },
    {
      "invoice_id": "INV479025528485658880",
      "invoice_number": "INV-2025-85658880",
      "invoice_date": "2025-07-14T20:45:00.000Z",
      "due_date": "2025-08-13T20:45:00.000Z",
      "status": "paid",
      "payment_status": "paid",
      "total_amount": 1848,
      "currency": "USD",
      "period_start": "2025-07-14T20:45:00.000Z",
      "period_end": "2025-08-14T20:45:00.000Z"
    }
  ],
  "lastEvaluatedKey": null
}

* required

Headers

Authorization* string
Your API credentials for authentication.

Path Parameters

subscription_id* string
The subscription ID to list invoices for.

Query Parameters

limit integer
Optional. Number of results to return (1-100, default: 25).

Returns

Returns an array of summarized Invoice objects, sorted by most recent first.

Payments

Payments provide immutable audit trails of all payment attempts for invoices. Unlike invoices which can be updated, payment records are never modified once created, ensuring complete payment history and compliance.

The Payment Object

The Payment object represents an immutable payment attempt record for an invoice, providing a complete audit trail of all payment processing activities. Please note that Paket does not natively process payments, rather it is a store of a payment attempts made via a Platform's PSP. As such, it is encumbant on the Platform processing a payment to post payment responsese to this API to ensure an immutable audit trail of payment attemps exists for each Invoice

The Payment Object

{
  "payment_id": "PAY479027832345678912",
  "invoice_id": "INV479027832278880256",
  "subscription_id": "SUB479027832035610624",
  "platform_id": "PL468440696748511232",
  "amount": 1848,
  "currency": "USD",
  "status": "succeeded",
  "payment_method_id": "pm_1NvQsHKyuNiyfQC0M4X0Q8Bq",
  "payment_intent_id": "pi_3NvQsHKyuNiyfQC00d9qFQe3",
  "error_code": null,
  "error_message": null,
  "processor_response": {
    "last_four": "4242",
    "brand": "visa",
    "exp_month": 12,
    "exp_year": 2028
  },
  "metadata": {
    "source": "web_app",
    "retry_attempt": 0
  },
  "created_ip": "192.168.1.100",
  "created_at": "2025-08-14T21:15:00.000Z",
  "activation_urls": [
    {
      "app_id": "AP468442205989113856",
      "app_name": "Disney+",
      "product_id": "PR469716925099413504",
      "product_name": "Disney+ Basic",
      "activation_url": "https://disneyplus.com/activate?token=abc123...",
      "expires_at": "2025-08-14T21:45:00.000Z"
    }
  ]
}

Refund Example:

{
  "payment_id": "PAY479027832345678912",
  "invoice_id": "INV479027832278880256",
  "subscription_id": "SUB479027832035610624",
  "platform_id": "PL468440696748511232",
  "amount": -1848,
  "currency": "USD",
  "status": "succeeded",
  "refund_reason": "Duplicate charge",
  "payment_method_id": "pm_1NvQsHKyuNiyfQC0M4X0Q8Bq",
  "payment_intent_id": "pi_3NvQsHKyuNiyfQC00d9qFQe3",
  "error_code": null,
  "error_message": null,
  "processor_response": {
    "last_four": "4242",
    "brand": "visa",
    "exp_month": 12,
    "exp_year": 2028
  },
  "metadata": {
    "refund_requested_by": "customer_service",
    "original_charge_date": "2025-08-14T21:15:00.000Z"
  },
  "created_ip": "192.168.1.100",
  "created_at": "2025-08-15T14:30:00.000Z"
}

Attributes

payment_id string
The unique identifier for the payment record (prefixed with PAY).

invoice_id string
The invoice this payment attempt was made for.

subscription_id string
The subscription associated with this payment.

platform_id string
The platform identifier that initiated this payment.

amount integer
Payment amount in cents. Positive values represent payments, negative values represent refunds.

currency string
Three-letter ISO currency code.

status string
Payment processing status:

payment_method_id string
Payment processor's payment method identifier.

payment_intent_id string
Payment processor's intent identifier.

refund_reason string
Reason for refund (only present for refund records).

original_payment_id string
Reference to the original payment being refunded (only present for refund records).

error_code string
Error code if payment failed (null for successful payments).

error_message string
Human-readable error message if payment failed (null for successful payments).

processor_response object
Payment processor's response data:

   last_four string
   Last four digits of payment method

   brand string
   Payment method brand (e.g., "visa", "mastercard")

   exp_month integer
   Expiration month

   exp_year integer
   Expiration year

metadata object
Additional metadata associated with the payment attempt.

created_ip string
IP address from which the payment was initiated.

created_at string
ISO 8601 timestamp when the payment record was created.

activation_urls array
Optional. Returned for successful payments on first invoices. Contains activation URLs for bundled services requiring activation:

   app_id string
   App identifier requiring activation

   app_name string
   App display name

   product_id string
   Product identifier to activate

   product_name string
   Product display name

   activation_url string
   URL for user to complete activation

   expires_at string
   ISO 8601 timestamp when activation expires

Create Payment

Endpoint

POST https://api.paket.tv/v1/catalog/subscriptions/:subscription_id/invoices/:invoice_id/payments

Creates an immutable payment record for an invoice. Supports both payments (positive amounts) and refunds (negative amounts).

POST https://api.paket.tv/v1/catalog/subscriptions/:subscription_id/invoices/:invoice_id/payments

curl --location --request POST 'https://api.paket.tv/v1/catalog/subscriptions/SUB479027832035610624/invoices/INV479027832278880256/payments' \
  --header 'Content-Type: application/json' \
  --header 'Authorization: Basic <credentials>' \
  --header 'Idempotency-Key: unique-payment-123' \
  --data '{
    "amount": 1848,
    "currency": "USD",
    "status": "succeeded",
    "payment_method_id": "pm_1NvQsHKyuNiyfQC0M4X0Q8Bq",
    "payment_intent_id": "pi_3NvQsHKyuNiyfQC00d9qFQe3",
    "processor_response": {
      "last_four": "4242",
      "brand": "visa",
      "exp_month": 12,
      "exp_year": 2028
    },
    "metadata": {
      "source": "web_app",
      "retry_attempt": 0
    }
  }'

Response (Successful Payment)

HTTP/1.1 201 Created
Content-Type: application/json
{
  "payment_id": "PAY479027832345678912",
  "invoice_id": "INV479027832278880256",
  "subscription_id": "SUB479027832035610624",
  "platform_id": "PL468440696748511232",
  "amount": 1848,
  "currency": "USD",
  "status": "succeeded",
  "payment_method_id": "pm_1NvQsHKyuNiyfQC0M4X0Q8Bq",
  "payment_intent_id": "pi_3NvQsHKyuNiyfQC00d9qFQe3",
  "error_code": null,
  "error_message": null,
  "processor_response": {
    "last_four": "4242",
    "brand": "visa",
    "exp_month": 12,
    "exp_year": 2028
  },
  "metadata": {
    "source": "web_app",
    "retry_attempt": 0
  },
  "created_ip": "192.168.1.100",
  "created_at": "2025-08-14T21:15:00.000Z",
  "activation_urls": [
    {
      "app_id": "AP468442205989113856",
      "app_name": "Disney+",
      "product_id": "PR469716925099413504",
      "product_name": "Disney+ Basic",
      "activation_url": "https://disneyplus.com/activate?token=abc123...",
      "expires_at": "2025-08-14T21:45:00.000Z"
    }
  ]
}

Response (Failed Payment)

HTTP/1.1 201 Created
Content-Type: application/json
{
  "payment_id": "PAY479027832345678913",
  "invoice_id": "INV479027832278880256",
  "subscription_id": "SUB479027832035610624",
  "platform_id": "PL468440696748511232",
  "amount": 1848,
  "currency": "USD",
  "status": "failed",
  "payment_method_id": "pm_1NvQsHKyuNiyfQC0M4X0Q8Bq",
  "payment_intent_id": "pi_3NvQsHKyuNiyfQC00d9qFQe3",
  "error_code": "insufficient_funds",
  "error_message": "Your card has insufficient funds.",
  "processor_response": {
    "last_four": "4242",
    "brand": "visa",
    "decline_code": "insufficient_funds"
  },
  "metadata": {
    "source": "web_app",
    "retry_attempt": 1
  },
  "created_ip": "192.168.1.100",
  "created_at": "2025-08-14T21:16:30.000Z"
}

* required

Headers

Authorization* string
Your API credentials for authentication.

Idempotency-Key string
Optional but recommended. Unique key to prevent duplicate payment records.

Path Parameters

subscription_id* string
The subscription ID.

invoice_id* string
The invoice ID to create payment for.

Request Body

amount* number
Payment amount in cents. Use positive values for payments, negative values for refunds.

status* string
Payment processing status. Valid values:

currency string
Optional. Three-letter ISO currency code (defaults to USD).

payment_method_id string
Optional. Payment processor's payment method identifier.

payment_intent_id string
Optional. Payment processor's intent identifier.

refund_reason string
Optional. Reason for refund (only applicable for refund records).

original_payment_id string
Optional. Reference to the original payment being refunded (only applicable for refund records).

error_code string
Optional. Error code for failed payments.

error_message string
Optional. Human-readable error message for failed payments.

processor_response object
Optional. Additional response data from the payment processor.

metadata object
Optional. Additional metadata for the payment attempt.

Returns

Returns the created Payment object. The payment record is immutable and cannot be modified after creation.

Get Payment

Endpoint

GET https://api.paket.tv/v1/catalog/subscriptions/:subscription_id/invoices/:invoice_id/payments/:payment_id

Retrieves details of a specific payment record.

GET https://api.paket.tv/v1/catalog/subscriptions/:subscription_id/invoices/:invoice_id/payments/:payment_id

curl --location 'https://api.paket.tv/v1/catalog/subscriptions/SUB479027832035610624/invoices/INV479027832278880256/payments/PAY479027832345678912' \
  --header 'Accept: application/json' \
  --header 'Authorization: Basic <credentials>'

Response

HTTP/1.1 200 OK
Content-Type: application/json
{
  "payment_id": "PAY479027832345678912",
  "invoice_id": "INV479027832278880256",
  "subscription_id": "SUB479027832035610624",
  "platform_id": "PL468440696748511232",
  "amount": 1848,
  "currency": "USD",
  "status": "succeeded",
  "payment_method_id": "pm_1NvQsHKyuNiyfQC0M4X0Q8Bq",
  "payment_intent_id": "pi_3NvQsHKyuNiyfQC00d9qFQe3",
  "error_code": null,
  "error_message": null,
  "processor_response": {
    "last_four": "4242",
    "brand": "visa",
    "exp_month": 12,
    "exp_year": 2028
  },
  "metadata": {
    "source": "web_app",
    "retry_attempt": 0
  },
  "created_ip": "192.168.1.100",
  "created_at": "2025-08-14T21:15:00.000Z"
}

* required

Headers

Authorization* string
Your API credentials for authentication.

Path Parameters

subscription_id* string
The subscription ID.

invoice_id* string
The invoice ID.

payment_id* string
The payment ID to retrieve.

Returns

Returns the complete Payment object.

List Payments

Endpoint

GET https://api.paket.tv/v1/catalog/subscriptions/:subscription_id/invoices/:invoice_id/payments

Lists all payment attempts for a specific invoice, sorted by most recent first.

GET https://api.paket.tv/v1/catalog/subscriptions/:subscription_id/invoices/:invoice_id/payments

curl --location 'https://api.paket.tv/v1/catalog/subscriptions/SUB479027832035610624/invoices/INV479027832278880256/payments?limit=25' \
  --header 'Accept: application/json' \
  --header 'Authorization: Basic <credentials>'

Response

HTTP/1.1 200 OK
Content-Type: application/json
{
  "payments": [
    {
      "payment_id": "PAY479027832345678912",
      "invoice_id": "INV479027832278880256",
      "subscription_id": "SUB479027832035610624",
      "platform_id": "PL468440696748511232",
      "amount": 1848,
      "currency": "USD",
      "status": "succeeded",
      "payment_method_id": "pm_1NvQsHKyuNiyfQC0M4X0Q8Bq",
      "payment_intent_id": "pi_3NvQsHKyuNiyfQC00d9qFQe3",
      "created_at": "2025-08-14T21:15:00.000Z"
    },
    {
      "payment_id": "PAY479027832345678911",
      "invoice_id": "INV479027832278880256",
      "subscription_id": "SUB479027832035610624",
      "platform_id": "PL468440696748511232",
      "amount": 1848,
      "currency": "USD",
      "status": "failed",
      "error_code": "insufficient_funds",
      "error_message": "Your card has insufficient funds.",
      "created_at": "2025-08-14T21:10:30.000Z"
    }
  ],
  "lastEvaluatedKey": null
}

* required

Headers

Authorization* string
Your API credentials for authentication.

Path Parameters

subscription_id* string
The subscription ID.

invoice_id* string
The invoice ID to list payments for.

Query Parameters

limit integer
Optional. Number of results to return (1-100, default: 25).

Returns

Returns an array of Payment objects, sorted by most recent first. This shows the complete payment history for an invoice, including all successful and failed attempts.

Activation

The Activation API provides endpoints for managing product activation sessions and validating activation codes. When a subscription is successfully paid, Paket automatically creates activation sessions for bundled services that require user activation.

The Activation Session Object

The Activation Session object represents a collection of activation codes generated for a paid subscription, tracking the activation status of each bundled product.

The Activation Session Object

{
  "activation_session_id": "AS479027832456789123",
  "subscription_id": "SUB479027832035610624",
  "platform_id": "PL468440696748511232",
  "session_id": "session_456",
  "status": "pending",
  "expires_at": "2025-08-21T21:15:00.000Z",
  "progress": {
    "items_total": 3,
    "items_activated": 1
  },
  "activation_urls": [
    {
      "app_id": "AP468442205989113856",
      "app_name": "Disney+",
      "product_id": "PR469716925099413504",
      "product_name": "Disney+ Basic",
      "activation_url": "https://disneyplus.com/activate?activation_code=AC_A3F2B7C9_D4E1F8A2",
      "expires_at": "2025-08-21T21:15:00.000Z"
    },
    {
      "app_id": "AP468442205989113857",
      "app_name": "Hulu",
      "product_id": "PR469716925099413505",
      "product_name": "Hulu (No Ads)",
      "activation_url": "https://hulu.com/activate?code=AC_B4G2K8D1_F5H9L3M6",
      "expires_at": "2025-08-21T21:15:00.000Z"
    }
  ],
  "metadata": {},
  "created_at": "2025-08-14T21:15:00.000Z",
  "updated_at": "2025-08-14T21:15:00.000Z"
}

Attributes

activation_session_id string
The unique identifier for the activation session (prefixed with AS).

subscription_id string
The subscription that triggered this activation session.

invoice_id string
The invoice that was paid to trigger activation.

session_id string
The user session associated with the subscription.

platform_id string
The platform identifier that created the subscription.

platform_name string
Display name of the platform.

status string
Overall activation session status: - pending - Awaiting activation for one or more items - partial - Some items activated but not all - completed - All items successfully activated - failed - Activation failed for one or more items - expired - Session expired before completion

items_total integer
Total number of products requiring activation.

items_activated integer
Number of products successfully activated.

created_at string
ISO 8601 timestamp when the activation session was created.

updated_at string
ISO 8601 timestamp when the activation session was last updated.

expires_at string
ISO 8601 timestamp when the activation session expires.

activation_items array
Array of activation items for each product in the subscription. Each item contains: - app_id - The app/publisher identifier - app_name - Display name of the app - product_id - The product being activated - product_name - Display name of the product - status - Item activation status (pending, activated, failed, expired) - activation_code_hash - SHA-256 hash of the activation code (for validation) - activation_url - Complete URL for user activation - jti - Unique JWT identifier for the activation token - created_at - When this activation item was created - expires_at - When this activation code expires (typically 7 days)

Exchange Activation Code

Endpoint

POST https://api.paket.tv/v1/catalog/activation/exchange

Validates and exchanges an activation code for product licensing information. Publishers use this endpoint to verify activation codes received from users.

POST https://api.paket.tv/v1/catalog/activation/exchange

curl --location --request POST 'https://api.paket.tv/v1/catalog/activation/exchange' \
  --header 'Content-Type: application/json' \
  --header 'Authorization: Basic <credentials>' \
  --data '{
    "activation_code": "AC_A3F2B7C9_D4E1F8A2"
  }'

Response (Successful Exchange)

HTTP/1.1 200 OK
Content-Type: application/json
{
  "activation_session_id": "AS479027832456789123",
  "app_id": "AP468442205989113856",
  "product_id": "PR469716925099413504",
  "subscription_id": "SUB479027832035610624",
  "platform_id": "PL468440696748511232",
  "platform_name": "Example Platform",
  "product": {
    "product_id": "PR469716925099413504",
    "product_name": "Disney+ Basic",
    "name": "Disney+ Basic",
    "description": "Disney+ Basic With Ads",
    "status": "active",
    "product_type": "streaming",
    "metadata": {
      "tier": "basic",
      "ads_supported": true
    }
  },
  "jti": "at_479027832567890234",
  "exchanged_at": "2025-08-14T21:30:00.000Z",
  "expires_at": "2025-08-17T21:15:00.000Z"
}

Response (Invalid/Expired Code)

HTTP/1.1 404 Not Found
Content-Type: application/json
{
  "error": "activation_code_not_found",
  "message": "Activation code not found or expired"
}

Response (Already Used)

HTTP/1.1 409 Conflict
Content-Type: application/json
{
  "error": "activation_code_already_used",
  "message": "This activation code has already been exchanged"
}

* required

Headers

Authorization* string
Your API credentials for authentication.

Request Body

activation_code* string
The activation code to validate and exchange, taken from the activation URL.

Returns

Returns activation details and product information if the code is valid and unused. The activation code is marked as exchanged and cannot be used again.

Implementation Notes

Publishers should: 1. Exchange the activation code received from the user 2. Complete user sign-up or sign-in process 3. Confirm the activation using the Update Activation Status endpoint 4. Handle error cases (expired, invalid, or already used codes)

Update Activation Status

Endpoint

PUT https://api.paket.tv/v1/catalog/activation/:session_id/items/:item_id

Confirms that a user has successfully completed the activation process. This endpoint should be called after the service has been successfully provisioned for the user.

PUT https://api.paket.tv/v1/catalog/activation/:session_id/items/:item_id

curl --location --request PUT 'https://api.paket.tv/v1/catalog/activation/AS479027832456789123/items/AP468442205989113856' \
  --header 'Content-Type: application/json' \
  --header 'Authorization: Basic <credentials>' \
  --data '{
    "status": "activated",
    "activated_at": "2025-08-14T21:35:00.000Z",
    "user_id": "publisher_user_123"
  }'

Response (Successful Update)

HTTP/1.1 200 OK
Content-Type: application/json
{
  "activation_session_id": "AS479027832456789123",
  "item_id": "AP468442205989113856",
  "product_id": "PR469716925099413504",
  "status": "activated",
  "activated_at": "2025-08-14T21:35:00.000Z",
  "updated_at": "2025-08-14T21:35:00.000Z"
}

* required

Headers

Authorization* string
Your API credentials for authentication.

Path Parameters

session_id* string
The activation session ID returned from the exchange endpoint.

item_id* string
The app ID for the item being activated.

Request Body

status* string
The activation status. Valid values: - activated - Successfully activated - failed - Activation failed

activated_at string
Optional. ISO 8601 timestamp of when the activation was completed.

user_id string
Optional. The publisher's internal user ID for tracking.

error_reason string
Required if status is failed. Reason for activation failure.

Returns

Returns the updated activation item confirming the activation status has been recorded.

Regenerate Activation Codes

Endpoint

POST https://api.paket.tv/v1/catalog/activation/:session_id/regenerate

Regenerates expired activation codes for a subscription. This endpoint allows platforms to generate new activation codes when the original codes have expired after 7 days.

POST https://api.paket.tv/v1/catalog/activation/:session_id/regenerate

curl --location --request POST 'https://api.paket.tv/v1/catalog/activation/AS479027832456789123/regenerate' \
  --header 'Content-Type: application/json' \
  --header 'Authorization: Basic <credentials>' \
  --data '{
    "regenerate_all": false,
    "app_ids": ["AP468442205989113856"]
  }'

Response (Successful Regeneration)

HTTP/1.1 200 OK
Content-Type: application/json
{
  "activation_session_id": "AS479027832456789123",
  "subscription_id": "SUB479027832035610624",
  "regenerated_count": 1,
  "activation_urls": [
    {
      "app_id": "AP468442205989113856",
      "app_name": "Disney+",
      "product_id": "PR469716925099413504",
      "product_name": "Disney+ Basic",
      "activation_url": "https://disneyplus.com/activate?activation_code=AC_B4G7K2L9_M3N5P8Q1",
      "expires_at": "2025-08-21T21:15:00.000Z"
    }
  ]
}

Response (Session Not Found)

HTTP/1.1 404 Not Found
Content-Type: application/json
{
  "error": "activation_session_not_found",
  "message": "Activation session not found or expired"
}

Response (Codes Still Valid)

HTTP/1.1 409 Conflict
Content-Type: application/json
{
  "error": "codes_still_valid",
  "message": "Existing activation codes are still valid and have not expired"
}

* required

Headers

Authorization* string
Your API credentials for authentication.

Path Parameters

session_id* string
The activation session ID for which to regenerate codes.

Request Body

regenerate_all boolean
Optional. If true, regenerates codes for all products in the session. Default: false.

app_ids array
Optional. Array of app IDs for which to regenerate codes. Required if regenerate_all is false.

force boolean
Optional. If true, regenerates codes even if existing codes haven't expired. Default: false.

Returns

Returns the activation session with new activation URLs containing fresh codes valid for another 7 days.

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 Contexts attached to a Session.

For example, if Apps A, B, and C have shared their respective Context IDs with a Platform - and such Context 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 Context's feed (i.e., a specific App) can also be requested simply by calling the Session API along with the requested Context 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": "AP463772054442217472",
  "context_id": "CX467798389036421120",
  "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",
  "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 App ID to which the item is associated.

context_id string
The Context 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.

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 Context Object

The Session Context Object is created when a Participant's context_id is added to a Session or when requesting a list of all Parcticipants associated with an active Session. It contains useful information related to a Participant's relationship to a Session.

{
  "session_id": "SN759077888463135026",
  "context_id": "CX463135026759077888",
  "app_id": "AP463772054442217472",
  "created_at": "2024-02-16T04:41:06.596Z"
}

Attributes

app_id string
The Publisher's App ID to which the context_id belongs.

context_id string
The app user's (or "Participant") unique Context identifier.

session_id string
The platform user's unique Session identifier.

created_at string
The ISO 8601 timestamp when the Session was created.

Platform UpNext 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 Sequence Diagram

Publisher UpNext Flow

Before beginning, Publisher partners should familiarize themselves with the Contexts object.

The diagram below is an overview of how Publisher Clients interact with the Paket UpNext API.

Publisher Sequence 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 Context

Endpoint

PUT https://api.paket.tv/v1/sessions/upnext/:session_id

Adds or updates a Context to an active Session.

PUT https://api.paket.tv/v1/sessions/upnext/:session_id

curl --location --request PUT 'https://api.paket.tv/v1/sessions/upnext/:session_id' \
  --header 'Content-Type: application/json' \
  --header 'Accept: application/json' \
  --header 'Authorization: Basic <credentials>' \
  --data '{
    "app_id": "fe4a9ed381e8e376",
    "context_id": "6e5060c3-7df4-488e-9e9a-67cd5077b352"
  }'

Response

HTTP/1.1 200 OK
Content-Type: application/json
{
  "session_id": "SN759077888463135026",
  "context_id": "CX463135026759077888",
  "app_id": "AP463772054442217472",
  "created_at": "2024-02-16T04:41:06.596Z"
}

* required

Headers

Authorization* string
Your API credentials for authentication.

Path Parameters

session_id* string
The platform user's unique Session identifier.

Request Body

app_id* string
The Publisher's App ID to which the Context being added belongs.

context_id* string
The Context ID to be added to the Session.

Returns

Returns a Session Context Object.

Remove a Context

Endpoint

DELETE https://api.paket.tv/v1/sessions/upnext/:session_id/:context_id

Removes a Context from an active Session.

DELETE https://api.paket.tv/v1/sessions/upnext/:session_id/:context_id

curl --location --request DELETE 'https://api.paket.tv/v1/sessions/upnext/:session_id/:context_id' \
  --header 'Accept: application/json' \
  --header 'Authorization: Basic <credentials>'

Response

HTTP/1.1 204 OK
Content-Type: application/json

* required

Headers

Authorization* string
Your API credentials for authentication.

Path Parameters

session_id* string
The platform user's unique Session identifier.

context_id* string
The app user's (or "Participant") unique Context identifier.

Returns

Returns a 204 No Content response.

Get an Aggregated List

Endpoint

GET https://api.paket.tv/v1/sessions/upnext/:session_id

Retrieves aggregated Session list from all registered Contexts.

GET https://api.paket.tv/v1/sessions/upnext/:session_id

curl --location 'https://api.paket.tv/v1/sessions/upnext/:session_id' \
  --header 'Accept: application/json' \
  --header 'Authorization: Basic <credentials>'

Response

HTTP/1.1 200 OK
Content-Type: application/json
{
  "total": 271,
  "next_key": 4,
  "items": [
    {
      "content_id": "1iwousk12i008d9",
      "app_id": "df79418d4e6d5325",
      "context_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",
      "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"
      }
    },
    {...},
    {...},
    {...}
  ]
}

* required

Headers

Authorization* string
Your API credentials for authentication.

Path Parameters

session_id* string
The platform user's unique Session identifier.

Query 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/sessions/upnext/:session_id/:context_id

Retrieves the Session list of a specified Context.

GET https://api.paket.tv/v1/sessions/upnext/:session_id/:context_id

curl --location 'https://api.paket.tv/v1/sessions/upnext/:session_id/:context_id' \
  --header 'Accept: application/json' \
  --header 'Authorization: Basic <credentials>'

Response

HTTP/1.1 200 OK
Content-Type: application/json
{
  "total": 271,
  "next_key": 4,
  "items": [
    {
      "content_id": "1iwousk12i008d9",
      "app_id": "df79418d4e6d5325",
      "context_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",
      "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"
      }
    },
    {...},
    {...},
    {...}
  ]
}

* required

Headers

Authorization* string
Your API credentials for authentication.

Path Parameters

session_id* string
The platform user's unique Session identifier.

context_id* string
The app user's (or "Participant") unique Context identifier.

Query 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 Contexts

Endpoint

GET https://api.paket.tv/v1/sessions/upnext/:session_id/contexts

Retrieves a list of all Context's associated with a Session.

GET https://api.paket.tv/v1/sessions/upnext/:session_id/contexts

curl --location 'https://api.paket.tv/v1/sessions/upnext/:session_id/contexts' \
  --header 'Accept: application/json' \
  --header 'Authorization: Basic <credentials>'

Response

HTTP/1.1 200 OK
Content-Type: application/json
{
  "total": 12,
  "next_key": 4,
  "items": [
    {
      "session_id": "SN759077888463135026",
      "context_id": "6b0af623-2923-4997-92a6-73f94bbe321e",
      "app_id": "df79418d4e6d5325",
      "created_at": "2023-12-23T23:38:50.303Z"
    },
    {...},
    {...},
    {...}
  ]
}

* required

Headers

Authorization* string
Your API credentials for authentication.

Path Parameters

session_id* string
The platform user's unique Session identifier.

Query 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 Contexts Objects.

Hide an Item in a List

Endpoint

PUT https://api.paket.tv/v1/sessions/upnext/:session_id/:context_id

PUT https://api.paket.tv/v1/sessions/upnext/:session_id/:context_id

curl --location --request PUT 'https://api.paket.tv/v1/sessions/upnext/:session_id/:context_id' \
  --header 'Content-Type: application/json' \
  --header 'Accept: application/json' \
  --header 'Authorization: Basic <credentials>' \
  --data '{
    "content_id": "1iwousk12i008d9",
    "action": "hide"
  }'

Response

HTTP/1.1 200 OK
Content-Type: application/json
{
  "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 Context's list, the item will remain hidden within the List Item Object unless the hidden attribute is set to false by a Publisher action.

* required

Headers

Authorization* string
Your API credentials for authentication.

Path Parameters

session_id* string
The platform user's unique Session identifier.

context_id* string
The app user's (or "Participant") unique Context identifier.

Request Body

content_id* string
The content ID of the item to be hidden.

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

Returns

Returns a 200 Success response.

Remove a Session

Endpoint

DELETE https://api.paket.tv/v1/sessions/upnext/:session_id

DELETE https://api.paket.tv/v1/sessions/upnext/:session_id

curl --location --request DELETE 'https://api.paket.tv/v1/sessions/upnext/:session_id' \
  --header 'Accept: application/json' \
  --header 'Authorization: Basic <credentials>'

Response

HTTP/1.1 204 OK
Content-Type: application/json

Deletes a Session and all Context associations.

* required

Headers

Authorization* string
Your API credentials for authentication.

Path Parameters

session_id* string
The platform user's unique Session identifier.

Returns

Returns a 204 No Content response.

Contexts

Contexts 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 Context'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/contexts/upnext/:context_id

PUT https://api.paket.tv/v1/contexts/upnext/:context_id

curl --location --request PUT 'https://api.paket.tv/v1/contexts/upnext/:context_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",
    "position": 654,
    "duration": 1308,
    "hidden": false
  }'

Response

HTTP/1.1 204 OK
Content-Type: application/json
{
  "message": "Success"
}

Adds or updates an Item to the Context list. Please refer to the UpNext Guidelines to learn more about how to determine when to add an Item to the Context's list.

* required

Headers

Authorization* string
Your API credentials for authentication.

Path Parameters

context_id* string
The Context ID to which the List belongs.

Request Body

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.

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/contexts/upnext/:context_id/:content_id

DELETE https://api.paket.tv/v1/contexts/upnext/:context_id/:content_id

curl --location --request DELETE 'https://api.paket.tv/v1/contexts/upnext/:context_id/:content_id' \
  --header 'Accept: application/json' \
  --header 'Authorization: Basic <credentials>'

Response

HTTP/1.1 204 OK
Content-Type: application/json

Removes an Item from the Context's list.

* required

Headers

Authorization* string
Your API credentials for authentication.

Path Parameters

context_id* string
The Context ID to which the List belongs.

content_id* string
The Content ID of the item being added. Typically, this is an internal identifier provided by the Publisher.

Returns

Returns a 204 No Content response.

Get a Context's List

Endpoint

GET https://api.paket.tv/v1/contexts/upnext/:context_id

Retrieves the list of a specified Context.

GET https://api.paket.tv/v1/contexts/upnext/:context_id

curl --location 'https://api.paket.tv/v1/contexts/upnext/:context_id' \
  --header 'Accept: application/json' \
  --header 'Authorization: Basic <credentials>'

Response

HTTP/1.1 200 OK
Content-Type: application/json
{
  "total": 271,
  "next_key": 4,
  "items": [
    {
      "content_id": "1iwousk12i008d9",
      "app_id": "df79418d4e6d5325",
      "context_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",
      "position": 654,
      "duration": 1308,
      "hidden": false
    },
    {...},
    {...},
    {...}
  ]
}

* required

Headers

Authorization* string
Your API credentials for authentication.

Path Parameters

context_id* string
The Context ID to which the List belongs.

Query 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 Context's Sessions

Endpoint

DELETE https://api-dev.paket.tv/v1/contexts/upnext/:context_id/sessions

Removes all sessions associated with a Context.

DELETE https://api-dev.paket.tv/v1/contexts/upnext/:context_id/sessions

curl --location --request DELETE 'https://api.paket.tv/v1/contexts/upnext/:context_id/sessions' \
  --header 'Accept: application/json' \
  --header 'Authorization: Basic <credentials>'

Response

HTTP/1.1 204 OK
Content-Type: application/json

* required

Headers

Authorization* string
Your API credentials for authentication.

Path Parameters

context_id* string
The Context ID to which the Sessions are associated.

Returns

Returns a 204 No Content response.

Webhooks

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 Context is added to a Session, we create a context.session.context_added event, and when a bundle subscription is canceled, we create an context.subscription.canceled event.

The Event object

Example webhook event

{
  "id": "evt_a75f6d23be8c17b1",
  "object": "event",
  "type": "context.session.context_added",
  "created": 1709679883853,
  "api_version": "2023-12-10",
  "request": {
    "id": "req_2442fd8627bedb77",
    "idempotency_key": null
  },
  "data": {
    "context_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., context.session.context_added or context.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.

Events

context.session.deleted data.object is a session context
Occurs when a Session is removed.
Recipients: Publishers (Apps) that have contexts in the deleted session

context.session.context_added data.object is a session context
Occurs when a Context is added to a Session.
Recipients: Publishers (Apps) that own the added context

context.session.context_removed data.object is a session context
Occurs when a Context is removed from a Session.
Recipients: Publishers (Apps) that own the removed context

context.list.item_hidden data.object is a list item
Occurs when a Context user removes or hides an item from their List via the Platform.
Recipients: Publishers (Apps) that own the hidden item

subscription.status.created data.object is a subscription
Occurs when a platform creates a subscription that includes a publisher's product.
Recipients: Publishers (Apps) whose products are included in the subscription

subscription.status.renewed data.object is a subscription
Occurs when a platform successfully renews a subscription that includes a publisher's product.
Recipients: Publishers (Apps) whose products are included in the subscription

subscription.status.cancels_on data.object is a subscription
Occurs when a subscription is scheduled to cancel at the end of the current period.
Recipients: Publishers (Apps) whose products are included in the subscription

subscription.status.canceled data.object is a subscription
Occurs when a subscription is actually canceled (immediately or at period end) by platform or due to non payment. Recipients: Publishers (Apps) whose products were included in the canceled subscription

subscription.status.paused data.object is a subscription
Occurs when a platform pauses a subscription.
Recipients: Publishers (Apps) whose products are included in the paused subscription

subscription.status.resumed data.object is a subscription
Occurs when a platform resumes a paused subscription or reactivates a subscription scheduled for cancellation.
Recipients: Publishers (Apps) whose products are included in the resumed subscription

subscription.invoice.created data.object is an invoice
Occurs when a new invoice is generated for a subscription (renewal or initial billing).
Recipients: Platforms that created the subscription receiving the invoice

subscription.invoice.past_due data.object is a subscription
Occurs when subscription enters grace period after non payment or payment failure.
Recipients: Publishers (Apps) whose products are included in the subscription entering grace period

activation.session.created data.object is an activation session
Occurs when payment succeeds and activation session is created.
Recipients: Publishers (Apps) whose products require activation in the session

activation.code.reissued data.object is activation exchange details
Occurs when a platform regenerates or reissues a new activation code.
Recipients: Publishers (Apps) whose products require activation in the session

activation.code.expired data.object is activation exchange details
Occurs when an activation code expires or is invalidated. Recipients: Publishers (Apps) whose products require activation in the session

activation.item.failed data.object is activation item details
Occurs when an activation attempt fails (before code expiration).
Recipients: Platforms that created the subscription containing the failed activation item

activation.item.completed data.object is activation item details
Occurs when a publisher confirms successful activation via the Update Activation Status endpoint.
Recipients: Platforms that created the subscription containing the activated item

activation.session.completed data.object is an activation session
Occurs when all items in an activation session are activated.
Recipients: Platforms that created the subscription with the completed activation session

activation.session.expired data.object is an activation session
Occurs when activation session expires after 7 days without completion.
Recipients: Platforms that created the subscription with the expired activation session