Content Launcher Integration Guide
This document explains how to integrate Content Launcher into your app. Media apps typically require integration with three key APIs:
- The Content Launcher API
- Vega Media Controls API
- Account Login API
The system implements Content Launcher and Vega Media Controls APIs as in an interactive component, which is the main component handling Vega media queries. The Account Login API functions as a service component.
Step 1: Update your App's manifest file
In your app's manifest.toml file, include Content Launcher support. This example assumes your package ID is com.amazondeveloper.keplervideoapp. Replace this package ID with your app's package ID.
Configure your app to interact with the Vega Media Content Launcher APIs.
schema-version = 1
[package]
title = "<Your app title>"
id = "com.amazondeveloper.media.sample"
[components]
[[components.interactive]]
id = "com.amazondeveloper.media.sample.main"
runtime-module = "/com.amazon.kepler.keplerscript.runtime.loader_2@IKeplerScript_2_0"
launch-type = "singleton"
# The category "com.amazon.category.kepler.media" is only necessary for the primary component, which is identified in the [[extras]]
# section of the manifest using the "component-id" value.
categories = ["com.amazon.category.main", "com.amazon.category.kepler.media"]
[processes]
[[processes.group]]
component-ids = ["com.amazondeveloper.media.sample.main"]
[offers]
[[offers.interaction]]
id = "com.amazondeveloper.media.sample.main"
[[message]]
uri = "pkg://com.amazondeveloper.media.sample.main"
# Match the privileges used in [[offers.interaction]]. If privileges are not added, then use "*".
sender-privileges = ["*"]
receiver-privileges = ["self"]
[[offers.module]]
id = "/com.amazondeveloper.media.sample.module@ISomeUri1"
includes-messages = ["pkg://com.amazondeveloper.media.sample.main"]
[[extras]]
key = "interface.provider"
component-id = "com.amazondeveloper.media.sample.main"
[extras.value.application]
[[extras.value.application.interface]]
interface_name = "com.amazon.kepler.media.IContentLauncherServer"
# The "override_command_component" field is only necessary when the "component-id" specified in the [[extras]]
# section differs from the one you're providing here. This enables you to use a different component for
# command execution than the one initially defined in the extras, giving you flexibility in your
# configuration setup.
# For example, if you're using Account Login interface in addition to the Content Laucher interface
# you would need to override the Account Login status attribute to be directed to the service
# component with the following line:
# override_command_component = { Status = "com.amazondeveloper.media.sample.interface.provider" }
attribute_options = ["partner-id"]
static-values = { partner-id = "<Your partner id>" }
[needs]
[[needs.module]]
id = "/com.amazon.kepler.media@IContentLauncher1"
partner-id is the same unique identifier (PARTNER_ID) used in Fire OS launcher integration. Contact your Amazon representative for support and further clarification.Step 2: Include the necessary package dependencies in your app
In the package.json file, add the @amazon-devices/kepler-media-content-launcher package as a dependency.
"dependencies": {
"@amazon-devices/kepler-media-content-launcher": "^2.0.0",
},
Step 3: Implement the Content Launcher API
-
Define the Content Launcher handler.
Instantiate a new
ContentLauncherServerComponent. Develop a handler object that encapsulates the callback function.import { ILauncherResponse, IContentLauncherHandler, ContentLauncherStatusType, ContentLauncherServerComponent, ILaunchContentOptionalFields, } from '@amazon-devices/kepler-media-content-launcher'; ... // Create an instance of ContentLauncherServerComponent let factory = new ContentLauncherServerComponent(); // Create a handler that is called when content is requested to be launched. const contentLauncherHandler: IContentLauncherHandler = { async handleLaunchContent( _optionalFields: ILaunchContentOptionalFields, ): Promise<ILauncherResponse> { console.log('Content_Launcher_Sample: handleLaunchContent invoked'); //Iterate here to fetch data, //business logic to handle launch request let launcherResponse = factory .makeLauncherResponseBuilder() .contentLauncherStatus(ContentLauncherStatusType.SUCCESS) .build(); return Promise.resolve(launcherResponse); }, };The handler should process the request, return a Promise to
ILauncherResponse, and create it with an instance of theContentLauncherServerComponent. Set the status ofcontentLauncherStatusforLauncherResponsetoContentLauncherStatusType.SUCCESSif your app successfully processed the request. Set the status toContentLauncherStatusType.AUTH_FAILEDif your app can't process the request due to authorization issues. Set the status toContentLauncherStatusType.URL_NOT_AVAILABLEfor everything else. -
Implement the Vega Media Content Launcher in your interactive app.
To implement the Vega Media Content Launcher in your interactive app, start by obtaining a singleton instance of
IContentLauncherServerAsync. ImplementIContentLauncherServerAsyncby using thegetOrMakeServermethod on yourContentLauncherServerComponentinstance. Next, create a handler object implementing theIContentLauncherHandlerinterface to process content launch requests. Call the 'setHandlerForComponent' method for the 'IContentLauncherServerAsync' instance. This associates the handler with the correct component. Pass the handler and the appropriateIComponentInstance. In an interactive app, you can obtain theIComponentInstanceusing theuseComponentInstancemethod. For React Native apps, set up the handler within theuseEffecthook. It should initialize Content Launcher as soon as the component mounts and theIComponentInstanceare available. This tightly integrates Content Launcher functionality with your component's lifecycle. It also lets your app to handle Vega Content Launcher commands efficiently from the moment it's initialized. This setup is important for apps with multiple components, so that each component usesIComponentInstance, preventing confusion in callback routing.import { useComponentInstance, IComponentInstance } from '@amazon-devices/react-native-kepler'; export const App = () => { const componentInstance: IComponentInstance = useComponentInstance(); useEffect(() => { const factory = new ContentLauncherServerComponent(); const contentLauncherHandler: IContentLauncherHandler = { async handleLaunchContent( _optionalFields: ILaunchContentOptionalFields, ): Promise<ILauncherResponse> { console.log('Content_Launcher_Sample: handleLaunchContent invoked.'); // Iterate to fetch data.. //..here const launcherResponse = factory .makeLauncherResponseBuilder() .contentLauncherStatus(ContentLauncherStatusType.SUCCESS) .build(); return Promise.resolve(launcherResponse); }, }; const contentLauncherServer = factory.getOrMakeServer(); contentLauncherServer.setHandlerForComponent(contentLauncherHandler,componentInstance); return () => {}; }, []); // Create a user interface for your provider app here. };
Implementation details
The IContentLauncherHandler handler takes one parameter that defines what content to play or show search results.
- Optional fields passed through a pointer to an object implementing the
ILaunchContentOptionalFieldsinterface.
Content Launcher request examples
The following examples explain contentSearch parameter values for some key Content Launcher use cases. This example lists all supported use cases. Content Launcher is invoked and the app launches for every use case.
The following sample catalog for streamz_us includes example entries for the movie Seabound and the TV show The SeaShow: The Real Story.
...
<Movie>
<ID>1700000725</ID>
<Title locale="en-US">Seabound</Title>
<Offers>
<SubscriptionOffer>
<LaunchDetails>
<Quality>UHD</Quality>
<Subtitle>en-US</Subtitle>
<LaunchId>tv.streamz/movie/46720001</LaunchId>
</LaunchDetails>
</SubscriptionOffer>
<FreeOffer>
<Regions>
<Territories>US</Territories>
</Regions>
<LaunchDetails>
<Quality>SD</Quality>
<Subtitle>en-US</Subtitle>
<LaunchId>tv.streamz/movie/467200002</LaunchId>
</LaunchDetails>
</FreeOffer>
</Offers>
</Movie>
<TvShow>
<ID>1700000123</ID>
<Title locale="en-US">The SeaShow: The Real Story</Title>
<Offers>
<FreeOffer>
<Regions>
<Territories>US</Territories>
</Regions>
<LaunchDetails>
<Quality>HD</Quality>
<Subtitle>en-US</Subtitle>
<LaunchId>459800033</LaunchId>
</LaunchDetails>
</FreeOffer>
</Offers>
</TvShow>
<TvSeason>
<ID>1700000234</ID>
<Title locale="en-US">Season 1</Title>
<Offers>
<FreeOffer>
<Regions>
<Territories>US</Territories>
</Regions>
<LaunchDetails>
<Quality>HD</Quality>
<Subtitle>en-US</Subtitle>
<LaunchId>453200012</LaunchId>
</LaunchDetails>
</FreeOffer>
</Offers>
<ShowID>1700000123</ShowID>
<SeasonInShow>2</SeasonInShow>
</TvSeason>
<TvEpisode>
<ID>1700000825</ID>
<Title locale="en-US">The Seashow. Story Starts</Title>
<Offers>
<FreeOffer>
<Regions>
<Territories>US</Territories>
</Regions>
<LaunchDetails>
<Quality>HD</Quality>
<Subtitle>en-US</Subtitle>
<LaunchId>453100008</LaunchId>
</LaunchDetails>
</FreeOffer>
</Offers>
<ShowID>1700000123</ShowID>
<SeasonID>1700000234</SeasonID>
<EpisodeInSeason>5</EpisodeInSeason>
</TvEpisode>
...
Launch content through the remote
Launch the movie Seabound using a remote from the Vega TV Home screen.
"parameterList": [
{ // parameter 0
"type": 13, // ContentSearchParamType::VIDEO,
"value": , // Content title will not be populated
"externalIdList": [{
"name": "catalogContentId", // Will be deprecated. Ignore this
"value": "tv.catalog/movie/46720000" // ID or LaunchId from catalog
},
{
"name": "amzn_id",
"value": "tv.catalog/movie/46720000" // ID or LaunchId from catalog
}
]
}
]
The app should identify the movie using tv.streamz/movie/46720000 for the LaunchId, and play it directly.
LaunchId, <ID> is passed as the value.Quickplay with voice
Play movie Seabound through voice. Use the utterance "Alexa, Play Seabound."
autoPlay will be true here. The following example includes the contentSearch: IContentSearch values. The app launches and it should play content directly using ID 1700000725.
[
{ // parameter 0
"type": 13, // ContentSearchParamType::VIDEO
"value": "Seabound", // search string
"externalIdList": [{
"name": "streamz_us" // your catalog id. Will be deprecated. Ignore this
"value": "1700000725" // ID from catalog
},
{
"name": "amzn_id"
"value": "1700000725" // ID from catalog
}
]
}
]
streamz_us is a placeholder for the catalog ID in this example. Alexa doesn't use LaunchID even when it is present in the catalog.Playing a specific episode with voice
The following catalog sample represents a TV Show SeaShow: The Real Story, its season, and an episode. The Alexa utterance "Alexa, Play Season 2 Episode 5 from The SeaShow: The Real Story," invokes the app to play the specific episode.
autoPlay will be true here. contentSearch includes the show ID, not the episode ID. The app must identify the exact episode using ID 1700000123, ContentSearchParamType::SEASON, and ContentSearchParamType::EPISODE values.
[
{ // parameter 0
"type": 13, // ContentSearchParamType::VIDEO
"value": "Season Two Episode Five The SeaShow: The Real Story",
"externalIdList": [{
"name": "streamz_us", // Will be deprecated, Ignore this
"value": "1700000123" // ID of the Show from catalog
},
{
"name": "amzn_id",
"value": "1700000123" // ID of the Show from catalog
}]
},
{ // parameter 1
"type": 14, // ContentSearchParamType::SEASON
"value": "2", // Season number in catalog
"externalIdList": []
},
{ // parameter 2
"type": 15, // ContentSearchParamType::EPISODE
"value": "5", // episode number in catalog
"externalIdList": []
}
]
Last updated: Mar 23, 2026

