Skip to content

Play service API

📘 API v2 released

From version 1.7.0 of the play service, we have released a new version of the playout API. See the difference here.

This page describes the play service API and its different parameters.

OpenAPI reference: Vimond Play Service API — interactive contract for POST /api/v2/asset/{assetId}/play (and deprecated v1).

curl -X POST \
https://{tenant}.play.cf.{domain}/api/v2/asset/{asset-id}/play \
-H 'Content-Type: application/json' \
-H 'Authorization: Bearer {jwt_access_token}' \
-H 'X-Vimond-Subprofile: {subprofile_token}' \
-H 'Accept-Language: {locales}' \
-H 'User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36' \
-d '{
"device": {
"label": "DR_ROBERT_FORD_SWEETWATER_X_SMARTPHONE",
"udid": "f0685750-1417-407b-b9b2-54797b8e8f54"
}
}
'

📘 API Reference

See Reference : Get the Stream URLs for how to fetch the playback information.

The body of the POST play call can be augmented with the user’s device information in oder to deal with cases where content licensing requires enforcing restrictions or limitations on the number of devices a user can use to access the content. See an example of the data format below.

{
"device": {
"label": "CHIEF_HOPPER_IPHONE_X",
"udid": "2cc6031b-80ea-4357-ba7d-e7c72401c542"
}
}

Fields:

  • label - Required label of device and can not be longer than 200 characters
  • udid - Required id of device and can not be longer than 100 characters

🚧 The service will respond with a 400 Bad Request if the requested asset has device limitations but the request does not contain device info in the body.

In order to make the client as light and simple as possible, the play service recommends the best available stream for the end-user. To do this, the play service relies on multiple information. One of them is the User-Agent.

Hence, the tenant’s portal should forward the User-Agent header sent by the browser and the request to the play service should look like this.

If needed, it is possible to override the user agent header. This can be used to override the user agent value, or to complete it. To override the user agent header, you can add the client field in the request body.

{
"device": {
"label": "JIAN_YANG_MAC_BOOK_PRO",
"udid": "2cc6031b-80ea-4357-ba7d-e7c72401c542"
},
"client": {
"browser": {
"name": "Chrome",
"version": "63.0.3239.132",
"major": "63"
},
"engine": {
"name": "WebKit",
"version": "537.36"
},
"os": {
"name": "Mac OS",
"version": "10.13.2"
},
"device": {
"model": "MacBook Pro",
"type": "desktop",
"manufacturer": "Apple",
"description": "Chrome 63.0.3239.132 on OS X 10.13.2 64-bit"
},
"cpu": {
"architecture": "amd64"
}
}
}

By default the play service will respond with a single stream, the minimum set of metadata needed by the player and the set of bad streams if they are any failed open steams. The response document should be as described below:

{
"data": [
{
"assetId": "12345",
"categoryId": "67890",
"assetTitle": "Old Sheldon : The bathroom schedule multiplication",
"startTime": 0.0,
"endTime": 147.877,
"duration": 147.877,
"drmProtected": false,
"live": false,
"recommendedStream": {
"id": "1",
"bitrate": 1500,
"mediaFormat": "mp4",
"mimeType": "video/mp4",
"drmProxyType": "drmtoday.fairplay",
"drm": {
"uri": "https://my-license-url.com/?assetId=env-12345",
"headers": {
"x-dt-auth-token": "some.auth.token"
},
"method": "POST",
"certificateUrl": "https://my-fairplay-certificate.com"
},
"provider": "Amazon",
"manifest": {
"headers": [
{
"Authorization": "Bearer q1w2e3r4t5y6u7i8o9.a1s2d3f4g5h6j7k8l9.z1x2c3v4v5b6n7m8"
}
],
"uri": "https://s3-eu-central-1.amazonaws.com/vmp-vodvideofiles/7380a/Veko_2013_Torsdag_Kayak_720pdfa4(497_R21MP41000).mp4"
}
},
,
"subtitles": [
{
"url": "https://vimond.subtitles-cdn.io/api/web/asset/497/subtitle/11912",
"name": "Old Sheldon (en)",
"locale": "en",
"audience": [
"NORMAL"
]
}
],
"playerEventRequest": {
"body": {
"client": {
"buildName": "${client_build_name}",
"buildVersion": "${client_build_version}",
"deviceId": "1c09edd4-4f29-4777-812b-9ba795c0de28",
"drm": "${client_drm}",
"envPlatform": "${client_env_platform}",
"envVersion": "${client_env_version}",
"pageUrl": "${client_page_url}",
"platform": "web",
"playerEvent": "${player_event}",
"playerState": "${player_state}",
"streamUrl": "${client_stream_url}",
"userAgent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/49.0.2623.112 Safari/537.36",
"videoFormat": "${video_mime_type}",
"videoProtocol": "${video_protocol}",
"viewingSession": "${viewing_session}"
},
"progress": {
"eventNumber": 1,
"assetId": "12345",
"categoryId": "67890",
"title": "Old Sheldon : The bathroom schedule multiplication",
"playbackType": "vod",
"vod": {
"duration": 147.877,
"position": "${vod_stream_position}"
}
},
"eventName": "encrypted_player_log_event",
"originator": "${originator}",
"originatorId": "894c0efa-80b4-4f31-a7d9-6532b463babe",
"subProfileId": "709d0c6eea56d5f8a2cf3947964138f93c8b8960",
"versions": [
"1.0"
],
"tenant": "vimond",
"clientDate": "2015-04-07T11:33:37.383Z",
"logData": "8r394jf834hg743h394j3k9rr3j="
},
"eventInterval": 10,
"uri": "https://{tenant}.player-session.{domain}/external/player-events"
},
"version": {
"type": "short",
"available": [
"short",
"long"
]
}
}
],
"errors": [
{
"title": "BAD_STREAM",
"detail": "1 stream failed with invalid media format: [unknown/hls]",
"code": "3012"
}
],
"links": {
"self": "https://{tenant}.play.cf.{domain}/api/v2/asset/12345/play"
}
}

