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 second
  • POST: 5 requests per second
  • PATCH: 5 requests per second
  • DELETE: 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

{
  "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 stream
  • config.drmHeaders - custom headers to pass to the DRM server

Required creational POST body attributes:

  • config.name
  • config.streamType - hls or dash
  • config.streamDrmType - widevine, playready, or none
  • config.streamUrl
  • config.version - 1
  • config.streamDrmLicenseUrl - required only if streamDrmType is not none

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

What is a test environment?

{
  "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 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, or testing
    Note: The streamId 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)

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)

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)

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)

DELETE v1/player/testing/streams/<streamId>/targets/<streamTargetId>

Job resource and API

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 or automatic
  • status - created, executing, finished, aborted, failed, or notified
    • There can be only 1 job in created or executing status, which means there can only be 1 job scheduled for execution or executing in a test environment for a stream

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

{
  "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, or skipped
  • reason - the reason why the tests was skipped when the result is skipped
  • failureDescription - always present, contains a description of the failure when the result is failure

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

{
  "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 the activeStreamTargets
  • monthlyTestExecutions count of manual (on demand) test execution
    • monthlyTestExecutionsLimit 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

Can 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

Diagram.png

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's status will either be ready or invalid with corresponding statusValidationError
  • 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