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:
- Scalable subscription and bundling orchestration – streamline third-party subscription management across services using platform's native payments and identity services.
- Cross-device continue watching & Up Next management – unify playback progress and next-up recommendations across multiple apps and devices.
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.
- Platforms should register as a Platform Tenant
- Publishers should register as an App Tenant
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:
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
- Test API requests are validated identically to live requests
- Response schemas are identical to live requests
- Response data is dynamically generated for testing purposes
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
- Forced HTTPS: Connections are strictly enforced over HTTPS at
https://api.paket.tv/v1
- TLS/SSL: X.509 server certificates to validate server requests are authenticated as Paket Media, Inc.
- Basic Auth: Basic authentication required for all API requests with unique Client username and rollable secret keys
- IP Whitelisting: Restrict access to API requests to your server IP addresses designated at the Client level
- Encryption-at-rest: All data stored is encrypted-at-rest
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:
- Verify the signature matches the body and timestamp using the shared secret key.
- Ensure the request timestamp is within a 5-minute tolerance window.
- Log the signature status for audit and observability purposes.
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)
secret_key
: your client’s API secrettimestamp
: the current UNIX timestamp in millisecondsrequest_body
: the raw body string (or '' if there is no 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.
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:
- The timestamp (as a string)
- The character
.
- The actual JSON payload (that is, the request body)
Step 3: Determine the expected signature
Example Hashed result
f03a63e17d5720d7d01974d115059c8ec05b0f425828a2d0d341020f431bbafa
Compute an HMAC with the SHA256 hash function. Use the endpoint’s signing secret as the key, and use the signed_payload string as the message.
Step 4: Compare the signatures
Compare the signature (or signatures) in the header to the expected signature. For an equality match, compute the difference between the current timestamp and the received timestamp, then decide if the difference is within your tolerance.
To protect against timing attacks, use a constant-time-string comparison to compare the expected signature to each of the received signatures.
Paket IP addresses
To further protect your endpoints, it is recommended that you implement IP whitelisting of the Paket servers from which you may receive webhook events.
Paket IP Addresses:
54.185.102.16
52.40.235.54
35.83.22.57
Retry Behavior
Paket attempts to deliver a given event to your webhook endpoint up to fifteen (15) times over the course of 3 days with an exponential back off. In the Webhooks logs section of the Paket Publisher Portal, you can view when the next retry will occur as well as the event and event data itself.
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
- Keys are removed from the system automatically after they're at least 72 hours old
- A new request will be generated if a key is reused after the original is pruned
- The idempotency layer compares incoming parameters to those of the original request and errors if they're different to prevent accidental misuse
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]
.
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 New Subscription
- Platform Creates Subscription: Platform calls
POST /v1/catalog/subscriptions
with user's session ID and selected plan - Invoice Generation: Paket automatically generates the first invoice for the billing period
- Platform Processes Payment: Platform collects payment through their payment service provider (PSP)
- Payment Recording: Platform posts payment result to
POST /v1/catalog/subscriptions/{subscription_id}/invoices/{invoice_id}/payments
- Subscription Activation: On successful payment, Paket returns activation URLs for each of the plan's products and triggers the app activation flow
- Publisher Notification: Publishers receive
activation.session.created
webhooks for new subscriptions requiring activation. The webhook includes ajti
(JWT identifier) for security validation.
Product Activation
- User Arrives: User visits activation URL with their unique activation code
- Code Validation: Publisher validates the activation code via
POST /v1/catalog/activation/exchange
, which returns the purchased product details and thejti
for cross-reference validation. - Account Setup: Publisher validates the product and completes user sign-up or sign-in process
- Activation Confirmation: Publisher calls
PUT /v1/catalog/activation/{session_id}/items/{item_id}
to confirm activation. - 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
- Time-Limited: Activation codes expire after 7 days
- Single Use: Each code can only be exchanged once
- No Secrets Required: Simply exchange the code as received from the user
- Automatic Validation: Paket handles all security validation internally
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.
- Invoice Generation: On the billing date, Paket automatically generates a new invoice for the next billing cycle
- Platform Notification: Platform receives notification about the new invoice
- Payment Processing: Platform collects payment through their payment service provider (PSP)
- Payment Confirmation: Platform records payment result via
POST /v1/catalog/subscriptions/{subscription_id}/invoices/{invoice_id}/payments
- Renewal Completion: On successful payment, subscription billing cycle advances and service continues
- 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.
- Cancellation Request: Platform initiates cancellation via
PUT /v1/catalog/subscriptions/{subscription_id}
with status"canceled"
- Final Billing: Paket calculates any pro-rated charges or credits based on cancellation timing
- Publisher Notification: Publishers receive
subscription.canceled
webhook event with cancellation details - Service Termination: Publishers deactivate services for the canceled subscription
- Grace Period: Optional grace period allows users to maintain access until the end of the current billing period
- Final Invoice: If applicable, Paket generates a final invoice for any outstanding charges
- 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:
sub_bundle
- Multiple subscription services bundled togethersub_single
- Single subscription service
status
string
The current status of the plan:
active
- Available for new subscriptionsinactive
- Not available for new subscriptionsdeprecated
- Being phased out
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:
trialing
- In free trial periodactive
- Active and paidpast_due
- Payment failed but in grace periodcanceled
- Canceled by userunpaid
- Payment requiredpaused
- Temporarily paused
activation_status
string
Publisher activation status:
pending
- Awaiting activationpartial
- Partially activated (some services activated but not all)completed
- Successfully activatedfailed
- Activation failed
payment_status
string
Current payment status:
paid
- Fully paidunpaid
- Payment pendingscheduled
- Payment scheduledno_payment_required
- Free or trial periodprocessing
- Payment in progressfailed
- Payment failedcanceled
- Payment canceled
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:
inclusive
- Tax will be included in plan price (subtotal recalculated based on tax)exclusive
- Tax will be added to plan pricenone
- Plan is not taxable
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:
sales_tax
vat
gst
pst
hst
none
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:
open
paid
failed
processing
canceled
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:
succeeded
- Payment completed successfullyfailed
- Payment failed to processprocessing
- Payment is being processedcanceled
- Payment was canceledrequires_action
- Payment requires additional user actionrefunded
- Full refund processed successfullypartially_refunded
- Partial refund processed successfullyrefund_failed
- Refund attempt failedrefund_pending
- Refund is being processed
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:
succeeded
- Payment completed successfullyfailed
- Payment failed to processprocessing
- Payment is being processedcanceled
- Payment was canceledrequires_action
- Payment requires additional user actionrefunded
- Full refund processed successfullypartially_refunded
- Partial refund processed successfullyrefund_failed
- Refund attempt failedrefund_pending
- Refund is being processed
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:
up_next_continue
up_next_next
up_next_new
up_next_watchlist
media_type
string
The item's media type, which can be one of the following enum values:
movie
tv_episode
title
string
The title of the movie or TV show item.
description
string
The item description.
season
integer
The tv series season number. Returned only if item media_type
is tv_episode
.
episode
integer
The tv series episode number. Returned only if item media_type
is tv_episode
.
poster_art_uri
string
Uri of item's thumbnail image.
poster_art_aspect_ratio
string
Aspect ratio of media provided at poster_art_uri
, which can be one of the following enum values:
aspect_ratio_16_9
aspect_ratio_4_3
aspect_ratio_1_1
aspect_ratio_2_3
preview_video_uri
string
Uri of item's preview video, if provided.
position
integer
Last recorded position of media playback in seconds (returned if action
is up_next_continue
).
duration
integer
Item's total running time in seconds.
hidden
boolean
Indicates whether item is hidden or visible.
platform_data
object
Custom object containing custom attributes provided by the requesting Platform in the form of key-value pairs.
app_media
object
Object containing URIs to app media provided by the integrated Publisher.
Media URIs are constructed using the following shchema: <base_url>/media/<app_id>/<file_name>.png
. Media will return provided the respective file has been uploaded by the Publisher. Note: this can be reviewed and verified by the Platform via the UpNext API avails configuration in the Paket Developer Portal.
Below is a list of available keys and its respective file_name
:
icon_1x
corresponds toicon@1x.png
(240x240, PNG)icon_2x
corresponds toicon@2x.png
(480x480, PNG)icon_3x
corresponds toicon@3x.png
(960x960, PNG)tile_1x
corresponds totile@1x.png
(400x240, PNG)tile_2x
corresponds totile@2x.png
(800x480, PNG)logo_dark_1x
corresponds tologo_dark@1x.png
(400x240, PNG, Transparency)logo_light_1x
corresponds tologo_light@1x.png
(400x240, PNG, Transpareny)
The Session 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.
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.
Sessions
Sessions are the primary means by which Platforms interact with the Paket UpNext API.
It is through this API that Platforms can:
- Add or remove Contexts to a Session
- Fetch an aggregated UpNext list
- Fetch a specific Context's UpNext list
- Fetch a list of a Session's Contexts
- Hide items from a list
- Remove an existing Session
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:
hide
unhide
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:
- Add or remove items from a Context's list
- Fetch a specific Context's UpNext list
- Remove a Context's Sessions
Publisher Guidelines
It is likely that most Publishers who will be integrating with the Paket UpNext API will have an existing back-end service dedicated to making continue watching, new episodes, and related requests. In such cases - and to ensure as consistent a user experience as possible - it is recommended that such partners post data to the UpNext API in a way that is consistent with its existing guidelines and best practices.
For those Publishers who will be integrating exclusively with the Paket API, please refer to the following guidelines as to when items should be added to a 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:
- The user exits an app client during playback
- The user pauses or stops playback of a media item for more than five (5) minutes
Including unfinished movies and TV shows
Please add an up_next_continue
item if:
- A movie or TV show is started and the user has watched more than two (2) minutes; or
- A movie or TV show is is started and the user has watched more that 3% of its total duration (whichever is earlier)
Including new and next episode from a tv series
- Please add an
up_next_next
item if a user finishes an episode in a series and the next episode is available on your service - Please add an
up_next_new
item if a user is caught up on all available episodes of a tv series and a new season or episode becomes availables - Please add an
up_next_watchlist
item if an item in a user's watchlist was previously unavailable but has since been made available to watch on the service
Remove finished items from the UpNext List
- A media item is considered 'finished' when the end credits begin
- If the end credits cannot be determined, a media item is considered 'finished' when 3% or less the total duration of the media is remaining to be watched
Add Item to List
Endpoint
PUT https://api.paket.tv/v1/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:
movie
tv_episode
action
* string
The item action, which can be one of the following enum values:
up_next_continue
up_next_next
up_next_new
up_next_watchlist
title
* string
The title of the movie or TV show item.
description
* string
The item description.
poster_art_uri
* string
Uri of item's thumbnail image.
poster_art_aspect_ratio
* string
Aspect ratio of media provided at poster_art_uri
, which can be one of the following enum values:
aspect_ratio_16_9
aspect_ratio_4_3
aspect_ratio_1_1
aspect_ratio_2_3
season
integer
The tv series season number. Required only if item media_type
is tv_episode
.
episode
integer
The tv series episode number. Required only if item media_type
is tv_episode
.
preview_video_uri
string
Uri of item's preview video, if provided.
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