Although this should be sufficient in most cases, it is possible to extend the response.

The play service API allows you to specify some filters to have more control on the returned streams. These filters are given through query parameters and work as described below:

[block:parameters] { “data”: { “h-0”: “Parameters”, “h-1”: “Possible values”, “h-2”: “Description”, “0-0”: “contentType”, “0-1”: “MimeType format: \n- application/vnd.ms-sstr+xml \n- application/dash+xml \n- application/x-mpegurl \n- video/webm \n- video/mp4 \n- video/flv \n- application/f4m+xml \nBut also shortname to these: \n_hls_, mp4, ism, dash, webm, flv, hds. \nCan be extended with custom mime types.”, “0-2”: “mimeType of the stream needed”, “1-0”: “provider”, “1-1”: “akamai, amazon, … \nDepending on your stream server”, “1-2”: “Content delivery network provider of the stream”, “2-0”: “profile”, “2-1”: “low, medium, high, ultraHigh. \nCan be configured with custom names”, “2-2”: “Quality required by the client”, “3-0”: “platform”, “3-1”: “web, … \nDepending on the tenant platform”, “3-2”: “Tenant’s platform. An asset may be published on some platforms while not on others”, “4-0”: “streamId”, “4-1”: “any valid streamId”, “4-2”: “Will return the stream Id asked by the client”, “5-0”: “excludeStreams”, “5-1”: “an array of streamId”, “5-2”: “stream ids that the client does not want in the response.” }, “cols”: 3, “rows”: 6, “align”: [ “left”, “left”, “left” ] } [/block]

If an asset has versions, you specify which version to get streams for using the versions parameter together with the orderVersionsByPriority parameter.
The asset ID of the endpoint is always the parent asset ID, and then the versions parameter is used to determine the streams to return per the below rules.

[block:parameters] { “data”: { “h-0”: “Parameters”, “h-1”: “Possible values”, “h-2”: “Description”, “0-0”: “versions”, “0-1”: “a comma-separated list of requested asset versions”, “0-2”: “Which version of the asset that should be used. If multiple versions are specified, then the highest priority version is used, see the orderVersionsByPriority parameter. Similarly, if the the client does not request any specific version(s) then by default the highest priority version among the available versions of the asset will be used. \n \nWhen the versions parameter is provided, at least one of the requested versions must match an actual version of the asset.”, “1-0”: “orderVersionsByPriority”, “1-1”: “boolean”, “1-2”: “Defaults to true, in which case the asset’s pre-defined versioning priority is used. \nIf false, override the pre-defined priority with the order defined in the versions parameter, i.e., the first of the requested versions that match an actual version of the asset.” }, “cols”: 3, “rows”: 2, “align”: [ “left”, “left”, “left” ] } [/block]

The response can be augmented via the query parameter “extraFields”. This parameter contains an array of string and is empty by default. At the moment this field can be augmented with the following values:

