Get Started with Vega Subscription Entitlement
Here’s what you need to know to integrate the Vega Subscription Entitlement into your app for Fire TV.
If the data is not accessible or needs to be transformed, this integration could take longer. You can confirm that your data is stored in the requested format using the documentation below.
Prerequisites
- Access to the source code of your app for Fire TV.
- A Fire TV device that supports this integration. Check with your Amazon contact for a list of devices currently supported.
- Your app must participate in the Catalog Ingestion process, so Fire TV recognizes the subscription IDs your app is passing in these APIs.
- Your app must share entitlements for each customer, so Fire TV shows the entitled provider as part of our content discovery experience. For more information, reach out to your Amazon contact.
Integration steps
Step 1. Include the necessary package dependencies in your app
Add the Kepler-Subscription-Entitlement
package and headless-task-manager
dependencies in your package.json file.
"dependencies": {
"@amazon-devices/react-native-kepler": "~2.0.0",
"react": "18.2.0",
"react-native": "0.72.0",
"@amazon-devices/kepler-subscription-entitlement": "^1.1.0",
"@amazon-devices/headless-task-manager": "^1.0.0"
}
- The
kepler-subscription-entitlement
package provides APIs for sending your subscription entitlement data into the system. - The
headless-task-manager
package provides APIs to register your data-pull background service with the system. You can read more details below.
Step 2. Update your manifest file
Update your manifest.toml file to include Subscription Entitlement support. Below is an example for a sample app:
schema-version = 1
## Define your package
[package]
title = "Vega Video app"
version = "2.17.0"
id = "com.amazondeveloper.keplervideoapp"
[components]
## Define your app's interactive component (if it doesn't already exist)
[[components.interactive]]
id = "com.amazondeveloper.keplervideoapp.main"
library-name = "com.amazondeveloper.keplervideoapp"
runtime-module = "/com.amazon.kepler.keplerscript.runtime.loader_2@IKeplerScript_2_0"
categories = ["com.amazon.category.kva"]
launch-type = "singleton"
## Define your app's service component which can handle data request.
[[components.service]]
id = "com.amazondeveloper.keplervideoapp.content.dataRefresh.provider"
runtime-module = "/com.amazon.kepler.headless.runtime.loader_2@IKeplerScript_2_0"
launch-type = "singleton"
categories = ["com.amazon.category.kepler.media"]
## Define a process group for each component
[processes]
## <other process related entries>
[[processes.group]]
component-ids = ["com.amazondeveloper.keplervideoapp.main"]
[[processes.group]]
component-ids = ["com.amazondeveloper.keplervideoapp.content.dataRefresh.provider"]
[wants]
## Defines that your app has a dependency on the Subscription Entitlement data service
[[wants.service]]
id = "com.amazon.tv.developer.dataservice.main"
[needs]
## Defines the privilege your app needs in order to use the Subscription Entitlement interface to provide data
[[needs.privilege]]
id = "com.amazon.tv.subscription-entitlement.privilege.provide-data"
[offers]
## Defines the data refresh service component of your app
[[offers.service]]
id = "com.amazondeveloper.keplervideoapp.content.dataRefresh.provider"
## Defines the interactive components of your app
[[offers.interaction]]
id = "com.amazondeveloper.keplervideoapp.main"
## Add extras to declare support for Subscription Entitlement
[[extras]]
key = "interface.provider"
## If you're utilizing account login or content launcher interface,
## replace component-id with appropriate service component. Follow Account Login Integration Guide
component-id = "com.amazondeveloper.keplervideoapp.content.dataRefresh.provider"
[extras.value.application]
## Defines support for the Subscription Entitlement interface and the attributes
[[extras.value.application.interface]]
interface_name = "com.amazon.kepler.media.ISubscriptionEntitlementServer"
attribute_options = ["DataRefreshComponentId"]
[extras.value.application.interface.static_values]
DataRefreshComponentId = "com.amazondeveloper.keplervideoapp.content.dataRefresh.provider"
Each interface configuration must be kept separate. Do not combine or mix attributes between different interfaces in the manifest file.
Here is an example of the correct way to define multiple interfaces.
[extras.value.application]
[[extras.value.application.interface]]
interface_name = "com.amazon.kepler.media.IContentPersonalizationServer"
attribute_options = ["SupportedCustomerLists", "DataRefreshComponentId"]
[extras.value.application.interface.static_values]
SupportedCustomerLists = ["Watchlist"]
DataRefreshComponentId = "com.amazondeveloper.keplervideoapp.content.dataRefresh.provider"
[[extras.value.application.interface]]
interface_name = "com.amazon.kepler.media.IContentLauncherServer"
override_command_component = { LaunchContent = "com.amazondeveloper.keplervideoapp.main" }
attribute_options = ["partner-id"]
[extras.value.application.interface.static_values]
partner-id = "<Your partner id>"
And here is an incorrect way to do this. Do not do it this way.
[extras.value.application]
[[extras.value.application.interface]]
interface_name = "com.amazon.kepler.media.IContentPersonalizationServer"
attribute_options = ["SupportedCustomerLists", "DataRefreshComponentId"]
[[extras.value.application.interface]]
interface_name = "com.amazon.kepler.media.IContentLauncherServer"
override_command_component = { LaunchContent = "com.amazondeveloper.keplervideoapp.main" }
attribute_options = ["partner-id"]
[extras.value.application.interface.static_values]
partner-id = "<Your partner id>"
SupportedCustomerLists = ["Watchlist"]
DataRefreshComponentId = "com.amazondeveloper.keplervideoapp.content.dataRefresh.provider"
Step 3. Make a sample API call
Begin with a sample/mock event generated at the app launch. To construct the event and send it, use the following code:
// Example subscription entitlement entry generated and sent
const subscriptionEntry: ISubscriptionEntitlementEntry = new SubscriptionEntitlementEntryBuilder()
.acquisitionTimestamp(new Date())
.expirationTimestamp(new Date())
.subscriptionId('testSubscriptionId')
.build();
// Send the event
SubscriptionEntitlementServer.reportNewSubscription(subscriptionEntry);
Step 4. Validate the integration
Trigger the sample event code you constructed to run inside your app. After you run the code successfully, view the logs to validate the SDK has been linked to your app and is processing the message.
You can validate the steps by searching your app logs:
journalctl --follow |grep -Ei 'kepler.tv.subscription_entitlement'
The log message you receive for the event shown in Step 3 should contain at least one of the below logs:
Dec 15 01:00:17.721539 carat-3fc19fb5ae526e4d local0.info keplerscript-ru[22814]: 1483317178 INFO kepler.tv.subscription_entitlement:ISubscriptionEntitlementServer getOrMakeServer called
Dec 15 01:00:17.725200 carat-3fc19fb5ae526e4d local0.info keplerscript-ru[22814]: 1483317178 INFO kepler.tv.subscription_entitlement.anse.turbomodule:reportNewSubscription called
Dec 15 01:00:17.725311 carat-3fc19fb5ae526e4d local0.info keplerscript-ru[22814]: 1483317178 INFO kepler.tv.subscription_entitlement:SubscriptionEntitlementEntryBuilder build() called
Dec 15 01:00:17.725360 carat-3fc19fb5ae526e4d local0.info keplerscript-ru[22814]: 1483317178 INFO kepler.tv.subscription_entitlement:reportNewSubscription call received
Step 5. Make API calls as part of in-app functionality
Review the When to Send section and locate where in your app you need to make API calls to the Vega Subscription Entitlement.
Step 6. Implement your data pull service for background or off-device data
To allow Amazon to pull data from your app, implement the service as described below. This service contains everything needed for setup and connection and requires you to implement functions to send data to a receiver object. The object allows you to share data in chunks, as needed, to prevent loading large lists into memory.
- Create a service.js file on the same path as the package.json with the following content. This alerts the system about the entry points for your
content.dataRefresh.provider
service.import { HeadlessEntryPointRegistry } from '@amazon-devices/headless-task-manager'; import { onStartService, onStopService, } from './src/headless/HeadlessService'; HeadlessEntryPointRegistry.registerHeadlessEntryPoint2( 'com.amazondeveloper.keplervideoapp.content.dataRefresh.provider::onStartService', () => onStartService, ); HeadlessEntryPointRegistry.registerHeadlessEntryPoint2( 'com.amazondeveloper.keplervideoapp.content.dataRefresh.provider::onStopService', () => onStopService, );
- Create your Headless Service Interface file under src/headless/HeadlessServiceInterface.ts with the following content:
import { IComponentInstance, } from "@amazon-devices/react-native-kepler"; export interface HeadlessServiceInterface { /** * This function is called when native service onStart is called. * @param {IComponentInstance} componentInstance - The headless component instance. */ onStart(componentInstance: IComponentInstance): Promise<void>; /** * This function is called when native service onStop is called. * @param {IComponentInstance} componentInstance - The headless component instance. */ onStop(componentInstance: IComponentInstance): Promise<void>; }
- Create your data pull service under src/headless/HeadlessService.ts with the following content:
import { ISubscriptionEntitlementsHandler, ISubscriptionEntitlementsProvider, SubscriptionEntitlementServer } from "@amazon-devices/kepler-subscription-entitlement"; import { HeadlessServiceInterface } from "./HeadlessInterface"; import { IComponentInstance } from "@amazon-devices/react-native-kepler"; /***********Subscription Entitlement Handlers*************/ const subscriptionEntitlementHandler: ISubscriptionEntitlementsHandler = { getAllSubscriptionEntitlements: ( subscriptionEntitlementsProvider: ISubscriptionEntitlementsProvider, ) => { subscriptionEntitlementsProvider.addSubscriptionEntitlementChunk(<ADD ENTITLEMENTS>); subscriptionEntitlementsProvider.commit(); }, }; class HeadlessService implements HeadlessServiceInterface { onStart(componentInstance: IComponentInstance): Promise<void> { SubscriptionEntitlementServer.setSubscriptionEntitlementsHandlerForComponent( subscriptionEntitlementHandler, componentInstance ); return Promise.resolve(); } onStop(componentInstance: IComponentInstance): Promise<void> { return Promise.resolve(); } } const HeadlessServiceInstance = new HeadlessService() as HeadlessServiceInterface; export const onStartService = (componentInstance: IComponentInstance): Promise<void> => { return HeadlessServiceInstance.onStart(componentInstance); }; export const onStopService = (componentInstance: IComponentInstance): Promise<void> => { return HeadlessServiceInstance.onStop(componentInstance); };
Implementation details
Make changes to your catalog integration when directed by your Amazon contact
To make use of the entitlement and activity data, Fire TV needs the following data from your existing Fire TV catalog integration. Fire TV’s public catalog integration documentation will be updated to include these elements in the future, but here is a preview of what will be needed concerning the Vega Subscription Entitlement integration. Your Amazon contact will inform you of the right time to begin these catalog changes.
- Subscription IDs - Existing subscription offers need to specify the Subscription ID they apply to.
Reporting updates
The SDK allows you to share information using three types of operations:
New
(reportNewSubscription
)- Represents an incremental update to add a new entry to the dataset.Removed
(reportRemovedSubscription
) - Represents a decremental update to remove an entry from the dataset.Refreshed
(reportRefreshedSubscriptions
) - Indicates that there have been changes to the dataset due to off-device actions, and a new refreshed version of the list needs to be fetched using the data pull service.
The New
and Removed
operations are useful when the customer interacts with your app and changes their subscription levels. The Refreshed
operation is useful for situations when there are significant changes to the list due to customer sign-in, off-device activity, or if you suspect the list is out of sync for another reason.
Providing large sets of data
When supplying large amounts of data through the data pull service, we recommend you pull the data in reasonably small pages from your cloud backend and call the provider APIs as the data is is being pulled down. This limits the memory usage of your service and prevent your app from being terminated by the system.
Here is an example flow.
const subscriptionEntitlementHandler: ISubscriptionEntitlementsHandler = {
getAllSubscriptionEntitlements: (
provider: ISubscriptionEntitlementsProvider,
) => {
let myCloudHasMoreData = true;
while(myCloudHasMoreData){
let myCloudResponse = getNextPageFromMyBackend();
let myCloudData = myCloudResponse.getData();
let subscriptions: ISubscriptionEntitlementEntry[] = [];
for(let element in myCloudData){
let subscription = <build data with SubscriptionEntitlementEntryBuilder>
subscriptions.push(subscriptions)
}
provider.addSubscriptionEntitlementChunk(subscriptions);
myCloudHasMoreData = myCloudResponse.hasMoreData();
}
provider.commit();
},
};
Last updated: Sep 30, 2025