Guidelines for creating a good content API
As the owner of your content, you know best how your content is structured and how it should be presented on the app. Because of that, we try to impose as little as possible on how to structure your content API.
Zapp, using its DSP framework, provides a middleware to translate your date structure in a way that our apps can "understand".
With that said, A lot of content based apps follow the same hierarchies paradigms. here are a few guidelines and suggestion that will help you structure your API if you are building it from scratch, or if you are looking for an OVP CMS provider.
General guidelines for API structure
- We recommend that your API will return its response in the JSON format.
- Your API URLs should be hosted using
https
. - Its best to follow the REST methods names (GET, POST, etc.) When you can use GET as it will allow caching.
- Host your APIs on a CDN or make sure your APIs can mange the anticipated scale your apps will have.
- Add documentation to your API.
Returning a feed of entries
Zapp apps and their screens are built from components. In general, a component wraps a list of items (also called a feed of entries) and may also include extra metadata like the title or thumbnail. For example a component can be a list, rail or a grid of episodes of a specific season wrapped with a title of the season show name and a show hero thumbnail.
When designing your API take this into account and allow your API calls to return lists of items that corresponds to the way you want to list them in the app.
The anatomy of a content entry
Each entry of the feed represents the single item (also known as cell) in a given component. You can view a cell also as the teaser of the single item you want to present. For example a cell item can hold a single episode or a show.
When deciding what fields you should return on each feed entry think of all the metadata you would like to show in the cell UI on the app. each field you want to present should be derived for the data that is being passed in the entry; For example, if you want to present an episode teaser with a title, description, season, episode numbers and a thumbnail, you should return each of those fields in each entry. Furthermore, except form all the teaser fields you should return in the entry what type of content you would like to open when a user taps/click on the cell and the id or the stream URL (for videos) of the content you want open.
Examples of fields you might consider returning - according to your content and business needs:
All fields and fields formats are optional depending on your needs. The list bellow is an example of possibilities and best practice recommendations. For the full list of API please have a look here
{
"entry": [ // array of entries
{
"id": "93adae53-8b45-4847-8c7c-75b93d9048a2", // the unique id of the entry
"title": "My Episode title",
"summary": "My content description",
"media_group": [
{
"type": "image",
"media_item": [ // we recommend to pass thumbnails as an object where each key represents the semantic meaning of that image.
{
"src": "https://example.com/images/big-brother-thumb.png",
"key": "thumbnail-16x9",
},
{
"src": "https://example.com/images/big-brother-thumb.png",
"key": "hero-4x3",
}
]
},
],
"content": {
"type": "video/hls",
"src": "https://example.com/big-brother-s1-e1.m3u8", // If the stream is not protected we recommend to pass its full absolute path in the entry, if it does make sure you have an API call that we can use to retrieve the stream URL using the entry id (or any other set entry field)
},
"extensions": {
"is-live": true, // good for differentiating between future and current programs on a live channel
"duration": 3200, // duration can be in any format but we recommend to pass it the number of seconds,
"start-time": 1602009661153, // Good for live events, we recommend using a UTC timestamp as it will make sure your time is valid across timezones
"requires-authentication": true, // note if content is restricted for authenticated users only
"geo-restriction": ["US", "FR"] //indicate if a content should be restricted for a specific set of countries. we recommend using a white list country codes of allowed countries
}
}
]
}
Content hierarchies
On many cases you content has some sort of hierarchy. for example, is common to have a list of shows that have a list of seasons with a list of episodes on each season. Construct you API in a way that will allow you to query items according your content hierarchy. For example create API calls to retrieve all the episodes of a specific season.
Filtering options
Its common to create collection of items according to a specific category or tag.
For example you might want to have a method that returns only featured shows and display them on your home screen.
A good practice would be to tag those items in your code and allow to add tag filter to your all shows
API. So instead of creating a specific API method to retrieve featured shows that allow to
add a filter query tag to your all-shows request
Playlists & Collections
There might be use cases that you would like to create manual collections/playlists of items. We recommend creating an API method that will allow you to retrieve a specific playlist by providing the playlist id
Search
If you want to provide a search screen in your app make sure you create an API method that can get search query string as its parameter.
SVOD & Protected content
If your content is protected by a payed subscription, a login screen, or a time protected steam, its best not to provide the hls
stream inside the response and instead provide an the id of the item.
Using this method will allow you to cache your response.
Implementing protected steams requires to have a screen hook
/ player hook
plugin that can
authenticate the user and retrieve the signed stream by using the entry id and the user token.
We provide out of the box solution if you are using inPlayer
or MPX
for authentication.
If your API requires another provider,
please make sure you consult with your customer success representative.
AVOD
Our tool offers an out of the box integration with VAST Google IMA
.
If you would like to use IMA to integrate ads inside your steams make sure you pass with each entry
the corresponding ad_url
and offset
. See example
Personalized data
We can create requests that are personalized according to a specific user needs. Make sure your system is build to handle personalized data scale as in many cases those requests can't be cached.
Implementing personalized data requires to have a screen hook
/ player hook
plugin that can
authenticate the user and retrieve its corresponding content.
We provide out of the box solution if MPX
for authentication.
If your API requires another provider,
please make sure you consult with your customer success representative.
Images
We recommend using png
as the format of your image.
We recommend to return an object with multiple thumbnails for each entry to represent different thumbnail aspect rations or resolution. This will allow you to use the right image in the right place on your app's screens.
Make sure you are using images in the right resolution and weight. Makes sure you are using absolute paths to refer the images URL.