[block:parameters] { “data”: { “h-0”: “Value”, “h-1”: “Description”, “0-0”: “markers”, “0-1”: “Field containing an array of Asset’s marker. These markers will be sorted by start time.”, “1-0”: “alternativeStreams”, “1-1”: “Contains all the other streams that match the filters given in the request (See Filters ).”, “2-0”: “streamsTemplate”, “2-1”: “Contains a template to make the play request with the different parameters and their possible values.”, “3-0”: “assetType”, “3-1”: “String value holding the asset type”, “4-0”: “metadata.\*”, “4-1”: “An arbitrary metadata field defined on the asset. \nOnly a limited number of metadata fields can be requested; if you need to look up many metadata fields you must instead make a request to the Content Discovery service. The default max limit is 3 metadata fields.” }, “cols”: 2, “rows”: 5, “align”: [ “left”, “left” ] } [/block]

You can find an example of how to set up these fields below:

curl -X POST \
https://{tenant}.play.cf.{domain}\
/api/v2/asset/{asset-id}\
/play?extraFields=markers,alternativeStreams,streamsTemplate,metadata.director \
-H 'Content-Type: application/json' \
-H 'Authorization: Bearer {jwt_access_token}' \
-H 'X-Vimond-Subprofile: {subprofile_token}' \
-H 'Accept-Language: {locales}' \
-H 'User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36' \
-d '{
"device": {
"label": "SHELDON_ALIENWARE_LAPTOP",
"udid": "f0685750-1417-407b-b9b2-54797b8e8f54"
}
}
'

And the augmented response will be as described below:

{
"data": [
{
"assetId": "54321",
"categoryId": "98760",
"assetTitle": "The bored developer writing documentation : If you read these line, please help me!",
"duration": 147.877,
"startTime": 0.0,
"endTime": 147.877,
"live": false,
"drmProtected": false,
"metadata": {
"director": "The Director"
},
"recommendedStream": {
"id": "1",
"bitrate": 2000,
"mediaFormat": "mp4",
"mimeType": "video/mp4",
"provider": "amazon",
"manifest": {
"headers": [],
"uri": "https://s3-eu-central-1.amazonaws.com/vmp-vodvideofiles/7380a/call_developer_abuse_720pdfa4(497_R21MP41000).mp4"
}
},
"streamTemplate": {
"profile": [ "low", "medium", "high", "ultraHigh" ],
"provider": [ "amazon"],
"mimeType": [ "application/x-mpegurl", "application/vnd.ms-sstr+xml",
"application/f4m+xml", "application/dash+xml", "video/mp4"]
},
"alternativeStreams": [
{
"id": "4",
"bitrate": 2000,
"mediaFormat": "ism",
"mimeType": "application/vnd.ms-sstr+xml",
"provider": "amazon",
"manifest": {
"headers": [],
"uri": "https://s3-eu-central-1.amazonaws.com/7380a/call_developer_abuse_(497_ISMUSP).ism/Manifest"
}
},
{
"id": "5",
"bitrate": 1500,
"mediaFormat": "hds",
"mimeType": "application/f4m+xml",
"provider": "amazon",
"manifest": {
"headers": [],
"uri": "https://d3bwpqn4orkllw.cloudfront.net/7380a/call_developer_abuse_(497_ISMUSP).ism/call_developer_abuse_(497_ISMUSP).f4m"
}
},
{
"id": "6",
"bitrate": 1200,
"mediaFormat": "dash",
"mimeType": "application/dash+xml",
"provider": "amazon",
"manifest": {
"headers": [],
"uri": "https://d3bwpqn4orkllw.cloudfront.net/7380a/call_developer_abuse_(497_ISMUSP).ism/call_developer_abuse__(497_ISMUSP).mpd"
}
}
],
"subtitles": [
{
"url": "https://vimond.subtitles-cdn.io/api/web/asset/497/subtitle/11912",
"name": "The bored developer ( en )",
"locale": "en",
"audience": [ "NORMAL" ]
}
],
"markers": [
{
"title": "test_chapter",
"description": "introduction",
"type": "chapter",
"startTime": 3.424,
"endTime": 7.163,
"images": {
"url": "https://image-service.ha.dev.vops.io/api/v2/img/vis/api/v2/img//5a5f4774e4b0c8aae35c82f9-1516193652681%3Flocation=main%26region=eng%26ver=a08bfp"
}
}
],
"playerEventRequest": {
"body": {
"client": {
"buildName": "${client_build_name}",
"buildVersion": "${client_build_version}",
"deviceId": "1c09edd4-4f29-4777-812b-9ba795c0de28",
"drm": "${client_drm}",
"envPlatform": "${client_env_platform}",
"envVersion": "${client_env_version}",
"pageUrl": "${client_page_url}",
"platform": "web",
"playerEvent": "${player_event}",
"playerState": "${player_state}",
"streamUrl": "${client_stream_url}",
"userAgent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/49.0.2623.112 Safari/537.36",
"videoFormat": "${video_mime_type}",
"videoProtocol": "${video_protocol}",
"viewingSession": "${viewing_session}"
},
"progress": {
"eventNumber": 1,
"assetId": "54321",
"categoryId": "98760",
"title": "The bored developer writing documentation : If you read these line, please help me!",
"playbackType": "vod",
"vod": {
"duration": 147.877,
"position": "${vod_stream_position}"
}
},
"eventName": "encrypted_player_log_event",
"originator": "${originator}",
"originatorId": "894c0efa-80b4-4f31-a7d9-6532b463babe",
"subProfileId": "709d0c6eea56d5f8a2cf3947964138f93c8b8960",
"versions": ["1.0"],
"tenant": "vimond",
"clientDate": "2015-04-07T11:33:37.383Z",
"logData": "8r394jf834hg743h394j3k9rr3j="
},
"eventInterval": "10.0",
"uri": "https://{tenant}.player-session.{domain}/external/player-events"
},
"version": {
"type": "short",
"available": [
"short",
"long"
]
}
}
],
"links": {
"self": "https://{tenant}.play.{domain}/api/v2/asset/54321/play"
}
}

