StreamLab API
StreamLab Introduction
https://developer.bitmovin.com/playback/docs/stream-lab-introduction
Overview
The API follows REST principles, with all operations performed using HTTP GET, POST, PATCH, or DELETE requests on resources.
Rate limits:
GET
: 25 requests per secondPOST
: 5 requests per secondPATCH
: 5 requests per secondDELETE
: 5 requests per second
API
Base URL: https://api.bitmovin.com/v1
Request example
curl -X POST https://api.bitmovin.com/v1/player/testing/streams \
-H 'Content-Type: application/json' \
-H 'X-Api-Key: <apiKey>' \
--data-raw '{"config":{"name":"Imported from \"Try your stream\" on 4/29/2025, 2:36:20 PM","streamType":"dash","streamDrmType":"none","streamUrl":"https://bitmovin-a.akamaihd.net/content/MI201109210084_1/mpds/f08e80da-bf1d-4e3d-8899-f0f6155f6efa.mpd","version":1}}'
Stream
Resource and API
Stream
Resource and APIStream
resource
Stream
resource{
"id": "846858ee-c215-4199-ad65-7675ce51f370",
"config": {
"name": "Imported from \"Try your stream\" on 4/28/2025, 5:17:31 PM",
"streamType": "dash",
"streamDrmType": "widevine",
"streamUrl": "https://bitmovin-a.akamaihd.net/content/art-of-motion_drm/mpds/11331.mpd",
"version": 1,
"streamDrmLicenseUrl": "https://widevine-proxy.appspot.com/proxy",
"drmHeaders": { "Test": "Test" }
},
"vpnLocationId": "4ff48470-3c45-416c-8013-08360ce320ea",
"suiteId": "6f74025c-1ff1-4d2e-af9c-2d95f3e581af",
"createdAt": "2025-04-28T13:17:31.548Z",
"updatedAt": "2025-04-28T13:17:31.548Z"
}
Details about properties:
vpnLocationId
- what VPN location to use to test the streamconfig.drmHeaders
- custom headers to pass to the DRM server
Required creational POST body attributes:
config.name
config.streamType
-hls
ordash
config.streamDrmType
-widevine
,playready
, ornone
config.streamUrl
config.version
-1
config.streamDrmLicenseUrl
- required only ifstreamDrmType
is notnone
Optional POST body creational attributes:
config.drmHeaders
vpnLocationId
Create stream
POST v1/player/testing/streams
- returns a Stream
resource.
Body example
{
"config": {
"name": "Imported from \"Try your stream\" on 4/28/2025, 5:17:31 PM",
"streamType": "dash",
"streamDrmType": "widevine",
"streamUrl": "https://bitmovin-a.akamaihd.net/content/art-of-motion_drm/mpds/11331.mpd",
"version": 1,
"streamDrmLicenseUrl": "https://widevine-proxy.appspot.com/proxy"
}
}
Response example
{
"data": {
"result": {
"id": "846858ee-c215-4199-ad65-7675ce51f370",
"config": {
"name": "Imported from \"Try your stream\" on 4/28/2025, 5:17:31 PM",
"streamType": "dash",
"streamDrmType": "widevine",
"streamUrl": "https://bitmovin-a.akamaihd.net/content/art-of-motion_drm/mpds/11331.mpd",
"version": 1,
"streamDrmLicenseUrl": "https://widevine-proxy.appspot.com/proxy"
},
"suiteId": "6f74025c-1ff1-4d2e-af9c-2d95f3e581af",
"createdAt": "2025-04-28T13:17:31.548Z",
"updatedAt": "2025-04-28T13:17:31.548Z"
}
},
"requestId": "2409974c-2433-11f0-aea9-e27f83dd5332",
"status": "SUCCESS"
}
Patch stream
PATCH v1/player/testing/streams
- returns a Stream
resource.
Accepts the same properties as the create endpoint. All properties are optional. Only new property values will be applied. If one of these streamDrmLicenseUrl
, streamDrmType
, streamType
, streamUrl
, version
, drmHeaders
is changed, it will trigger re-validation of all linked test environments.
Get stream details
GET v1/player/testing/streams/<streamId>
Response
{
"data": {
"result": {
"id": "846858ee-c215-4199-ad65-7675ce51f370",
"config": {
"name": "Imported from \"Try your stream\" on 4/28/2025, 5:17:31 PM",
"version": 1,
"streamUrl": "https://bitmovin-a.akamaihd.net/content/art-of-motion_drm/mpds/11331.mpd",
"streamType": "dash",
"streamDrmType": "widevine",
"streamDrmLicenseUrl": "https://widevine-proxy.appspot.com/proxy"
},
"suiteId": "6f74025c-1ff1-4d2e-af9c-2d95f3e581af",
"createdAt": "2025-04-28T13:17:31.000Z",
"updatedAt": "2025-04-28T13:17:31.000Z"
}
},
"requestId": "3806776b-2435-11f0-8d43-6a4dd36112b1",
"status": "SUCCESS"
}
Get streams
GET v1/player/testing/streams?offset=0&limit=30
- returns Stream
resources.
Delete stream
DELETE v1/player/testing/streams/<streamId>
Target
(test environment) resource and API
Target
(test environment) resource and APITarget
(test environment) resource
Target
(test environment) resource{
"id": "7c0133d3-fe8d-4662-9aa4-5b445013354b",
"name": "Chrome on macOS",
"capabilities": [
"DRM: Widevine"
],
"deviceType": "desktop"
}
Get targets (test environments)
GET v1/player/testing/targets?offset=0&limit=1000
- returns a Target
resource.
Response example
{
"data": {
"result": {
"totalCount": 1,
"offset": 0,
"items": [
{
"id": "7c0133d3-fe8d-4662-9aa4-5b445013354b",
"name": "Chrome on macOS",
"capabilities": [
"DRM: Widevine"
],
"deviceType": "desktop"
}
]
}
},
"requestId": "4cbfeffd-2431-11f0-a154-0a645591883e",
"status": "SUCCESS"
}
StreamTarget
target (test environment) to stream link resource and API
StreamTarget
target (test environment) to stream link resource and APIStreamTarget
resource
StreamTarget
resource StreamTarget
represents a link between Stream ←→ Target (test environment).
{
"id": "b8e48a38-ce1e-4fad-8914-57693dc2d77d",
"streamId": "846858ee-c215-4199-ad65-7675ce51f370",
"status": "invalid",
"statusValidationError": "Error: The provided DRM license URL cannot be accessed. Please make sure that the URL is valid, accessible from the internet, points to a video manifest, and allows cross-origin requests. If you use geoblocking or other means of access control, please make sure to allow access from Stream Lab IP addresses (contact support for details).",
"targetId": "7c0133d3-fe8d-4662-9aa4-5b445013354b",
"createdAt": "2025-04-28T13:17:31.000Z",
"updatedAt": "2025-04-28T13:19:00.000Z",
"automaticTestEnabled": false
}
Required creational POST body attributes:
targetId
status
-validating
,ready
,invalid
, ortesting
Note: ThestreamId
does not need to be provided in the request body, as it is inferred from the URL.
Optional POST body creational attributes:
automaticTestEnabled
- whether to test the stream on regular basis (during weekends)
Create target (test environments) to stream link (StreamTarget
)
StreamTarget
) POST v1/player/testing/streams/<streamId>/targets
- returns a StreamTarget
resource.
Body example
{
"targetId": "7c0133d3-fe8d-4662-9aa4-5b445013354b",
"automaticTestEnabled": false
}
Response example
{
"data": {
"result": {
"id": "b8e48a38-ce1e-4fad-8914-57693dc2d77d",
"streamId": "846858ee-c215-4199-ad65-7675ce51f370",
"status": "validating",
"targetId": "7c0133d3-fe8d-4662-9aa4-5b445013354b",
"createdAt": "2025-04-28T13:17:31.888Z",
"updatedAt": "2025-04-28T13:17:31.888Z",
"automaticTestEnabled": false
}
},
"requestId": "242e552a-2433-11f0-b103-c284ac960442",
"status": "SUCCESS"
}
Patch target (test environment) to stream link (StreamTarget
)
StreamTarget
) PATCH v1/player/testing/streams/<streamId>/targets/<streamTargetId>
- returns a Stream
resource.
Accepts the same properties as the create endpoint. All properties are optional. Only new property values will be applied. If the targetId
is changed, it will trigger re-validation.
Get target (test environment) to stream links (StreamTarget
s)
StreamTarget
s) GET v1/player/testing/streams/<streamId>/targets?offset=0&limit=1000
- returns StreamTarget
resources.
Response example
{
"data": {
"result": {
"totalCount": 1,
"offset": 0,
"items": [
{
"id": "b8e48a38-ce1e-4fad-8914-57693dc2d77d",
"streamId": "846858ee-c215-4199-ad65-7675ce51f370",
"status": "invalid",
"statusValidationError": "Error: The provided DRM license URL cannot be accessed. Please make sure that the URL is valid, accessible from the internet, points to a video manifest, and allows cross-origin requests. If you use geoblocking or other means of access control, please make sure to allow access from Stream Lab IP addresses (contact support for details).",
"targetId": "7c0133d3-fe8d-4662-9aa4-5b445013354b",
"createdAt": "2025-04-28T13:17:31.000Z",
"updatedAt": "2025-04-28T13:19:00.000Z",
"automaticTestEnabled": false
}
]
}
},
"requestId": "38256105-2435-11f0-bcc6-0a645591883e",
"status": "SUCCESS"
}
Delete target (test environment) to stream link (StreamTarget
)
StreamTarget
) DELETE v1/player/testing/streams/<streamId>/targets/<streamTargetId>
Job
resource and API
Job
resource and APIJob
resource
Job
resource Job
represents a test execution in a test environment.
{
"id": "b849c46f-6918-4be8-b503-ab54a5d03dac",
"streamTargetId": "fb11bd36-a6f5-4750-8701-a7e747919a27",
"status": "notified",
"type": "manual",
"createdAt": "2025-04-29T13:00:25.000Z",
"updatedAt": "2025-04-29T13:02:00.000Z",
"summary": {
"testResultCounts": {
"success": 11,
"failure": 0,
"skipped": 4
},
"os": "macos",
"osVersion": "15.3.0",
"browser": "chrome",
"browserVersion": "135.0.0",
"deviceType": "desktop",
"location": "eu:klu:b2",
"playerVersion": "8.207.0",
"updatedAt": "2025-04-29T13:01:43.000Z"
}
}
Details about properties:
type
-manual
orautomatic
status
-created
,executing
,finished
,aborted
,failed
, ornotified
- There can be only 1 job in
created
orexecuting
status, which means there can only be 1 job scheduled for execution or executing in a test environment for a stream
- There can be only 1 job in
Required creational POST body attributes:
- None. All required attributes are inferred from the URL.
Optional POST body creational attributes:
- None.
Jobs created via API are considered a manual (on demand) test execution.
Create job
POST v1/player/testing/streams/<streamId>/targets/<streamTargetId>/jobs
A job (manual test execution request) can be created immediately after a StreamTarget
resource (link between stream and test environment) is created. However, it is recommended to wait until the StreamTarget
is validated (until the status
is ready
) to not waste credits in case of misconfiguration (e.g. due to unreachable DRM server). Each manual job creation spends 1 monthlyTestExecutions
.
Get jobs
GET v1/player/testing/streams/<streamId>/targets/<streamTargetId>/jobs?offset=0&limit=1000
Response example
{
"data": {
"result": {
"totalCount": 1,
"offset": 0,
"items": [
{
"id": "b849c46f-6918-4be8-b503-ab54a5d03dac",
"streamTargetId": "fb11bd36-a6f5-4750-8701-a7e747919a27",
"status": "notified",
"type": "manual",
"createdAt": "2025-04-29T13:00:25.000Z",
"updatedAt": "2025-04-29T13:02:00.000Z",
"summary": {
"testResultCounts": {
"success": 11,
"failure": 0,
"skipped": 4
},
"os": "macos",
"osVersion": "15.3.0",
"browser": "chrome",
"browserVersion": "135.0.0",
"deviceType": "desktop",
"location": "eu:klu:b2",
"playerVersion": "8.207.0",
"updatedAt": "2025-04-29T13:01:43.000Z"
}
}
]
}
},
"requestId": "278bf0cc-24fa-11f0-8360-6a4dd36112b1",
"status": "SUCCESS"
}
TestResult
resource and API
TestResult
resource and APITestResult
resource
TestResult
resource{
"result": "skipped",
"reason": "No LA URL configured (unprotected stream)",
"durationMs": 0,
"collection": "Stream validation",
"id": "18357240-06b1-4a60-a4d4-b38a3065314a",
"suiteId": "6f74025c-1ff1-4d2e-af9c-2d95f3e581af",
"name": "DRM license availability",
"description": "Check if the DRM license acquisition URL is reachable by Stream Lab's fleet of test devices.",
"failureDescription": "The DRM LA URL is unreachable from our test devices (e.g. due to geoblocking)."
}
Details about properties:
result
-success
,failure
, orskipped
reason
- the reason why the tests was skipped when theresult
isskipped
failureDescription
- always present, contains a description of the failure when theresult
isfailure
Get test results
GET v1/player/testing/jobs/<jobId>/testresults?offset=0&limit=1000
Response example
{
"data": {
"result": {
"totalCount": 1,
"offset": 0,
"items": [
{
"result": "success",
"reason": null,
"durationMs": 5,
"collection": "Stream validation",
"id": "99e098b8-2000-4907-97cf-9711f6cc5eb9",
"suiteId": "6f74025c-1ff1-4d2e-af9c-2d95f3e581af",
"name": "Validate stream config",
"description": "Validates correctness of the stream configuration.",
"failureDescription": "The stream configuration is unsupported or the stream is not supported on the selected target."
}
]
}
},
"requestId": "1d79d4df-3547-11f0-a4db-6a4dd36112b1",
"status": "SUCCESS"
}
Limit
resource and API
Limit
resource and APILimit
resource
Limit
resource{
"activeStreamTargetsLimit": 200,
"streamUrlLimit": 1024,
"monthlyTestExecutionsLimit": 200,
"monthlyTestExecutions": 0,
"activeStreamTargets": 0
}
activeStreamTargets
count of current stream ←→ test environment links that have testing on regular basis enabled (automaticTestEnabled: true
)activeStreamTargetsLimit
max limit for theactiveStreamTargets
monthlyTestExecutions
count of manual (on demand) test executionmonthlyTestExecutionsLimit
max limit for the above
Get limits
GET v1/player/testing/limits
- returns a Limit
resource.
Response example
{
"data": {
"result": {
"activeStreamTargetsLimit": 200,
"streamUrlLimit": 1024,
"monthlyTestExecutionsLimit": 200,
"monthlyTestExecutions": 0,
"activeStreamTargets": 0
}
},
"requestId": "61239fc6-24e8-11f0-b974-e27f83dd5332",
"status": "SUCCESS"
}
VpnLocation
resource and API
VpnLocation
resource and APIVpnLocation
resource
VpnLocation
resourceCan I test geo-restricted streams?
{
"id": "cfea044e-0bb3-442a-b923-607f840c88d9",
"name": "Australia - Sydney"
}
Get VPN locations
GET v1/player/testing/vpn-locations?offset=0&limit=1000
- returns a VpnLocation
resource.
Response example
{
"data": {
"result": {
"totalCount": 1,
"offset": 0,
"items": [
{
"id": "4ff48470-3c45-416c-8013-08360ce320ea",
"name": "Albania"
}
]
}
},
"requestId": "aa6034f6-2432-11f0-91a6-e27f83dd5332",
"status": "SUCCESS"
}
Diagram

Quick start
Only StreamLab API is exposed to users and required to create streams, link targets (test environments) to them and run tests.
Steps:
- Create streams
POST v1/player/testing/streams
- Get the list of available targets (test environment)
GET v1/player/testing/targets
- Link targets (test environments) to streams for testing
POST v1/player/testing/streams/<streamId>/targets
- It creates stream ←→ target (test environment) links (
StreamTarget
resources) - Each stream ←→ target (test environment) link is validated right after creation
- Validation is performed automatically. Usually it finishes in a few minutes but it can take longer if the related test environments are busy or unavailable due to a physical problem.
- After validation is completed the
StreamTarget
'sstatus
will either beready
orinvalid
with correspondingstatusValidationError
- It creates stream ←→ target (test environment) links (
- All valid streams that have
automaticTestEnabled: true
will automatically be tested on a regular basis during weekends - To run stream tests on demand (manually), create a job resource
POST v1/player/testing/streams/<streamId>/targets/<streamTargetId>/jobs
for each target (test environment) linked to the stream - Use
GET v1/player/testing/jobs/<jobId>/testresults
to get test results
Updated about 21 hours ago