Stream Lab API
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.nameconfig.streamType-hlsordashconfig.streamDrmType-widevine,playready, ornoneconfig.streamUrlconfig.version-1config.streamDrmLicenseUrl- required only ifstreamDrmTypeis notnone
Optional POST body creational attributes:
config.drmHeadersvpnLocationId
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:
targetIdstatus-validating,ready,invalid, ortesting
Note: ThestreamIddoes 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 (StreamTargets)
StreamTargets)  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-manualorautomaticstatus-created,executing,finished,aborted,failed, ornotified- There can be only 1 job in 
createdorexecutingstatus, 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, orskippedreason- the reason why the tests was skipped when theresultisskippedfailureDescription- always present, contains a description of the failure when theresultisfailure
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
}
activeStreamTargetscount of current stream ←→ test environment links that have testing on regular basis enabled (automaticTestEnabled: true)activeStreamTargetsLimitmax limit for theactiveStreamTargets
monthlyTestExecutionscount of manual (on demand) test executionmonthlyTestExecutionsLimitmax 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 (
StreamTargetresources) - 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'sstatuswill either bereadyorinvalidwith correspondingstatusValidationError 
 - It creates stream ←→ target (test environment) links (
 - All valid streams that have 
automaticTestEnabled: truewill 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>/jobsfor each target (test environment) linked to the stream - Use 
GET v1/player/testing/jobs/<jobId>/testresultsto get test results 
Updated 4 months ago