In order to get better analytics on the play request is it recommended to add a query parameter with the name of the calling application:

curl -X POST \
http://{tenant}.play.cf.{domain}\
/api/v2/asset/{asset-id}/play?appName=botherguts \
-H 'Content-Type: application/json' \
-H 'Authorization: Bearer {jwt_access_token}' \
-H 'X-Vimond-Subprofile: {subprofile_token}' \
-H 'Accept-Language: {locales}' \
-H 'User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36' \
-d '{
"device": {
"label": "ROLO_HAYNES_IMPLANT",
"udid": "f0685750-1417-407b-b9b2-54797b8e8f54"
}
}
'

If a stream returned in the response is drm protected your player needs to fetch a drm license to be able to play it. In that case the stream will contain the necessary information in these two fields:

  • drmProxyType: A string representing which drm provider is protecting the stream.
  • drm: A json with the following model:
{
"uri": "https://my-license-url.com/?assetId=env-12345",
"headers": {
"x-dt-auth-token": "some.auth.token"
},
"method": "POST",
"certificateUrl": "https://my-fairplay-certificate.com"
}

From the information in the drm block you can create a request to fetch the drm license. The body you need to send in the request will be different for each drm provider, and it is required to follow the standards of the given provider.

  • uri - The uri for the license request.
  • method - Implies if you need to make a GET or a POST request.
  • headers - If present, it contains all headers you need in the request.
  • certificateUrl - If present, it contains the url for a certificate. This only applies for the fairplay provider.
HTTP return codeDescription
200The play request was executed successfully
204The play request did not match any existing stream.
400The request is invalid
401The credentials are missing or invalid
403The user does not have the right entitlements for this asset.
404The asset does not exist or has not been published
503The play service failed to process the request.

All the bad streams will return in the following format.

"errors": [
{
"title": "BAD_STREAM",
"detail": "2 streams failed with invalid media formats : [unknown/hls, unknown/dash]",
"code": "3012"
},
{
"title": "BAD_STREAM",
"detail": "1 stream failed with invalid URI : [Illegal character in path]",
"code": "3012"
}
],

All the failed requests will return a body in the following format:

{
"errors": {
"title": "INVALID_QUERY_PARAM",
"detail": "Empty or invalid query parameter",
"code": 1004
}
}

All times and durations in the response document are expressed in seconds with decimals.

The following are the changes to be aware of when migrating from v1 to the v2 playback endpoint:

  • Playback of assets with transmission time in the future is no longer allowed. The request is successful with a 200 OK response with the basic asset information without streams. There will also be an error as part of the response explaining why there aren’t any streams.
  • “Fields” query parameter is renamed to “extraFields”
  • The error 3003 has it’s title changed from MISSING_CONTENT_PACKAGE to MISSING_ENTITLEMENT