Video service#

The video service manages videos and video metadata.

OpenAPI file: VideoService.json

Endpoints#

Get#

GET /video/v1/videos/{videoRid}

Deprecated: Legacy Video-entity API. Videos are now channels on datasets; list a channel’s files with listVideoChannelDatasetFiles and read dataset metadata from CatalogService.

Returns video metadata associated with a video rid.

Path parameters

videoRid string (RID) required

​

Response

rid string (RID)

​

title string

​

description string

​

labels array of string

​

properties map of PropertyName to string

​

createdBy string (RID)

​

createdAt string (date-time)

​

isArchived boolean

​

originMetadata VideoOriginMetadata deprecated

Deprecated: deprecated in favor of per-file VideoFileOriginMetadata. Will be removed after April 15th.

Fields of VideoOriginMetadata
videoSources array of Handle deprecated

Deprecated: deprecated in favor of per-file VideoFileOriginMetadata. Will be removed after April 15th.

Set type to "s3".

s3 string

​

timestampManifest VideoTimestampManifest deprecated

Deprecated: deprecated in favor of per-file VideoFileOriginMetadata. Will be removed after April 15th.

Set type to "mcap".

mcap McapTimestampManifest

​

Fields of McapTimestampManifest
mcapChannelLocator McapChannelLocator

​

Set type to "topic".

topic string

​

Set type to "id".

id integer

​

Set type to "s3paths".

s3paths array of string

​

Set type to "noManifest".

noManifest NoTimestampManifest

​

Fields of NoTimestampManifest
startingTimestamp Timestamp

Specifies the original starting timestamp of the video.

Fields of Timestamp
seconds integer (int64)

​

nanos integer (int64)

​

scaleParameter ScaleParameter

A field that specifies that the frame rate of the video does not match the frame rate of the camera | i.e. a slowed down or sped up video. Can specify either the camera frame rate or the absolute end time.

Set type to "trueFrameRate".

trueFrameRate number

​

Set type to "endingTimestamp".

endingTimestamp Timestamp

​

Set type to "scaleFactor".

scaleFactor number

the scale factor can be used to calculate whether media duration differs from a video’s | real duration, and if so, the true frame rate of the camera. The video time will thus be scaled | by the ratio of the real duration to media duration, or media frame rate to true frame rate.

allSegmentsMetadata VideoAllSegmentsMetadata

​

Fields of VideoAllSegmentsMetadata
rid string (RID)

​

numFrames integer

​

numSegments integer

​

scaleFactor number

deprecated, in favor of per-file VideoFileSegmentsMetadata scaleFactor. Will be removed after April 15th.

minAbsoluteTimestamp Timestamp

​

maxAbsoluteTimestamp Timestamp

the timestamp corresponding to absolute starting timestamp plus absolute duration of the video.

mediaDurationSeconds number

​

mediaFrameRate number

The average media frame rate (FPS) of the video calculated as total frames / duration in seconds.

minTimestamp Timestamp

deprecated. Will be removed after April 15th.

maxTimestamp Timestamp

deprecated. Will be removed after April 15th.

durationSeconds number

deprecated. Will be removed after April 15th.

frameRate number

deprecated. Will be removed after April 15th.

Request

curl "https://api.gov.nominal.io/api/video/v1/videos/<video rid>" \
  -H "Authorization: Bearer <api key>"
import requests

response = requests.get(
    "https://api.gov.nominal.io/api/video/v1/videos/<video rid>",
    headers={"Authorization": "Bearer <api key>"},
)
response.raise_for_status()
print(response.json())
import httpx

response = httpx.get(
    "https://api.gov.nominal.io/api/video/v1/videos/<video rid>",
    headers={"Authorization": "Bearer <api key>"},
)
response.raise_for_status()
print(response.json())
import asyncio

import aiohttp


async def main() -> None:
    async with aiohttp.ClientSession() as session:
        async with session.get(
            "https://api.gov.nominal.io/api/video/v1/videos/<video rid>",
            headers={"Authorization": "Bearer <api key>"},
        ) as response:
            response.raise_for_status()
            print(await response.json())


asyncio.run(main())

Response: 200

{
  "rid": "<video rid>",
  "title": "<title>",
  "description": "<description>",
  "labels": [
    "<label>"
  ],
  "properties": {
    "<key>": "<property value>"
  },
  "createdBy": "<created by>",
  "createdAt": "2026-01-01T00:00:00Z",
  "isArchived": true,
  "originMetadata": {
    "videoSources": [
      {
        "type": "s3",
        "s3": "<s3 path>"
      }
    ],
    "timestampManifest": {
      "type": "mcap",
      "mcap": {
        "mcapChannelLocator": {
          "type": "topic",
          "topic": "<mcap channel topic>"
        }
      }
    }
  },
  "allSegmentsMetadata": {
    "rid": "<video rid>",
    "numFrames": 1,
    "numSegments": 1,
    "scaleFactor": 1,
    "minAbsoluteTimestamp": {
      "seconds": 1,
      "nanos": 1
    },
    "maxAbsoluteTimestamp": {
      "seconds": 1,
      "nanos": 1
    },
    "mediaDurationSeconds": 1,
    "mediaFrameRate": 1,
    "minTimestamp": {
      "seconds": 1,
      "nanos": 1
    },
    "maxTimestamp": {
      "seconds": 1,
      "nanos": 1
    },
    "durationSeconds": 1,
    "frameRate": 1
  }
}

Update metadata#

PUT /video/v1/videos/{videoRid}

Deprecated: Legacy Video-entity API. Videos are now channels on datasets; update dataset metadata with CatalogService#updateDatasetMetadata and per-file titles with batchUpdateVideoChannelDatasetFiles.

Updates the metadata for a video associated with the given video rid.

Path parameters

videoRid string (RID) required

​

Body

title string

​

description string

​

labels array of string

​

properties map of PropertyName to string

​

startingTimestamp Timestamp

​

Fields of Timestamp
seconds integer (int64) required

​

nanos integer (int64) required

​

scaleParameter ScaleParameter deprecated

Deprecated: deprecated in favor of updating scaleParameter per-file. Will fail if set on a video with multiple files. Will be removed after April 15th.

Set type to "trueFrameRate".

trueFrameRate number

​

Set type to "endingTimestamp".

endingTimestamp Timestamp

​

Set type to "scaleFactor".

scaleFactor number

the scale factor can be used to calculate whether media duration differs from a video’s | real duration, and if so, the true frame rate of the camera. The video time will thus be scaled | by the ratio of the real duration to media duration, or media frame rate to true frame rate.

Response

rid string (RID)

​

title string

​

description string

​

labels array of string

​

properties map of PropertyName to string

​

createdBy string (RID)

​

createdAt string (date-time)

​

isArchived boolean

​

originMetadata VideoOriginMetadata deprecated

Deprecated: deprecated in favor of per-file VideoFileOriginMetadata. Will be removed after April 15th.

Fields of VideoOriginMetadata
videoSources array of Handle deprecated

Deprecated: deprecated in favor of per-file VideoFileOriginMetadata. Will be removed after April 15th.

Set type to "s3".

s3 string

​

timestampManifest VideoTimestampManifest deprecated

Deprecated: deprecated in favor of per-file VideoFileOriginMetadata. Will be removed after April 15th.

Set type to "mcap".

mcap McapTimestampManifest

​

Fields of McapTimestampManifest
mcapChannelLocator McapChannelLocator

​

Set type to "topic".

topic string

​

Set type to "id".

id integer

​

Set type to "s3paths".

s3paths array of string

​

Set type to "noManifest".

noManifest NoTimestampManifest

​

Fields of NoTimestampManifest
startingTimestamp Timestamp

Specifies the original starting timestamp of the video.

Fields of Timestamp
seconds integer (int64)

​

nanos integer (int64)

​

scaleParameter ScaleParameter

A field that specifies that the frame rate of the video does not match the frame rate of the camera | i.e. a slowed down or sped up video. Can specify either the camera frame rate or the absolute end time.

Set type to "trueFrameRate".

trueFrameRate number

​

Set type to "endingTimestamp".

endingTimestamp Timestamp

​

Set type to "scaleFactor".

scaleFactor number

the scale factor can be used to calculate whether media duration differs from a video’s | real duration, and if so, the true frame rate of the camera. The video time will thus be scaled | by the ratio of the real duration to media duration, or media frame rate to true frame rate.

allSegmentsMetadata VideoAllSegmentsMetadata

​

Fields of VideoAllSegmentsMetadata
rid string (RID)

​

numFrames integer

​

numSegments integer

​

scaleFactor number

deprecated, in favor of per-file VideoFileSegmentsMetadata scaleFactor. Will be removed after April 15th.

minAbsoluteTimestamp Timestamp

​

maxAbsoluteTimestamp Timestamp

the timestamp corresponding to absolute starting timestamp plus absolute duration of the video.

mediaDurationSeconds number

​

mediaFrameRate number

The average media frame rate (FPS) of the video calculated as total frames / duration in seconds.

minTimestamp Timestamp

deprecated. Will be removed after April 15th.

maxTimestamp Timestamp

deprecated. Will be removed after April 15th.

durationSeconds number

deprecated. Will be removed after April 15th.

frameRate number

deprecated. Will be removed after April 15th.

Request

curl -X PUT "https://api.gov.nominal.io/api/video/v1/videos/<video rid>" \
  -H "Authorization: Bearer <api key>" \
  -H "Content-Type: application/json" \
  --data '{
  "title": "<title>",
  "description": "<description>",
  "labels": [
    "<label>"
  ],
  "properties": {
    "<key>": "<property value>"
  },
  "startingTimestamp": {
    "seconds": 1,
    "nanos": 1
  },
  "scaleParameter": {
    "type": "trueFrameRate",
    "trueFrameRate": 1
  }
}'
import requests

response = requests.put(
    "https://api.gov.nominal.io/api/video/v1/videos/<video rid>",
    headers={"Authorization": "Bearer <api key>"},
    json={
        "title": "<title>",
        "description": "<description>",
        "labels": ["<label>"],
        "properties": {"<key>": "<property value>"},
        "startingTimestamp": {"seconds": 1, "nanos": 1},
        "scaleParameter": {"type": "trueFrameRate", "trueFrameRate": 1},
    },
)
response.raise_for_status()
print(response.json())
import httpx

response = httpx.put(
    "https://api.gov.nominal.io/api/video/v1/videos/<video rid>",
    headers={"Authorization": "Bearer <api key>"},
    json={
        "title": "<title>",
        "description": "<description>",
        "labels": ["<label>"],
        "properties": {"<key>": "<property value>"},
        "startingTimestamp": {"seconds": 1, "nanos": 1},
        "scaleParameter": {"type": "trueFrameRate", "trueFrameRate": 1},
    },
)
response.raise_for_status()
print(response.json())
import asyncio

import aiohttp


async def main() -> None:
    async with aiohttp.ClientSession() as session:
        async with session.put(
            "https://api.gov.nominal.io/api/video/v1/videos/<video rid>",
            headers={"Authorization": "Bearer <api key>"},
            json={
                "title": "<title>",
                "description": "<description>",
                "labels": ["<label>"],
                "properties": {"<key>": "<property value>"},
                "startingTimestamp": {"seconds": 1, "nanos": 1},
                "scaleParameter": {"type": "trueFrameRate", "trueFrameRate": 1},
            },
        ) as response:
            response.raise_for_status()
            print(await response.json())


asyncio.run(main())

Response: 200

{
  "rid": "<video rid>",
  "title": "<title>",
  "description": "<description>",
  "labels": [
    "<label>"
  ],
  "properties": {
    "<key>": "<property value>"
  },
  "createdBy": "<created by>",
  "createdAt": "2026-01-01T00:00:00Z",
  "isArchived": true,
  "originMetadata": {
    "videoSources": [
      {
        "type": "s3",
        "s3": "<s3 path>"
      }
    ],
    "timestampManifest": {
      "type": "mcap",
      "mcap": {
        "mcapChannelLocator": {
          "type": "topic",
          "topic": "<mcap channel topic>"
        }
      }
    }
  },
  "allSegmentsMetadata": {
    "rid": "<video rid>",
    "numFrames": 1,
    "numSegments": 1,
    "scaleFactor": 1,
    "minAbsoluteTimestamp": {
      "seconds": 1,
      "nanos": 1
    },
    "maxAbsoluteTimestamp": {
      "seconds": 1,
      "nanos": 1
    },
    "mediaDurationSeconds": 1,
    "mediaFrameRate": 1,
    "minTimestamp": {
      "seconds": 1,
      "nanos": 1
    },
    "maxTimestamp": {
      "seconds": 1,
      "nanos": 1
    },
    "durationSeconds": 1,
    "frameRate": 1
  }
}

Batch get#

POST /video/v1/videos/batchGet

Deprecated: Legacy Video-entity API. Videos are now channels on datasets; list a channel’s files with listVideoChannelDatasetFiles and read dataset metadata from CatalogService.

Returns video metadata about each video given a set of video rids.

Body

videoRids array of string (RID)

​

Response

responses array of Video

​

Fields of Video
rid string (RID)

​

title string

​

description string

​

labels array of string

​

properties map of PropertyName to string

​

createdBy string (RID)

​

createdAt string (date-time)

​

isArchived boolean

​

originMetadata VideoOriginMetadata deprecated

Deprecated: deprecated in favor of per-file VideoFileOriginMetadata. Will be removed after April 15th.

Fields of VideoOriginMetadata
videoSources array of Handle deprecated

Deprecated: deprecated in favor of per-file VideoFileOriginMetadata. Will be removed after April 15th.

Set type to "s3".

s3 string

​

timestampManifest VideoTimestampManifest deprecated

Deprecated: deprecated in favor of per-file VideoFileOriginMetadata. Will be removed after April 15th.

Set type to "mcap".

mcap McapTimestampManifest

​

Fields of McapTimestampManifest
mcapChannelLocator McapChannelLocator

​

Set type to "topic".

topic string

​

Set type to "id".

id integer

​

Set type to "s3paths".

s3paths array of string

​

Set type to "noManifest".

noManifest NoTimestampManifest

​

Fields of NoTimestampManifest
startingTimestamp Timestamp

Specifies the original starting timestamp of the video.

Fields of Timestamp
seconds integer (int64)

​

nanos integer (int64)

​

scaleParameter ScaleParameter

A field that specifies that the frame rate of the video does not match the frame rate of the camera | i.e. a slowed down or sped up video. Can specify either the camera frame rate or the absolute end time.

Set type to "trueFrameRate".

trueFrameRate number

​

Set type to "endingTimestamp".

endingTimestamp Timestamp

​

Set type to "scaleFactor".

scaleFactor number

the scale factor can be used to calculate whether media duration differs from a video’s | real duration, and if so, the true frame rate of the camera. The video time will thus be scaled | by the ratio of the real duration to media duration, or media frame rate to true frame rate.

allSegmentsMetadata VideoAllSegmentsMetadata

​

Fields of VideoAllSegmentsMetadata
rid string (RID)

​

numFrames integer

​

numSegments integer

​

scaleFactor number

deprecated, in favor of per-file VideoFileSegmentsMetadata scaleFactor. Will be removed after April 15th.

minAbsoluteTimestamp Timestamp

​

maxAbsoluteTimestamp Timestamp

the timestamp corresponding to absolute starting timestamp plus absolute duration of the video.

mediaDurationSeconds number

​

mediaFrameRate number

The average media frame rate (FPS) of the video calculated as total frames / duration in seconds.

minTimestamp Timestamp

deprecated. Will be removed after April 15th.

maxTimestamp Timestamp

deprecated. Will be removed after April 15th.

durationSeconds number

deprecated. Will be removed after April 15th.

frameRate number

deprecated. Will be removed after April 15th.

Request

curl -X POST "https://api.gov.nominal.io/api/video/v1/videos/batchGet" \
  -H "Authorization: Bearer <api key>" \
  -H "Content-Type: application/json" \
  --data '{
  "videoRids": [
    "<video rid>"
  ]
}'
import requests

response = requests.post(
    "https://api.gov.nominal.io/api/video/v1/videos/batchGet",
    headers={"Authorization": "Bearer <api key>"},
    json={"videoRids": ["<video rid>"]},
)
response.raise_for_status()
print(response.json())
import httpx

response = httpx.post(
    "https://api.gov.nominal.io/api/video/v1/videos/batchGet",
    headers={"Authorization": "Bearer <api key>"},
    json={"videoRids": ["<video rid>"]},
)
response.raise_for_status()
print(response.json())
import asyncio

import aiohttp


async def main() -> None:
    async with aiohttp.ClientSession() as session:
        async with session.post(
            "https://api.gov.nominal.io/api/video/v1/videos/batchGet",
            headers={"Authorization": "Bearer <api key>"},
            json={"videoRids": ["<video rid>"]},
        ) as response:
            response.raise_for_status()
            print(await response.json())


asyncio.run(main())

Response: 200

{
  "responses": [
    {
      "rid": "<video rid>",
      "title": "<title>",
      "description": "<description>",
      "labels": [
        "<label>"
      ],
      "properties": {
        "<key>": "<property value>"
      },
      "createdBy": "<created by>",
      "createdAt": "2026-01-01T00:00:00Z",
      "isArchived": true,
      "originMetadata": {
        "videoSources": [
          {
            "type": "s3",
            "s3": "<s3 path>"
          }
        ],
        "timestampManifest": {
          "type": "mcap",
          "mcap": {
            "mcapChannelLocator": {
              "type": "topic",
              "topic": "<mcap channel topic>"
            }
          }
        }
      },
      "allSegmentsMetadata": {
        "rid": "<video rid>",
        "numFrames": 1,
        "numSegments": 1,
        "scaleFactor": 1,
        "minAbsoluteTimestamp": {
          "seconds": 1,
          "nanos": 1
        },
        "maxAbsoluteTimestamp": {
          "seconds": 1,
          "nanos": 1
        },
        "mediaDurationSeconds": 1,
        "mediaFrameRate": 1,
        "minTimestamp": {
          "seconds": 1,
          "nanos": 1
        },
        "maxTimestamp": {
          "seconds": 1,
          "nanos": 1
        },
        "durationSeconds": 1,
        "frameRate": 1
      }
    }
  ]
}

Create#

POST /video/v1/videos

Deprecated: Legacy Video-entity API. Videos are now channels on datasets; ingest with videoV2 options targeting a dataset channel instead of creating a Video.

Creates and persists a video entity with the given metadata.

Body

title string required

​

description string

​

labels array of string

​

properties map of PropertyName to string

​

originMetadata VideoOriginMetadata deprecated

Deprecated: deprecated in favor of per-file VideoFileOriginMetadata. Will be removed after April 15th.

Fields of VideoOriginMetadata
videoSources array of Handle deprecated

Deprecated: deprecated in favor of per-file VideoFileOriginMetadata. Will be removed after April 15th.

Set type to "s3".

s3 string

​

timestampManifest VideoTimestampManifest required deprecated

Deprecated: deprecated in favor of per-file VideoFileOriginMetadata. Will be removed after April 15th.

Set type to "mcap".

mcap McapTimestampManifest

​

Fields of McapTimestampManifest
mcapChannelLocator McapChannelLocator required

​

Set type to "topic".

topic string

​

Set type to "id".

id integer

​

Set type to "s3paths".

s3paths array of string

​

Set type to "noManifest".

noManifest NoTimestampManifest

​

Fields of NoTimestampManifest
startingTimestamp Timestamp required

Specifies the original starting timestamp of the video.

Fields of Timestamp
seconds integer (int64) required

​

nanos integer (int64) required

​

scaleParameter ScaleParameter

A field that specifies that the frame rate of the video does not match the frame rate of the camera | i.e. a slowed down or sped up video. Can specify either the camera frame rate or the absolute end time.

Set type to "trueFrameRate".

trueFrameRate number

​

Set type to "endingTimestamp".

endingTimestamp Timestamp

​

Set type to "scaleFactor".

scaleFactor number

the scale factor can be used to calculate whether media duration differs from a video’s | real duration, and if so, the true frame rate of the camera. The video time will thus be scaled | by the ratio of the real duration to media duration, or media frame rate to true frame rate.

workspace string (RID)

The workspace in which to create the video. If not provided, the video will be created in the default workspace for the user’s organization, if the default workspace for the organization is configured.

markingRids array of string (RID)

The markings to apply to the created video. If not provided, the video will be visible to all users in the same workspace.

Response

rid string (RID)

​

title string

​

description string

​

labels array of string

​

properties map of PropertyName to string

​

createdBy string (RID)

​

createdAt string (date-time)

​

isArchived boolean

​

originMetadata VideoOriginMetadata deprecated

Deprecated: deprecated in favor of per-file VideoFileOriginMetadata. Will be removed after April 15th.

Fields of VideoOriginMetadata
videoSources array of Handle deprecated

Deprecated: deprecated in favor of per-file VideoFileOriginMetadata. Will be removed after April 15th.

Set type to "s3".

s3 string

​

timestampManifest VideoTimestampManifest deprecated

Deprecated: deprecated in favor of per-file VideoFileOriginMetadata. Will be removed after April 15th.

Set type to "mcap".

mcap McapTimestampManifest

​

Fields of McapTimestampManifest
mcapChannelLocator McapChannelLocator

​

Set type to "topic".

topic string

​

Set type to "id".

id integer

​

Set type to "s3paths".

s3paths array of string

​

Set type to "noManifest".

noManifest NoTimestampManifest

​

Fields of NoTimestampManifest
startingTimestamp Timestamp

Specifies the original starting timestamp of the video.

Fields of Timestamp
seconds integer (int64)

​

nanos integer (int64)

​

scaleParameter ScaleParameter

A field that specifies that the frame rate of the video does not match the frame rate of the camera | i.e. a slowed down or sped up video. Can specify either the camera frame rate or the absolute end time.

Set type to "trueFrameRate".

trueFrameRate number

​

Set type to "endingTimestamp".

endingTimestamp Timestamp

​

Set type to "scaleFactor".

scaleFactor number

the scale factor can be used to calculate whether media duration differs from a video’s | real duration, and if so, the true frame rate of the camera. The video time will thus be scaled | by the ratio of the real duration to media duration, or media frame rate to true frame rate.

allSegmentsMetadata VideoAllSegmentsMetadata

​

Fields of VideoAllSegmentsMetadata
rid string (RID)

​

numFrames integer

​

numSegments integer

​

scaleFactor number

deprecated, in favor of per-file VideoFileSegmentsMetadata scaleFactor. Will be removed after April 15th.

minAbsoluteTimestamp Timestamp

​

maxAbsoluteTimestamp Timestamp

the timestamp corresponding to absolute starting timestamp plus absolute duration of the video.

mediaDurationSeconds number

​

mediaFrameRate number

The average media frame rate (FPS) of the video calculated as total frames / duration in seconds.

minTimestamp Timestamp

deprecated. Will be removed after April 15th.

maxTimestamp Timestamp

deprecated. Will be removed after April 15th.

durationSeconds number

deprecated. Will be removed after April 15th.

frameRate number

deprecated. Will be removed after April 15th.

Request

curl -X POST "https://api.gov.nominal.io/api/video/v1/videos" \
  -H "Authorization: Bearer <api key>" \
  -H "Content-Type: application/json" \
  --data '{
  "title": "<title>"
}'
import requests

response = requests.post(
    "https://api.gov.nominal.io/api/video/v1/videos",
    headers={"Authorization": "Bearer <api key>"},
    json={"title": "<title>"},
)
response.raise_for_status()
print(response.json())
import httpx

response = httpx.post(
    "https://api.gov.nominal.io/api/video/v1/videos",
    headers={"Authorization": "Bearer <api key>"},
    json={"title": "<title>"},
)
response.raise_for_status()
print(response.json())
import asyncio

import aiohttp


async def main() -> None:
    async with aiohttp.ClientSession() as session:
        async with session.post(
            "https://api.gov.nominal.io/api/video/v1/videos",
            headers={"Authorization": "Bearer <api key>"},
            json={"title": "<title>"},
        ) as response:
            response.raise_for_status()
            print(await response.json())


asyncio.run(main())

Response: 200

{
  "rid": "<video rid>",
  "title": "<title>",
  "description": "<description>",
  "labels": [
    "<label>"
  ],
  "properties": {
    "<key>": "<property value>"
  },
  "createdBy": "<created by>",
  "createdAt": "2026-01-01T00:00:00Z",
  "isArchived": true,
  "originMetadata": {
    "videoSources": [
      {
        "type": "s3",
        "s3": "<s3 path>"
      }
    ],
    "timestampManifest": {
      "type": "mcap",
      "mcap": {
        "mcapChannelLocator": {
          "type": "topic",
          "topic": "<mcap channel topic>"
        }
      }
    }
  },
  "allSegmentsMetadata": {
    "rid": "<video rid>",
    "numFrames": 1,
    "numSegments": 1,
    "scaleFactor": 1,
    "minAbsoluteTimestamp": {
      "seconds": 1,
      "nanos": 1
    },
    "maxAbsoluteTimestamp": {
      "seconds": 1,
      "nanos": 1
    },
    "mediaDurationSeconds": 1,
    "mediaFrameRate": 1,
    "minTimestamp": {
      "seconds": 1,
      "nanos": 1
    },
    "maxTimestamp": {
      "seconds": 1,
      "nanos": 1
    },
    "durationSeconds": 1,
    "frameRate": 1
  }
}

Get ingest status#

GET /video/v1/videos/{videoRid}/ingest-status

Deprecated: Legacy Video-entity API. Videos are now channels on datasets; ingest status is tracked per file on the Catalog dataset file (CatalogService#getDatasetFile).

Path parameters

videoRid string (RID) required

​

Response

A DetailedIngestStatus union.

Set type to "success".

success SuccessIngestStatus

​

Set type to "error".

error ErrorIngestStatus

​

Fields of ErrorIngestStatus
errors array of IngestError

​

Fields of IngestError
errorType string

​

message string

​

errorInstanceId string

​

Set type to "inProgress".

inProgress number

A number between 0 and 1 representing percentage progress.

Request

curl "https://api.gov.nominal.io/api/video/v1/videos/<video rid>/ingest-status" \
  -H "Authorization: Bearer <api key>"
import requests

response = requests.get(
    "https://api.gov.nominal.io/api/video/v1/videos/<video rid>/ingest-status",
    headers={"Authorization": "Bearer <api key>"},
)
response.raise_for_status()
print(response.json())
import httpx

response = httpx.get(
    "https://api.gov.nominal.io/api/video/v1/videos/<video rid>/ingest-status",
    headers={"Authorization": "Bearer <api key>"},
)
response.raise_for_status()
print(response.json())
import asyncio

import aiohttp


async def main() -> None:
    async with aiohttp.ClientSession() as session:
        async with session.get(
            "https://api.gov.nominal.io/api/video/v1/videos/<video rid>/ingest-status",
            headers={"Authorization": "Bearer <api key>"},
        ) as response:
            response.raise_for_status()
            print(await response.json())


asyncio.run(main())

Response: 200

{
  "type": "success",
  "success": {}
}

Batch get ingest status#

POST /video/v1/videos/batch-get-ingest-status

Deprecated: Legacy Video-entity API. Videos are now channels on datasets; ingest status is tracked per file on the Catalog dataset file (CatalogService#batchGetDatasetFiles).

Body

The body is an array of string (RID).

Response

The body is a map of VideoRid to DetailedIngestStatus.

Set type to "success".

success SuccessIngestStatus

​

Set type to "error".

error ErrorIngestStatus

​

Fields of ErrorIngestStatus
errors array of IngestError

​

Fields of IngestError
errorType string

​

message string

​

errorInstanceId string

​

Set type to "inProgress".

inProgress number

A number between 0 and 1 representing percentage progress.

Request

curl -X POST "https://api.gov.nominal.io/api/video/v1/videos/batch-get-ingest-status" \
  -H "Authorization: Bearer <api key>" \
  -H "Content-Type: application/json" \
  --data '[
  "<video rid>"
]'
import requests

response = requests.post(
    "https://api.gov.nominal.io/api/video/v1/videos/batch-get-ingest-status",
    headers={"Authorization": "Bearer <api key>"},
    json=["<video rid>"],
)
response.raise_for_status()
print(response.json())
import httpx

response = httpx.post(
    "https://api.gov.nominal.io/api/video/v1/videos/batch-get-ingest-status",
    headers={"Authorization": "Bearer <api key>"},
    json=["<video rid>"],
)
response.raise_for_status()
print(response.json())
import asyncio

import aiohttp


async def main() -> None:
    async with aiohttp.ClientSession() as session:
        async with session.post(
            "https://api.gov.nominal.io/api/video/v1/videos/batch-get-ingest-status",
            headers={"Authorization": "Bearer <api key>"},
            json=["<video rid>"],
        ) as response:
            response.raise_for_status()
            print(await response.json())


asyncio.run(main())

Response: 200

{
  "<key>": {
    "type": "success",
    "success": {}
  }
}

Get enriched ingest status#

POST /video/v1/videos/enriched-ingest-status

Deprecated: Legacy Video-entity API. Videos are now channels on datasets; ingest status is tracked per file on the Catalog dataset file (CatalogService#getDatasetFile).

Body

videoRid string (RID) required

​

token string

​

Response

status VideoIngestStatus

​

Set type to "ready".

ready Empty

​

Set type to "inProgress".

inProgress Empty

​

Set type to "error".

error Empty

​

fileIngestStatus map of VideoFileRid to VideoFileIngestStatus

​

Set type to "success".

success SuccessIngestStatus

​

Set type to "error".

error IngestError

​

Fields of IngestError
errorType string

​

message string

​

errorInstanceId string

​

Set type to "inProgress".

inProgress Empty

​

nextPageToken string

​

When there is nothing to return, the response is HTTP 204 with no body.

Request

curl -X POST "https://api.gov.nominal.io/api/video/v1/videos/enriched-ingest-status" \
  -H "Authorization: Bearer <api key>" \
  -H "Content-Type: application/json" \
  --data '{
  "videoRid": "<video rid>"
}'
import requests

response = requests.post(
    "https://api.gov.nominal.io/api/video/v1/videos/enriched-ingest-status",
    headers={"Authorization": "Bearer <api key>"},
    json={"videoRid": "<video rid>"},
)
response.raise_for_status()
print(response.json())
import httpx

response = httpx.post(
    "https://api.gov.nominal.io/api/video/v1/videos/enriched-ingest-status",
    headers={"Authorization": "Bearer <api key>"},
    json={"videoRid": "<video rid>"},
)
response.raise_for_status()
print(response.json())
import asyncio

import aiohttp


async def main() -> None:
    async with aiohttp.ClientSession() as session:
        async with session.post(
            "https://api.gov.nominal.io/api/video/v1/videos/enriched-ingest-status",
            headers={"Authorization": "Bearer <api key>"},
            json={"videoRid": "<video rid>"},
        ) as response:
            response.raise_for_status()
            print(await response.json())


asyncio.run(main())

Response: 200

{
  "status": {
    "type": "ready",
    "ready": {}
  },
  "fileIngestStatus": {
    "<key>": {
      "type": "success",
      "success": {}
    }
  },
  "nextPageToken": "<token>"
}

Archive#

PUT /video/v1/videos/{videoRid}/archive

Deprecated: Legacy Video-entity API. Videos are now channels on datasets; archive the backing dataset with CatalogService#archiveDataset, or delete individual files with IngestService#deleteFile.

Archives a video, which excludes it from search and hides it from being publicly visible, but does not permanently delete it. Archived videos can be unarchived.

Path parameters

videoRid string (RID) required

​

Response

No content (HTTP 204).

Request

curl -X PUT "https://api.gov.nominal.io/api/video/v1/videos/<video rid>/archive" \
  -H "Authorization: Bearer <api key>"
import requests

response = requests.put(
    "https://api.gov.nominal.io/api/video/v1/videos/<video rid>/archive",
    headers={"Authorization": "Bearer <api key>"},
)
response.raise_for_status()
import httpx

response = httpx.put(
    "https://api.gov.nominal.io/api/video/v1/videos/<video rid>/archive",
    headers={"Authorization": "Bearer <api key>"},
)
response.raise_for_status()
import asyncio

import aiohttp


async def main() -> None:
    async with aiohttp.ClientSession() as session:
        async with session.put(
            "https://api.gov.nominal.io/api/video/v1/videos/<video rid>/archive",
            headers={"Authorization": "Bearer <api key>"},
        ) as response:
            response.raise_for_status()


asyncio.run(main())

Response: 204

No content.

Unarchive#

PUT /video/v1/videos/{videoRid}/unarchive

Deprecated: Legacy Video-entity API. Videos are now channels on datasets; unarchive the backing dataset with CatalogService#unarchiveDataset.

Unarchives a previously archived video.

Path parameters

videoRid string (RID) required

​

Response

No content (HTTP 204).

Request

curl -X PUT "https://api.gov.nominal.io/api/video/v1/videos/<video rid>/unarchive" \
  -H "Authorization: Bearer <api key>"
import requests

response = requests.put(
    "https://api.gov.nominal.io/api/video/v1/videos/<video rid>/unarchive",
    headers={"Authorization": "Bearer <api key>"},
)
response.raise_for_status()
import httpx

response = httpx.put(
    "https://api.gov.nominal.io/api/video/v1/videos/<video rid>/unarchive",
    headers={"Authorization": "Bearer <api key>"},
)
response.raise_for_status()
import asyncio

import aiohttp


async def main() -> None:
    async with aiohttp.ClientSession() as session:
        async with session.put(
            "https://api.gov.nominal.io/api/video/v1/videos/<video rid>/unarchive",
            headers={"Authorization": "Bearer <api key>"},
        ) as response:
            response.raise_for_status()


asyncio.run(main())

Response: 204

No content.

Get playlist#

GET /video/v1/videos/{videoRid}/playlist

Deprecated: Replaced by getPlaylistV2, which addresses the video channel series (channel + tags) instead of a Video rid.

Generates an HLS playlist for a video within optional time bounds. Uses GET with query parameters for HLS.js compatibility. The HLS playlist will contain links to all of the segments in the video that overlap with the given bounds, or all segments if no bounds are provided.

Note: The start and end parameters must either both be provided or both be omitted. Providing only one will result in a MissingTimestampBoundPair error.

Path parameters

videoRid string (RID) required

​

Query parameters

start string

Start bound as ISO-8601 timestamp (e.g., “2024-01-01T00:00:00Z”). Must be provided together with end, or neither.

end string

End bound as ISO-8601 timestamp (e.g., “2024-01-01T01:00:00Z”). Must be provided together with start, or neither.

Response: application/octet-stream

The body is the raw bytes.

A successful response.

Request

curl "https://api.gov.nominal.io/api/video/v1/videos/<video rid>/playlist" \
  -H "Authorization: Bearer <api key>" \
  --output "<file>"
from pathlib import Path

import requests

response = requests.get(
    "https://api.gov.nominal.io/api/video/v1/videos/<video rid>/playlist",
    headers={"Authorization": "Bearer <api key>"},
)
response.raise_for_status()
Path("<file>").write_bytes(response.content)
from pathlib import Path

import httpx

response = httpx.get(
    "https://api.gov.nominal.io/api/video/v1/videos/<video rid>/playlist",
    headers={"Authorization": "Bearer <api key>"},
)
response.raise_for_status()
Path("<file>").write_bytes(response.content)
import asyncio
from pathlib import Path

import aiohttp


async def main() -> None:
    async with aiohttp.ClientSession() as session:
        async with session.get(
            "https://api.gov.nominal.io/api/video/v1/videos/<video rid>/playlist",
            headers={"Authorization": "Bearer <api key>"},
        ) as response:
            response.raise_for_status()
            Path("<file>").write_bytes(await response.read())


asyncio.run(main())

Response: 200

The raw bytes.

Get segment summaries#

GET /video/v1/videos/{videoRid}/segment-summaries

Deprecated: Replaced by getSegmentSummariesInBounds. Will be removed after April 15th.

Returns the min and max absolute and media timestamps for each segment in a video. To be used during frame-timestamp mapping.

Path parameters

videoRid string (RID) required

​

Response

The body is an array of SegmentSummary.

Fields of SegmentSummary
minAbsoluteTimestamp Timestamp

​

Fields of Timestamp
seconds integer (int64)

​

nanos integer (int64)

​

maxAbsoluteTimestamp Timestamp

​

minMediaTimestamp number

​

maxMediaTimestamp number

​

Request

curl "https://api.gov.nominal.io/api/video/v1/videos/<video rid>/segment-summaries" \
  -H "Authorization: Bearer <api key>"
import requests

response = requests.get(
    "https://api.gov.nominal.io/api/video/v1/videos/<video rid>/segment-summaries",
    headers={"Authorization": "Bearer <api key>"},
)
response.raise_for_status()
print(response.json())
import httpx

response = httpx.get(
    "https://api.gov.nominal.io/api/video/v1/videos/<video rid>/segment-summaries",
    headers={"Authorization": "Bearer <api key>"},
)
response.raise_for_status()
print(response.json())
import asyncio

import aiohttp


async def main() -> None:
    async with aiohttp.ClientSession() as session:
        async with session.get(
            "https://api.gov.nominal.io/api/video/v1/videos/<video rid>/segment-summaries",
            headers={"Authorization": "Bearer <api key>"},
        ) as response:
            response.raise_for_status()
            print(await response.json())


asyncio.run(main())

Response: 200

[
  {
    "minAbsoluteTimestamp": {
      "seconds": 1,
      "nanos": 1
    },
    "maxAbsoluteTimestamp": {
      "seconds": 1,
      "nanos": 1
    },
    "minMediaTimestamp": 1,
    "maxMediaTimestamp": 1
  }
]

Get playlist in bounds#

POST /video/v1/videos/{videoRid}/playlist-in-bounds

Deprecated: Use getPlaylist (GET) for HLS.js compatibility.

Generates an HLS playlist for a video with the given video rid to enable playback within an optional set of bounds. The HLS playlist will contain links to all of the segments in the video that overlap with the given bounds. playlist will be limited to the given bounds.

Path parameters

videoRid string (RID) required

​

Body

bounds Bounds

​

Fields of Bounds
start Timestamp required

​

Fields of Timestamp
seconds integer (int64) required

​

nanos integer (int64) required

​

end Timestamp required

​

Response: application/octet-stream

The body is the raw bytes.

A successful response.

Request

curl -X POST "https://api.gov.nominal.io/api/video/v1/videos/<video rid>/playlist-in-bounds" \
  -H "Authorization: Bearer <api key>" \
  -H "Content-Type: application/json" \
  --data '{
  "bounds": {
    "start": {
      "seconds": 1,
      "nanos": 1
    },
    "end": {
      "seconds": 1,
      "nanos": 1
    }
  }
}' \
  --output "<file>"
from pathlib import Path

import requests

response = requests.post(
    "https://api.gov.nominal.io/api/video/v1/videos/<video rid>/playlist-in-bounds",
    headers={"Authorization": "Bearer <api key>"},
    json={
        "bounds": {
            "start": {"seconds": 1, "nanos": 1},
            "end": {"seconds": 1, "nanos": 1},
        },
    },
)
response.raise_for_status()
Path("<file>").write_bytes(response.content)
from pathlib import Path

import httpx

response = httpx.post(
    "https://api.gov.nominal.io/api/video/v1/videos/<video rid>/playlist-in-bounds",
    headers={"Authorization": "Bearer <api key>"},
    json={
        "bounds": {
            "start": {"seconds": 1, "nanos": 1},
            "end": {"seconds": 1, "nanos": 1},
        },
    },
)
response.raise_for_status()
Path("<file>").write_bytes(response.content)
import asyncio
from pathlib import Path

import aiohttp


async def main() -> None:
    async with aiohttp.ClientSession() as session:
        async with session.post(
            "https://api.gov.nominal.io/api/video/v1/videos/<video rid>/playlist-in-bounds",
            headers={"Authorization": "Bearer <api key>"},
            json={
                "bounds": {
                    "start": {"seconds": 1, "nanos": 1},
                    "end": {"seconds": 1, "nanos": 1},
                },
            },
        ) as response:
            response.raise_for_status()
            Path("<file>").write_bytes(await response.read())


asyncio.run(main())

Response: 200

The raw bytes.

Get playlist in bounds v2#

POST /video/v2/videos/playlist-in-bounds

Deprecated: Use getPlaylistV2 (GET) for HLS.js compatibility.

Generates an HLS playlist for a video series (identified by channel + tags) within bounds.

Body

channelSeries VideoChannelSeries required

​

Set type to "dataSource".

dataSource VideoDataSourceChannel

​

Fields of VideoDataSourceChannel
dataSourceRid string required

​

channel string required

​

tags map of TagName to string

​

Set type to "asset".

asset VideoAssetChannel

​

Fields of VideoAssetChannel
assetRid string required

​

dataScopeName string required

​

channel string required

​

tags map of TagName to string

​

bounds Bounds required

​

Fields of Bounds
start Timestamp required

​

Fields of Timestamp
seconds integer (int64) required

​

nanos integer (int64) required

​

end Timestamp required

​

Response: application/octet-stream

The body is the raw bytes.

A successful response.

Request

curl -X POST "https://api.gov.nominal.io/api/video/v2/videos/playlist-in-bounds" \
  -H "Authorization: Bearer <api key>" \
  -H "Content-Type: application/json" \
  --data '{
  "channelSeries": {
    "type": "dataSource",
    "dataSource": {
      "dataSourceRid": "<data source rid>",
      "channel": "<channel>"
    }
  },
  "bounds": {
    "start": {
      "seconds": 1,
      "nanos": 1
    },
    "end": {
      "seconds": 1,
      "nanos": 1
    }
  }
}' \
  --output "<file>"
from pathlib import Path

import requests

response = requests.post(
    "https://api.gov.nominal.io/api/video/v2/videos/playlist-in-bounds",
    headers={"Authorization": "Bearer <api key>"},
    json={
        "channelSeries": {
            "type": "dataSource",
            "dataSource": {"dataSourceRid": "<data source rid>", "channel": "<channel>"},
        },
        "bounds": {
            "start": {"seconds": 1, "nanos": 1},
            "end": {"seconds": 1, "nanos": 1},
        },
    },
)
response.raise_for_status()
Path("<file>").write_bytes(response.content)
from pathlib import Path

import httpx

response = httpx.post(
    "https://api.gov.nominal.io/api/video/v2/videos/playlist-in-bounds",
    headers={"Authorization": "Bearer <api key>"},
    json={
        "channelSeries": {
            "type": "dataSource",
            "dataSource": {"dataSourceRid": "<data source rid>", "channel": "<channel>"},
        },
        "bounds": {
            "start": {"seconds": 1, "nanos": 1},
            "end": {"seconds": 1, "nanos": 1},
        },
    },
)
response.raise_for_status()
Path("<file>").write_bytes(response.content)
import asyncio
from pathlib import Path

import aiohttp


async def main() -> None:
    async with aiohttp.ClientSession() as session:
        async with session.post(
            "https://api.gov.nominal.io/api/video/v2/videos/playlist-in-bounds",
            headers={"Authorization": "Bearer <api key>"},
            json={
                "channelSeries": {
                    "type": "dataSource",
                    "dataSource": {
                        "dataSourceRid": "<data source rid>",
                        "channel": "<channel>",
                    },
                },
                "bounds": {
                    "start": {"seconds": 1, "nanos": 1},
                    "end": {"seconds": 1, "nanos": 1},
                },
            },
        ) as response:
            response.raise_for_status()
            Path("<file>").write_bytes(await response.read())


asyncio.run(main())

Response: 200

The raw bytes.

Get playlist v2#

GET /video/v2/videos/playlist

Generates an HLS playlist for a video series within time bounds. Specify either dataSourceRid OR (assetRid + dataScopeName) to identify the series source.

Note: Both start and end parameters are required and must be provided together.

Query parameters

dataSourceRid string (RID)

Data source RID (mutually exclusive with assetRid)

assetRid string (RID)

Asset RID (mutually exclusive with dataSourceRid, requires dataScopeName)

dataScopeName string

Data scope name (required when using assetRid)

channel string required

Channel name

tags string

Tags as JSON-encoded map (e.g., {“vehicle”:”car1”})

start string required

Required start bound as ISO-8601 timestamp (e.g., “2024-01-01T00:00:00Z”). Must be provided with end.

end string required

Required end bound as ISO-8601 timestamp (e.g., “2024-01-01T01:00:00Z”). Must be provided with start.

Response: application/octet-stream

The body is the raw bytes.

A successful response.

Request

curl "https://api.gov.nominal.io/api/video/v2/videos/playlist?channel=<channel>&start=<start>&end=<end>" \
  -H "Authorization: Bearer <api key>" \
  --output "<file>"
from pathlib import Path

import requests

response = requests.get(
    "https://api.gov.nominal.io/api/video/v2/videos/playlist?channel=<channel>&start=<start>&end=<end>",
    headers={"Authorization": "Bearer <api key>"},
)
response.raise_for_status()
Path("<file>").write_bytes(response.content)
from pathlib import Path

import httpx

response = httpx.get(
    "https://api.gov.nominal.io/api/video/v2/videos/playlist?channel=<channel>&start=<start>&end=<end>",
    headers={"Authorization": "Bearer <api key>"},
)
response.raise_for_status()
Path("<file>").write_bytes(response.content)
import asyncio
from pathlib import Path

import aiohttp


async def main() -> None:
    async with aiohttp.ClientSession() as session:
        async with session.get(
            "https://api.gov.nominal.io/api/video/v2/videos/playlist?channel=<channel>&start=<start>&end=<end>",
            headers={"Authorization": "Bearer <api key>"},
        ) as response:
            response.raise_for_status()
            Path("<file>").write_bytes(await response.read())


asyncio.run(main())

Response: 200

The raw bytes.

Get segment summaries in bounds#

POST /video/v1/videos/{videoRid}/segment-summaries-in-bounds

Deprecated: Replaced by getSegmentSummariesInBoundsV2, which addresses the video channel series (channel + tags) instead of a Video rid.

Returns the min and max absolute and media timestamps for each segment in a video that overlap with an optional set of bounds.

Path parameters

videoRid string (RID) required

​

Body

bounds Bounds

​

Fields of Bounds
start Timestamp required

​

Fields of Timestamp
seconds integer (int64) required

​

nanos integer (int64) required

​

end Timestamp required

​

Response

The body is an array of SegmentSummary.

Fields of SegmentSummary
minAbsoluteTimestamp Timestamp

​

Fields of Timestamp
seconds integer (int64)

​

nanos integer (int64)

​

maxAbsoluteTimestamp Timestamp

​

minMediaTimestamp number

​

maxMediaTimestamp number

​

Request

curl -X POST "https://api.gov.nominal.io/api/video/v1/videos/<video rid>/segment-summaries-in-bounds" \
  -H "Authorization: Bearer <api key>" \
  -H "Content-Type: application/json" \
  --data '{
  "bounds": {
    "start": {
      "seconds": 1,
      "nanos": 1
    },
    "end": {
      "seconds": 1,
      "nanos": 1
    }
  }
}'
import requests

response = requests.post(
    "https://api.gov.nominal.io/api/video/v1/videos/<video rid>/segment-summaries-in-bounds",
    headers={"Authorization": "Bearer <api key>"},
    json={
        "bounds": {
            "start": {"seconds": 1, "nanos": 1},
            "end": {"seconds": 1, "nanos": 1},
        },
    },
)
response.raise_for_status()
print(response.json())
import httpx

response = httpx.post(
    "https://api.gov.nominal.io/api/video/v1/videos/<video rid>/segment-summaries-in-bounds",
    headers={"Authorization": "Bearer <api key>"},
    json={
        "bounds": {
            "start": {"seconds": 1, "nanos": 1},
            "end": {"seconds": 1, "nanos": 1},
        },
    },
)
response.raise_for_status()
print(response.json())
import asyncio

import aiohttp


async def main() -> None:
    async with aiohttp.ClientSession() as session:
        async with session.post(
            "https://api.gov.nominal.io/api/video/v1/videos/<video rid>/segment-summaries-in-bounds",
            headers={"Authorization": "Bearer <api key>"},
            json={
                "bounds": {
                    "start": {"seconds": 1, "nanos": 1},
                    "end": {"seconds": 1, "nanos": 1},
                },
            },
        ) as response:
            response.raise_for_status()
            print(await response.json())


asyncio.run(main())

Response: 200

[
  {
    "minAbsoluteTimestamp": {
      "seconds": 1,
      "nanos": 1
    },
    "maxAbsoluteTimestamp": {
      "seconds": 1,
      "nanos": 1
    },
    "minMediaTimestamp": 1,
    "maxMediaTimestamp": 1
  }
]

Get segment summaries in bounds v2#

POST /video/v2/videos/segment-summaries-in-bounds

Returns the min and max absolute and media timestamps for each segment matching a video series (identified by channel + tags) within the specified bounds.

Body

channelSeries VideoChannelSeries required

​

Set type to "dataSource".

dataSource VideoDataSourceChannel

​

Fields of VideoDataSourceChannel
dataSourceRid string required

​

channel string required

​

tags map of TagName to string

​

Set type to "asset".

asset VideoAssetChannel

​

Fields of VideoAssetChannel
assetRid string required

​

dataScopeName string required

​

channel string required

​

tags map of TagName to string

​

bounds Bounds required

​

Fields of Bounds
start Timestamp required

​

Fields of Timestamp
seconds integer (int64) required

​

nanos integer (int64) required

​

end Timestamp required

​

Response

The body is an array of SegmentSummaryV2.

Fields of SegmentSummaryV2
datasetFileId string (UUID)

The dataset file ID that this segment belongs to.

minAbsoluteTimestamp Timestamp

​

Fields of Timestamp
seconds integer (int64)

​

nanos integer (int64)

​

maxAbsoluteTimestamp Timestamp

​

minMediaTimestamp number

​

maxMediaTimestamp number

​

Request

curl -X POST "https://api.gov.nominal.io/api/video/v2/videos/segment-summaries-in-bounds" \
  -H "Authorization: Bearer <api key>" \
  -H "Content-Type: application/json" \
  --data '{
  "channelSeries": {
    "type": "dataSource",
    "dataSource": {
      "dataSourceRid": "<data source rid>",
      "channel": "<channel>"
    }
  },
  "bounds": {
    "start": {
      "seconds": 1,
      "nanos": 1
    },
    "end": {
      "seconds": 1,
      "nanos": 1
    }
  }
}'
import requests

response = requests.post(
    "https://api.gov.nominal.io/api/video/v2/videos/segment-summaries-in-bounds",
    headers={"Authorization": "Bearer <api key>"},
    json={
        "channelSeries": {
            "type": "dataSource",
            "dataSource": {"dataSourceRid": "<data source rid>", "channel": "<channel>"},
        },
        "bounds": {
            "start": {"seconds": 1, "nanos": 1},
            "end": {"seconds": 1, "nanos": 1},
        },
    },
)
response.raise_for_status()
print(response.json())
import httpx

response = httpx.post(
    "https://api.gov.nominal.io/api/video/v2/videos/segment-summaries-in-bounds",
    headers={"Authorization": "Bearer <api key>"},
    json={
        "channelSeries": {
            "type": "dataSource",
            "dataSource": {"dataSourceRid": "<data source rid>", "channel": "<channel>"},
        },
        "bounds": {
            "start": {"seconds": 1, "nanos": 1},
            "end": {"seconds": 1, "nanos": 1},
        },
    },
)
response.raise_for_status()
print(response.json())
import asyncio

import aiohttp


async def main() -> None:
    async with aiohttp.ClientSession() as session:
        async with session.post(
            "https://api.gov.nominal.io/api/video/v2/videos/segment-summaries-in-bounds",
            headers={"Authorization": "Bearer <api key>"},
            json={
                "channelSeries": {
                    "type": "dataSource",
                    "dataSource": {
                        "dataSourceRid": "<data source rid>",
                        "channel": "<channel>",
                    },
                },
                "bounds": {
                    "start": {"seconds": 1, "nanos": 1},
                    "end": {"seconds": 1, "nanos": 1},
                },
            },
        ) as response:
            response.raise_for_status()
            print(await response.json())


asyncio.run(main())

Response: 200

[
  {
    "datasetFileId": "<dataset file id>",
    "minAbsoluteTimestamp": {
      "seconds": 1,
      "nanos": 1
    },
    "maxAbsoluteTimestamp": {
      "seconds": 1,
      "nanos": 1
    },
    "minMediaTimestamp": 1,
    "maxMediaTimestamp": 1
  }
]

Get segment metadata v2#

POST /video/v2/videos/segment-metadata

Returns aggregated segment metadata for a video channel series, including total frames, segment count, min/max timestamps, and average frame rate. Optionally filter by time bounds.

Body

channelSeries VideoChannelSeries required

​

Set type to "dataSource".

dataSource VideoDataSourceChannel

​

Fields of VideoDataSourceChannel
dataSourceRid string required

​

channel string required

​

tags map of TagName to string

​

Set type to "asset".

asset VideoAssetChannel

​

Fields of VideoAssetChannel
assetRid string required

​

dataScopeName string required

​

channel string required

​

tags map of TagName to string

​

bounds Bounds

​

Fields of Bounds
start Timestamp required

​

Fields of Timestamp
seconds integer (int64) required

​

nanos integer (int64) required

​

end Timestamp required

​

Response

numFrames integer

​

numSegments integer

​

minAbsoluteTimestamp Timestamp

​

Fields of Timestamp
seconds integer (int64)

​

nanos integer (int64)

​

maxAbsoluteTimestamp Timestamp

​

mediaDurationSeconds number

​

mediaFrameRate number

The average media frame rate (FPS) calculated as total frames / duration in seconds.

When there is nothing to return, the response is HTTP 204 with no body.

Request

curl -X POST "https://api.gov.nominal.io/api/video/v2/videos/segment-metadata" \
  -H "Authorization: Bearer <api key>" \
  -H "Content-Type: application/json" \
  --data '{
  "channelSeries": {
    "type": "dataSource",
    "dataSource": {
      "dataSourceRid": "<data source rid>",
      "channel": "<channel>"
    }
  }
}'
import requests

response = requests.post(
    "https://api.gov.nominal.io/api/video/v2/videos/segment-metadata",
    headers={"Authorization": "Bearer <api key>"},
    json={
        "channelSeries": {
            "type": "dataSource",
            "dataSource": {"dataSourceRid": "<data source rid>", "channel": "<channel>"},
        },
    },
)
response.raise_for_status()
print(response.json())
import httpx

response = httpx.post(
    "https://api.gov.nominal.io/api/video/v2/videos/segment-metadata",
    headers={"Authorization": "Bearer <api key>"},
    json={
        "channelSeries": {
            "type": "dataSource",
            "dataSource": {"dataSourceRid": "<data source rid>", "channel": "<channel>"},
        },
    },
)
response.raise_for_status()
print(response.json())
import asyncio

import aiohttp


async def main() -> None:
    async with aiohttp.ClientSession() as session:
        async with session.post(
            "https://api.gov.nominal.io/api/video/v2/videos/segment-metadata",
            headers={"Authorization": "Bearer <api key>"},
            json={
                "channelSeries": {
                    "type": "dataSource",
                    "dataSource": {
                        "dataSourceRid": "<data source rid>",
                        "channel": "<channel>",
                    },
                },
            },
        ) as response:
            response.raise_for_status()
            print(await response.json())


asyncio.run(main())

Response: 200

{
  "numFrames": 1,
  "numSegments": 1,
  "minAbsoluteTimestamp": {
    "seconds": 1,
    "nanos": 1
  },
  "maxAbsoluteTimestamp": {
    "seconds": 1,
    "nanos": 1
  },
  "mediaDurationSeconds": 1,
  "mediaFrameRate": 1
}

Get segment by timestamp v2#

POST /video/v2/videos/get-segment-by-timestamp

Returns metadata for the segment within a video series containing the requested absolute timestamp.

Body

channelSeries VideoChannelSeries required

​

Set type to "dataSource".

dataSource VideoDataSourceChannel

​

Fields of VideoDataSourceChannel
dataSourceRid string required

​

channel string required

​

tags map of TagName to string

​

Set type to "asset".

asset VideoAssetChannel

​

Fields of VideoAssetChannel
assetRid string required

​

dataScopeName string required

​

channel string required

​

tags map of TagName to string

​

timestamp Timestamp required

​

Fields of Timestamp
seconds integer (int64) required

​

nanos integer (int64) required

​

viewRangeStart Timestamp

The start of the view range used to dynamically calculate media timestamps. The first segment with an overlap with the time bounds will have its minimum media timestamp set to 0, with every subsequent segment building media time cumulatively from that offset.

Response

rid string (RID)

​

datasetFileId string (UUID)

The dataset file ID that this segment belongs to.

dataHandle Handle

​

Set type to "s3".

s3 string

​

frameRate number

The average frame rate (FPS) of the segment calculated as total frames / duration in seconds.

durationSeconds number

The duration of a segment in media time.

timestamps SegmentTimestamps

for videos with frame-level timestamps, we provide mappings, otherwise we just include a single list of timestamps.

Set type to "timestampMappings".

timestampMappings TimestampMappings

​

Fields of TimestampMappings
mediaTimestamps array of number

​

absoluteTimestamps array of Timestamp

​

Fields of Timestamp
seconds integer (int64)

​

nanos integer (int64)

​

When there is nothing to return, the response is HTTP 204 with no body.

Request

curl -X POST "https://api.gov.nominal.io/api/video/v2/videos/get-segment-by-timestamp" \
  -H "Authorization: Bearer <api key>" \
  -H "Content-Type: application/json" \
  --data '{
  "channelSeries": {
    "type": "dataSource",
    "dataSource": {
      "dataSourceRid": "<data source rid>",
      "channel": "<channel>"
    }
  },
  "timestamp": {
    "seconds": 1,
    "nanos": 1
  }
}'
import requests

response = requests.post(
    "https://api.gov.nominal.io/api/video/v2/videos/get-segment-by-timestamp",
    headers={"Authorization": "Bearer <api key>"},
    json={
        "channelSeries": {
            "type": "dataSource",
            "dataSource": {"dataSourceRid": "<data source rid>", "channel": "<channel>"},
        },
        "timestamp": {"seconds": 1, "nanos": 1},
    },
)
response.raise_for_status()
print(response.json())
import httpx

response = httpx.post(
    "https://api.gov.nominal.io/api/video/v2/videos/get-segment-by-timestamp",
    headers={"Authorization": "Bearer <api key>"},
    json={
        "channelSeries": {
            "type": "dataSource",
            "dataSource": {"dataSourceRid": "<data source rid>", "channel": "<channel>"},
        },
        "timestamp": {"seconds": 1, "nanos": 1},
    },
)
response.raise_for_status()
print(response.json())
import asyncio

import aiohttp


async def main() -> None:
    async with aiohttp.ClientSession() as session:
        async with session.post(
            "https://api.gov.nominal.io/api/video/v2/videos/get-segment-by-timestamp",
            headers={"Authorization": "Bearer <api key>"},
            json={
                "channelSeries": {
                    "type": "dataSource",
                    "dataSource": {
                        "dataSourceRid": "<data source rid>",
                        "channel": "<channel>",
                    },
                },
                "timestamp": {"seconds": 1, "nanos": 1},
            },
        ) as response:
            response.raise_for_status()
            print(await response.json())


asyncio.run(main())

Response: 200

{
  "rid": "<segment rid>",
  "datasetFileId": "<dataset file id>",
  "dataHandle": {
    "type": "s3",
    "s3": "<s3 path>"
  },
  "frameRate": 1,
  "durationSeconds": 1,
  "timestamps": {
    "type": "timestampMappings",
    "timestampMappings": {
      "mediaTimestamps": [
        1
      ],
      "absoluteTimestamps": [
        {
          "seconds": 1,
          "nanos": 1
        }
      ]
    }
  }
}

Get segment at or after timestamp#

POST /video/v1/videos/{videoRid}/get-segment-at-or-after-timestamp

Deprecated: Replaced by getSegmentAtOrAfterTimestampV2, which addresses the video channel series (channel + tags) instead of a Video rid.

Returns metadata for the segment containing the requested absolute timestamp. If no segment contains the timestamp, returns the closest segment starting after the timestamp. Returns empty if no segment is found at or after the timestamp.

Path parameters

videoRid string (RID) required

​

Body

timestamp Timestamp required

​

Fields of Timestamp
seconds integer (int64) required

​

nanos integer (int64) required

​

Response

rid string (RID)

​

videoRid string (RID)

​

dataHandle Handle

​

Set type to "s3".

s3 string

​

frameRate number

The average frame rate (FPS) of the segment calculated as total frames / duration in seconds.

durationSeconds number

The duration of a segment in media time.

timestamps SegmentTimestamps

for videos with frame-level timestamps, we provide mappings, otherwise we just include a single list of timestamps.

Set type to "timestampMappings".

timestampMappings TimestampMappings

​

Fields of TimestampMappings
mediaTimestamps array of number

​

absoluteTimestamps array of Timestamp

​

Fields of Timestamp
seconds integer (int64)

​

nanos integer (int64)

​

When there is nothing to return, the response is HTTP 204 with no body.

Request

curl -X POST "https://api.gov.nominal.io/api/video/v1/videos/<video rid>/get-segment-at-or-after-timestamp" \
  -H "Authorization: Bearer <api key>" \
  -H "Content-Type: application/json" \
  --data '{
  "timestamp": {
    "seconds": 1,
    "nanos": 1
  }
}'
import requests

response = requests.post(
    "https://api.gov.nominal.io/api/video/v1/videos/<video rid>/get-segment-at-or-after-timestamp",
    headers={"Authorization": "Bearer <api key>"},
    json={"timestamp": {"seconds": 1, "nanos": 1}},
)
response.raise_for_status()
print(response.json())
import httpx

response = httpx.post(
    "https://api.gov.nominal.io/api/video/v1/videos/<video rid>/get-segment-at-or-after-timestamp",
    headers={"Authorization": "Bearer <api key>"},
    json={"timestamp": {"seconds": 1, "nanos": 1}},
)
response.raise_for_status()
print(response.json())
import asyncio

import aiohttp


async def main() -> None:
    async with aiohttp.ClientSession() as session:
        async with session.post(
            "https://api.gov.nominal.io/api/video/v1/videos/<video rid>/get-segment-at-or-after-timestamp",
            headers={"Authorization": "Bearer <api key>"},
            json={"timestamp": {"seconds": 1, "nanos": 1}},
        ) as response:
            response.raise_for_status()
            print(await response.json())


asyncio.run(main())

Response: 200

{
  "rid": "<segment rid>",
  "videoRid": "<video rid>",
  "dataHandle": {
    "type": "s3",
    "s3": "<s3 path>"
  },
  "frameRate": 1,
  "durationSeconds": 1,
  "timestamps": {
    "type": "timestampMappings",
    "timestampMappings": {
      "mediaTimestamps": [
        1
      ],
      "absoluteTimestamps": [
        {
          "seconds": 1,
          "nanos": 1
        }
      ]
    }
  }
}

Get segment at or after timestamp v2#

POST /video/v2/videos/get-segment-at-or-after-timestamp

Returns metadata for the segment containing the requested absolute timestamp for a video series (identified by channel + tags). If no segment contains the timestamp, returns the closest segment starting after the timestamp. Returns empty if no segment is found at or after the timestamp.

Body

channelSeries VideoChannelSeries required

​

Set type to "dataSource".

dataSource VideoDataSourceChannel

​

Fields of VideoDataSourceChannel
dataSourceRid string required

​

channel string required

​

tags map of TagName to string

​

Set type to "asset".

asset VideoAssetChannel

​

Fields of VideoAssetChannel
assetRid string required

​

dataScopeName string required

​

channel string required

​

tags map of TagName to string

​

timestamp Timestamp required

​

Fields of Timestamp
seconds integer (int64) required

​

nanos integer (int64) required

​

Response

rid string (RID)

​

datasetFileId string (UUID)

The dataset file ID that this segment belongs to.

dataHandle Handle

​

Set type to "s3".

s3 string

​

frameRate number

The average frame rate (FPS) of the segment calculated as total frames / duration in seconds.

durationSeconds number

The duration of a segment in media time.

timestamps SegmentTimestamps

for videos with frame-level timestamps, we provide mappings, otherwise we just include a single list of timestamps.

Set type to "timestampMappings".

timestampMappings TimestampMappings

​

Fields of TimestampMappings
mediaTimestamps array of number

​

absoluteTimestamps array of Timestamp

​

Fields of Timestamp
seconds integer (int64)

​

nanos integer (int64)

​

When there is nothing to return, the response is HTTP 204 with no body.

Request

curl -X POST "https://api.gov.nominal.io/api/video/v2/videos/get-segment-at-or-after-timestamp" \
  -H "Authorization: Bearer <api key>" \
  -H "Content-Type: application/json" \
  --data '{
  "channelSeries": {
    "type": "dataSource",
    "dataSource": {
      "dataSourceRid": "<data source rid>",
      "channel": "<channel>"
    }
  },
  "timestamp": {
    "seconds": 1,
    "nanos": 1
  }
}'
import requests

response = requests.post(
    "https://api.gov.nominal.io/api/video/v2/videos/get-segment-at-or-after-timestamp",
    headers={"Authorization": "Bearer <api key>"},
    json={
        "channelSeries": {
            "type": "dataSource",
            "dataSource": {"dataSourceRid": "<data source rid>", "channel": "<channel>"},
        },
        "timestamp": {"seconds": 1, "nanos": 1},
    },
)
response.raise_for_status()
print(response.json())
import httpx

response = httpx.post(
    "https://api.gov.nominal.io/api/video/v2/videos/get-segment-at-or-after-timestamp",
    headers={"Authorization": "Bearer <api key>"},
    json={
        "channelSeries": {
            "type": "dataSource",
            "dataSource": {"dataSourceRid": "<data source rid>", "channel": "<channel>"},
        },
        "timestamp": {"seconds": 1, "nanos": 1},
    },
)
response.raise_for_status()
print(response.json())
import asyncio

import aiohttp


async def main() -> None:
    async with aiohttp.ClientSession() as session:
        async with session.post(
            "https://api.gov.nominal.io/api/video/v2/videos/get-segment-at-or-after-timestamp",
            headers={"Authorization": "Bearer <api key>"},
            json={
                "channelSeries": {
                    "type": "dataSource",
                    "dataSource": {
                        "dataSourceRid": "<data source rid>",
                        "channel": "<channel>",
                    },
                },
                "timestamp": {"seconds": 1, "nanos": 1},
            },
        ) as response:
            response.raise_for_status()
            print(await response.json())


asyncio.run(main())

Response: 200

{
  "rid": "<segment rid>",
  "datasetFileId": "<dataset file id>",
  "dataHandle": {
    "type": "s3",
    "s3": "<s3 path>"
  },
  "frameRate": 1,
  "durationSeconds": 1,
  "timestamps": {
    "type": "timestampMappings",
    "timestampMappings": {
      "mediaTimestamps": [
        1
      ],
      "absoluteTimestamps": [
        {
          "seconds": 1,
          "nanos": 1
        }
      ]
    }
  }
}

Get file summaries#

POST /video/v1/videos/{videoRid}/get-ranges-with-existing-segment-data

Deprecated: Replaced by listVideoChannelDatasetFiles, which returns the dataset files backing a video channel together with the bounds each file contributes.

Returns the min and max absolute timestamps from non-archived video files associated with a given video that overlap with an optional set of bounds. The files on the edges of the bounds will be truncated to segments that are inside or overlap with the bounds.

Path parameters

videoRid string (RID) required

​

Body

bounds Bounds

​

Fields of Bounds
start Timestamp required

​

Fields of Timestamp
seconds integer (int64) required

​

nanos integer (int64) required

​

end Timestamp required

​

Response

fileSummaries array of FileSummary

​

Fields of FileSummary
fileRid string (RID)

​

bounds Bounds

​

Fields of Bounds
start Timestamp

​

Fields of Timestamp
seconds integer (int64)

​

nanos integer (int64)

​

end Timestamp

​

Request

curl -X POST "https://api.gov.nominal.io/api/video/v1/videos/<video rid>/get-ranges-with-existing-segment-data" \
  -H "Authorization: Bearer <api key>" \
  -H "Content-Type: application/json" \
  --data '{
  "bounds": {
    "start": {
      "seconds": 1,
      "nanos": 1
    },
    "end": {
      "seconds": 1,
      "nanos": 1
    }
  }
}'
import requests

response = requests.post(
    "https://api.gov.nominal.io/api/video/v1/videos/<video rid>/get-ranges-with-existing-segment-data",
    headers={"Authorization": "Bearer <api key>"},
    json={
        "bounds": {
            "start": {"seconds": 1, "nanos": 1},
            "end": {"seconds": 1, "nanos": 1},
        },
    },
)
response.raise_for_status()
print(response.json())
import httpx

response = httpx.post(
    "https://api.gov.nominal.io/api/video/v1/videos/<video rid>/get-ranges-with-existing-segment-data",
    headers={"Authorization": "Bearer <api key>"},
    json={
        "bounds": {
            "start": {"seconds": 1, "nanos": 1},
            "end": {"seconds": 1, "nanos": 1},
        },
    },
)
response.raise_for_status()
print(response.json())
import asyncio

import aiohttp


async def main() -> None:
    async with aiohttp.ClientSession() as session:
        async with session.post(
            "https://api.gov.nominal.io/api/video/v1/videos/<video rid>/get-ranges-with-existing-segment-data",
            headers={"Authorization": "Bearer <api key>"},
            json={
                "bounds": {
                    "start": {"seconds": 1, "nanos": 1},
                    "end": {"seconds": 1, "nanos": 1},
                },
            },
        ) as response:
            response.raise_for_status()
            print(await response.json())


asyncio.run(main())

Response: 200

{
  "fileSummaries": [
    {
      "fileRid": "<video file rid>",
      "bounds": {
        "start": {
          "seconds": 1,
          "nanos": 1
        },
        "end": {
          "seconds": 1,
          "nanos": 1
        }
      }
    }
  ]
}

Generate WHIP stream#

POST /video/v1/videos/{videoRid}/streaming/whip

Deprecated: Replaced by generateWhipStreamV2, which addresses a channel-backed live video series instead of a Video rid.

Generates a stream ID scoped to a video and returns a WHIP URL with a MediaMTX JWT and ICE servers. Enforces write permission on the video.

Path parameters

videoRid string (RID) required

​

Response

streamId string

​

whipUrl string

​

iceServers array of IceServer

​

Fields of IceServer
urls array of string

​

username string

​

credential string

​

Request

curl -X POST "https://api.gov.nominal.io/api/video/v1/videos/<video rid>/streaming/whip" \
  -H "Authorization: Bearer <api key>"
import requests

response = requests.post(
    "https://api.gov.nominal.io/api/video/v1/videos/<video rid>/streaming/whip",
    headers={"Authorization": "Bearer <api key>"},
)
response.raise_for_status()
print(response.json())
import httpx

response = httpx.post(
    "https://api.gov.nominal.io/api/video/v1/videos/<video rid>/streaming/whip",
    headers={"Authorization": "Bearer <api key>"},
)
response.raise_for_status()
print(response.json())
import asyncio

import aiohttp


async def main() -> None:
    async with aiohttp.ClientSession() as session:
        async with session.post(
            "https://api.gov.nominal.io/api/video/v1/videos/<video rid>/streaming/whip",
            headers={"Authorization": "Bearer <api key>"},
        ) as response:
            response.raise_for_status()
            print(await response.json())


asyncio.run(main())

Response: 200

{
  "streamId": "<stream id>",
  "whipUrl": "<whip url>",
  "iceServers": [
    {
      "urls": [
        "<urls>"
      ],
      "username": "<username>",
      "credential": "<credential>"
    }
  ]
}

Generate WHIP stream v2#

POST /video/v2/videos/streaming/whip

Generates a stream ID scoped to a channel-backed live video series and returns a WHIP URL with a MediaMTX JWT and ICE servers. Currently only datasource-backed dataset channels are supported.

Body

channelSeries VideoChannelSeries required

​

Set type to "dataSource".

dataSource VideoDataSourceChannel

​

Fields of VideoDataSourceChannel
dataSourceRid string required

​

channel string required

​

tags map of TagName to string

​

Set type to "asset".

asset VideoAssetChannel

​

Fields of VideoAssetChannel
assetRid string required

​

dataScopeName string required

​

channel string required

​

tags map of TagName to string

​

Response

streamId string

​

whipUrl string

​

iceServers array of IceServer

​

Fields of IceServer
urls array of string

​

username string

​

credential string

​

Request

curl -X POST "https://api.gov.nominal.io/api/video/v2/videos/streaming/whip" \
  -H "Authorization: Bearer <api key>" \
  -H "Content-Type: application/json" \
  --data '{
  "channelSeries": {
    "type": "dataSource",
    "dataSource": {
      "dataSourceRid": "<data source rid>",
      "channel": "<channel>"
    }
  }
}'
import requests

response = requests.post(
    "https://api.gov.nominal.io/api/video/v2/videos/streaming/whip",
    headers={"Authorization": "Bearer <api key>"},
    json={
        "channelSeries": {
            "type": "dataSource",
            "dataSource": {"dataSourceRid": "<data source rid>", "channel": "<channel>"},
        },
    },
)
response.raise_for_status()
print(response.json())
import httpx

response = httpx.post(
    "https://api.gov.nominal.io/api/video/v2/videos/streaming/whip",
    headers={"Authorization": "Bearer <api key>"},
    json={
        "channelSeries": {
            "type": "dataSource",
            "dataSource": {"dataSourceRid": "<data source rid>", "channel": "<channel>"},
        },
    },
)
response.raise_for_status()
print(response.json())
import asyncio

import aiohttp


async def main() -> None:
    async with aiohttp.ClientSession() as session:
        async with session.post(
            "https://api.gov.nominal.io/api/video/v2/videos/streaming/whip",
            headers={"Authorization": "Bearer <api key>"},
            json={
                "channelSeries": {
                    "type": "dataSource",
                    "dataSource": {
                        "dataSourceRid": "<data source rid>",
                        "channel": "<channel>",
                    },
                },
            },
        ) as response:
            response.raise_for_status()
            print(await response.json())


asyncio.run(main())

Response: 200

{
  "streamId": "<stream id>",
  "whipUrl": "<whip url>",
  "iceServers": [
    {
      "urls": [
        "<urls>"
      ],
      "username": "<username>",
      "credential": "<credential>"
    }
  ]
}

Generate WHEP stream#

POST /video/v1/videos/{videoRid}/streaming/whep

Deprecated: Replaced by generateWhepStreamV2, which addresses a channel-backed live video series instead of a Video rid.

Returns WHEP URL, ICE servers, and token for playing back the active stream. Returns empty if there is no active stream. Enforces read permission on the video.

Path parameters

videoRid string (RID) required

​

Response

whepUrl string

​

iceServers array of IceServer

​

Fields of IceServer
urls array of string

​

username string

​

credential string

​

token string

​

When there is nothing to return, the response is HTTP 204 with no body.

Request

curl -X POST "https://api.gov.nominal.io/api/video/v1/videos/<video rid>/streaming/whep" \
  -H "Authorization: Bearer <api key>"
import requests

response = requests.post(
    "https://api.gov.nominal.io/api/video/v1/videos/<video rid>/streaming/whep",
    headers={"Authorization": "Bearer <api key>"},
)
response.raise_for_status()
print(response.json())
import httpx

response = httpx.post(
    "https://api.gov.nominal.io/api/video/v1/videos/<video rid>/streaming/whep",
    headers={"Authorization": "Bearer <api key>"},
)
response.raise_for_status()
print(response.json())
import asyncio

import aiohttp


async def main() -> None:
    async with aiohttp.ClientSession() as session:
        async with session.post(
            "https://api.gov.nominal.io/api/video/v1/videos/<video rid>/streaming/whep",
            headers={"Authorization": "Bearer <api key>"},
        ) as response:
            response.raise_for_status()
            print(await response.json())


asyncio.run(main())

Response: 200

{
  "whepUrl": "<whep url>",
  "iceServers": [
    {
      "urls": [
        "<urls>"
      ],
      "username": "<username>",
      "credential": "<credential>"
    }
  ],
  "token": "<token>"
}

Generate WHEP stream v2#

POST /video/v2/videos/streaming/whep

Returns WHEP URL, ICE servers, and token for playing back the active channel-backed live video stream. Returns empty if there is no active stream. Currently only datasource-backed dataset channels are supported.

Body

channelSeries VideoChannelSeries required

​

Set type to "dataSource".

dataSource VideoDataSourceChannel

​

Fields of VideoDataSourceChannel
dataSourceRid string required

​

channel string required

​

tags map of TagName to string

​

Set type to "asset".

asset VideoAssetChannel

​

Fields of VideoAssetChannel
assetRid string required

​

dataScopeName string required

​

channel string required

​

tags map of TagName to string

​

Response

whepUrl string

​

iceServers array of IceServer

​

Fields of IceServer
urls array of string

​

username string

​

credential string

​

token string

​

When there is nothing to return, the response is HTTP 204 with no body.

Request

curl -X POST "https://api.gov.nominal.io/api/video/v2/videos/streaming/whep" \
  -H "Authorization: Bearer <api key>" \
  -H "Content-Type: application/json" \
  --data '{
  "channelSeries": {
    "type": "dataSource",
    "dataSource": {
      "dataSourceRid": "<data source rid>",
      "channel": "<channel>"
    }
  }
}'
import requests

response = requests.post(
    "https://api.gov.nominal.io/api/video/v2/videos/streaming/whep",
    headers={"Authorization": "Bearer <api key>"},
    json={
        "channelSeries": {
            "type": "dataSource",
            "dataSource": {"dataSourceRid": "<data source rid>", "channel": "<channel>"},
        },
    },
)
response.raise_for_status()
print(response.json())
import httpx

response = httpx.post(
    "https://api.gov.nominal.io/api/video/v2/videos/streaming/whep",
    headers={"Authorization": "Bearer <api key>"},
    json={
        "channelSeries": {
            "type": "dataSource",
            "dataSource": {"dataSourceRid": "<data source rid>", "channel": "<channel>"},
        },
    },
)
response.raise_for_status()
print(response.json())
import asyncio

import aiohttp


async def main() -> None:
    async with aiohttp.ClientSession() as session:
        async with session.post(
            "https://api.gov.nominal.io/api/video/v2/videos/streaming/whep",
            headers={"Authorization": "Bearer <api key>"},
            json={
                "channelSeries": {
                    "type": "dataSource",
                    "dataSource": {
                        "dataSourceRid": "<data source rid>",
                        "channel": "<channel>",
                    },
                },
            },
        ) as response:
            response.raise_for_status()
            print(await response.json())


asyncio.run(main())

Response: 200

{
  "whepUrl": "<whep url>",
  "iceServers": [
    {
      "urls": [
        "<urls>"
      ],
      "username": "<username>",
      "credential": "<credential>"
    }
  ],
  "token": "<token>"
}

Get stream#

GET /video/v1/videos/{videoRid}/streaming/streams/{streamId}

Returns stream session metadata for a given stream ID scoped to the video. Enforces read permission on the video.

Path parameters

videoRid string (RID) required

​

streamId string required

​

Response

streamId string

​

videoRid string (RID)

​

streamStatus string

​

start string (date-time)

​

end string (date-time)

​

createdAt string (date-time)

​

updatedAt string (date-time)

​

When there is nothing to return, the response is HTTP 204 with no body.

Request

curl "https://api.gov.nominal.io/api/video/v1/videos/<video rid>/streaming/streams/<stream id>" \
  -H "Authorization: Bearer <api key>"
import requests

response = requests.get(
    "https://api.gov.nominal.io/api/video/v1/videos/<video rid>/streaming/streams/<stream id>",
    headers={"Authorization": "Bearer <api key>"},
)
response.raise_for_status()
print(response.json())
import httpx

response = httpx.get(
    "https://api.gov.nominal.io/api/video/v1/videos/<video rid>/streaming/streams/<stream id>",
    headers={"Authorization": "Bearer <api key>"},
)
response.raise_for_status()
print(response.json())
import asyncio

import aiohttp


async def main() -> None:
    async with aiohttp.ClientSession() as session:
        async with session.get(
            "https://api.gov.nominal.io/api/video/v1/videos/<video rid>/streaming/streams/<stream id>",
            headers={"Authorization": "Bearer <api key>"},
        ) as response:
            response.raise_for_status()
            print(await response.json())


asyncio.run(main())

Response: 200

{
  "streamId": "<stream id>",
  "videoRid": "<video rid>",
  "streamStatus": "<stream status>",
  "start": "2026-01-01T00:00:00Z",
  "end": "2026-01-01T00:00:00Z",
  "createdAt": "2026-01-01T00:00:00Z",
  "updatedAt": "2026-01-01T00:00:00Z"
}

Get streams in bounds#

POST /video/v1/videos/{videoRid}/streaming/streams-in-bounds

Deprecated: Replaced by getStreamsInBoundsV2, which addresses a channel-backed live video series instead of a Video rid.

Returns all stream sessions for a video that overlap with the specified time bounds. A stream overlaps if there is any intersection between its [start, end] interval and the provided bounds. Enforces read permission on the video.

Path parameters

videoRid string (RID) required

​

Body

bounds Bounds required

​

Fields of Bounds
start Timestamp required

​

Fields of Timestamp
seconds integer (int64) required

​

nanos integer (int64) required

​

end Timestamp required

​

pageSize integer

Defaults to 100. Will throw if larger than 1_000.

token string

​

Response

streams array of VideoStream

​

Fields of VideoStream
streamId string

​

videoRid string (RID)

​

streamStatus string

​

start string (date-time)

​

end string (date-time)

​

createdAt string (date-time)

​

updatedAt string (date-time)

​

nextPageToken string

​

Request

curl -X POST "https://api.gov.nominal.io/api/video/v1/videos/<video rid>/streaming/streams-in-bounds" \
  -H "Authorization: Bearer <api key>" \
  -H "Content-Type: application/json" \
  --data '{
  "bounds": {
    "start": {
      "seconds": 1,
      "nanos": 1
    },
    "end": {
      "seconds": 1,
      "nanos": 1
    }
  }
}'
import requests

response = requests.post(
    "https://api.gov.nominal.io/api/video/v1/videos/<video rid>/streaming/streams-in-bounds",
    headers={"Authorization": "Bearer <api key>"},
    json={
        "bounds": {
            "start": {"seconds": 1, "nanos": 1},
            "end": {"seconds": 1, "nanos": 1},
        },
    },
)
response.raise_for_status()
print(response.json())
import httpx

response = httpx.post(
    "https://api.gov.nominal.io/api/video/v1/videos/<video rid>/streaming/streams-in-bounds",
    headers={"Authorization": "Bearer <api key>"},
    json={
        "bounds": {
            "start": {"seconds": 1, "nanos": 1},
            "end": {"seconds": 1, "nanos": 1},
        },
    },
)
response.raise_for_status()
print(response.json())
import asyncio

import aiohttp


async def main() -> None:
    async with aiohttp.ClientSession() as session:
        async with session.post(
            "https://api.gov.nominal.io/api/video/v1/videos/<video rid>/streaming/streams-in-bounds",
            headers={"Authorization": "Bearer <api key>"},
            json={
                "bounds": {
                    "start": {"seconds": 1, "nanos": 1},
                    "end": {"seconds": 1, "nanos": 1},
                },
            },
        ) as response:
            response.raise_for_status()
            print(await response.json())


asyncio.run(main())

Response: 200

{
  "streams": [
    {
      "streamId": "<stream id>",
      "videoRid": "<video rid>",
      "streamStatus": "<stream status>",
      "start": "2026-01-01T00:00:00Z",
      "end": "2026-01-01T00:00:00Z",
      "createdAt": "2026-01-01T00:00:00Z",
      "updatedAt": "2026-01-01T00:00:00Z"
    }
  ],
  "nextPageToken": "<token>"
}

Get streams in bounds v2#

POST /video/v2/videos/streaming/streams-in-bounds

Returns all channel-backed stream sessions for a dataset/channel that overlap with the specified time bounds. A stream overlaps if there is any intersection between its [start, end] interval and the provided bounds. Enforces read metadata permission on the dataset.

Body

channelSeries VideoChannelSeries required

​

Set type to "dataSource".

dataSource VideoDataSourceChannel

​

Fields of VideoDataSourceChannel
dataSourceRid string required

​

channel string required

​

tags map of TagName to string

​

Set type to "asset".

asset VideoAssetChannel

​

Fields of VideoAssetChannel
assetRid string required

​

dataScopeName string required

​

channel string required

​

tags map of TagName to string

​

bounds Bounds required

​

Fields of Bounds
start Timestamp required

​

Fields of Timestamp
seconds integer (int64) required

​

nanos integer (int64) required

​

end Timestamp required

​

pageSize integer

Defaults to 100. Will throw if larger than 1_000.

token string

​

Response

streams array of VideoStreamV2

​

Fields of VideoStreamV2
streamId string

​

streamStatus string

​

createdAt string (date-time)

​

updatedAt string (date-time)

​

start string (date-time)

​

end string (date-time)

​

nextPageToken string

​

Request

curl -X POST "https://api.gov.nominal.io/api/video/v2/videos/streaming/streams-in-bounds" \
  -H "Authorization: Bearer <api key>" \
  -H "Content-Type: application/json" \
  --data '{
  "channelSeries": {
    "type": "dataSource",
    "dataSource": {
      "dataSourceRid": "<data source rid>",
      "channel": "<channel>"
    }
  },
  "bounds": {
    "start": {
      "seconds": 1,
      "nanos": 1
    },
    "end": {
      "seconds": 1,
      "nanos": 1
    }
  }
}'
import requests

response = requests.post(
    "https://api.gov.nominal.io/api/video/v2/videos/streaming/streams-in-bounds",
    headers={"Authorization": "Bearer <api key>"},
    json={
        "channelSeries": {
            "type": "dataSource",
            "dataSource": {"dataSourceRid": "<data source rid>", "channel": "<channel>"},
        },
        "bounds": {
            "start": {"seconds": 1, "nanos": 1},
            "end": {"seconds": 1, "nanos": 1},
        },
    },
)
response.raise_for_status()
print(response.json())
import httpx

response = httpx.post(
    "https://api.gov.nominal.io/api/video/v2/videos/streaming/streams-in-bounds",
    headers={"Authorization": "Bearer <api key>"},
    json={
        "channelSeries": {
            "type": "dataSource",
            "dataSource": {"dataSourceRid": "<data source rid>", "channel": "<channel>"},
        },
        "bounds": {
            "start": {"seconds": 1, "nanos": 1},
            "end": {"seconds": 1, "nanos": 1},
        },
    },
)
response.raise_for_status()
print(response.json())
import asyncio

import aiohttp


async def main() -> None:
    async with aiohttp.ClientSession() as session:
        async with session.post(
            "https://api.gov.nominal.io/api/video/v2/videos/streaming/streams-in-bounds",
            headers={"Authorization": "Bearer <api key>"},
            json={
                "channelSeries": {
                    "type": "dataSource",
                    "dataSource": {
                        "dataSourceRid": "<data source rid>",
                        "channel": "<channel>",
                    },
                },
                "bounds": {
                    "start": {"seconds": 1, "nanos": 1},
                    "end": {"seconds": 1, "nanos": 1},
                },
            },
        ) as response:
            response.raise_for_status()
            print(await response.json())


asyncio.run(main())

Response: 200

{
  "streams": [
    {
      "streamId": "<stream id>",
      "streamStatus": "<stream status>",
      "createdAt": "2026-01-01T00:00:00Z",
      "updatedAt": "2026-01-01T00:00:00Z",
      "start": "2026-01-01T00:00:00Z",
      "end": "2026-01-01T00:00:00Z"
    }
  ],
  "nextPageToken": "<token>"
}

List video channel dataset files#

POST /video/v2/videos/channel-dataset-files

Returns the dataset files backing a video channel (identified by channel + tags), ordered by start timestamp ascending and paginated. Each entry carries the min/max absolute timestamps the file contributes to the channel. Optionally filtered by time bounds. Streamed sessions are not included; use getStreamsInBoundsV2 for those. Enforces read metadata permission on the datasource.

Body

channelSeries VideoChannelSeries required

​

Set type to "dataSource".

dataSource VideoDataSourceChannel

​

Fields of VideoDataSourceChannel
dataSourceRid string required

​

channel string required

​

tags map of TagName to string

​

Set type to "asset".

asset VideoAssetChannel

​

Fields of VideoAssetChannel
assetRid string required

​

dataScopeName string required

​

channel string required

​

tags map of TagName to string

​

bounds Bounds

​

Fields of Bounds
start Timestamp required

​

Fields of Timestamp
seconds integer (int64) required

​

nanos integer (int64) required

​

end Timestamp required

​

pageSize integer

Defaults to 100. Will throw if larger than 1_000.

token string

​

Response

datasetFiles array of VideoChannelDatasetFile

​

Fields of VideoChannelDatasetFile
datasetFileId string (UUID)

​

start Timestamp

​

Fields of Timestamp
seconds integer (int64)

​

nanos integer (int64)

​

end Timestamp

​

nextPageToken string

​

Request

curl -X POST "https://api.gov.nominal.io/api/video/v2/videos/channel-dataset-files" \
  -H "Authorization: Bearer <api key>" \
  -H "Content-Type: application/json" \
  --data '{
  "channelSeries": {
    "type": "dataSource",
    "dataSource": {
      "dataSourceRid": "<data source rid>",
      "channel": "<channel>"
    }
  }
}'
import requests

response = requests.post(
    "https://api.gov.nominal.io/api/video/v2/videos/channel-dataset-files",
    headers={"Authorization": "Bearer <api key>"},
    json={
        "channelSeries": {
            "type": "dataSource",
            "dataSource": {"dataSourceRid": "<data source rid>", "channel": "<channel>"},
        },
    },
)
response.raise_for_status()
print(response.json())
import httpx

response = httpx.post(
    "https://api.gov.nominal.io/api/video/v2/videos/channel-dataset-files",
    headers={"Authorization": "Bearer <api key>"},
    json={
        "channelSeries": {
            "type": "dataSource",
            "dataSource": {"dataSourceRid": "<data source rid>", "channel": "<channel>"},
        },
    },
)
response.raise_for_status()
print(response.json())
import asyncio

import aiohttp


async def main() -> None:
    async with aiohttp.ClientSession() as session:
        async with session.post(
            "https://api.gov.nominal.io/api/video/v2/videos/channel-dataset-files",
            headers={"Authorization": "Bearer <api key>"},
            json={
                "channelSeries": {
                    "type": "dataSource",
                    "dataSource": {
                        "dataSourceRid": "<data source rid>",
                        "channel": "<channel>",
                    },
                },
            },
        ) as response:
            response.raise_for_status()
            print(await response.json())


asyncio.run(main())

Response: 200

{
  "datasetFiles": [
    {
      "datasetFileId": "<dataset file id>",
      "start": {
        "seconds": 1,
        "nanos": 1
      },
      "end": {
        "seconds": 1,
        "nanos": 1
      }
    }
  ],
  "nextPageToken": "<token>"
}

Batch update video channel dataset files#

POST /video/v2/videos/channel-dataset-files/batch-update

Updates one or more video dataset files in a channel in a single transaction. Each update may set a new absolute start timestamp (segments shifted so the earliest starts at the given timestamp), a scale parameter (frame timestamps rescaled around the file’s start), and/or a new title (file name). If a resulting layout would overlap segments of another file in the channel, no files are updated and VIDEO_SEGMENT_CONFLICT is thrown (all-or-nothing). Returns the updated files with their new bounds and persists those bounds to the corresponding Catalog DatasetFile. Currently only datasource-backed dataset channels are supported. Enforces write data permission on the datasource.

Body

channelSeries VideoChannelSeries

​

Set type to "dataSource".

dataSource VideoDataSourceChannel

​

Fields of VideoDataSourceChannel
dataSourceRid string required

​

channel string required

​

tags map of TagName to string

​

Set type to "asset".

asset VideoAssetChannel

​

Fields of VideoAssetChannel
assetRid string required

​

dataScopeName string required

​

channel string required

​

tags map of TagName to string

​

datasetRid string (RID)

The dataset owning the files to update. Every requested file must belong to this dataset and be a video file (back a video series); enforces write data permission on the dataset.

updates array of VideoChannelDatasetFileUpdate

​

Fields of VideoChannelDatasetFileUpdate
datasetFileId string (UUID) required

​

start Timestamp

New absolute start timestamp for the file. The file’s earliest segment is shifted to this timestamp and every other segment in the file is shifted by the same offset.

Fields of Timestamp
seconds integer (int64) required

​

nanos integer (int64) required

​

title string

New name (title) for the dataset file.

scaleParameter ScaleParameter

Rescales the file’s frame timestamps around its start (e.g. a corrected true frame rate, an absolute ending timestamp, or a direct scale factor). The file’s cached segment metadata (scale factor, frame rate) is recomputed.

Set type to "trueFrameRate".

trueFrameRate number

​

Set type to "endingTimestamp".

endingTimestamp Timestamp

​

Set type to "scaleFactor".

scaleFactor number

the scale factor can be used to calculate whether media duration differs from a video’s | real duration, and if so, the true frame rate of the camera. The video time will thus be scaled | by the ratio of the real duration to media duration, or media frame rate to true frame rate.

Response

datasetFiles array of VideoChannelDatasetFile

​

Fields of VideoChannelDatasetFile
datasetFileId string (UUID)

​

start Timestamp

​

Fields of Timestamp
seconds integer (int64)

​

nanos integer (int64)

​

end Timestamp

​

Request

curl -X POST "https://api.gov.nominal.io/api/video/v2/videos/channel-dataset-files/batch-update" \
  -H "Authorization: Bearer <api key>" \
  -H "Content-Type: application/json" \
  --data '{
  "channelSeries": {
    "type": "dataSource",
    "dataSource": {
      "dataSourceRid": "<data source rid>",
      "channel": "<channel>"
    }
  },
  "datasetRid": "<dataset rid>",
  "updates": [
    {
      "datasetFileId": "<dataset file id>"
    }
  ]
}'
import requests

response = requests.post(
    "https://api.gov.nominal.io/api/video/v2/videos/channel-dataset-files/batch-update",
    headers={"Authorization": "Bearer <api key>"},
    json={
        "channelSeries": {
            "type": "dataSource",
            "dataSource": {"dataSourceRid": "<data source rid>", "channel": "<channel>"},
        },
        "datasetRid": "<dataset rid>",
        "updates": [{"datasetFileId": "<dataset file id>"}],
    },
)
response.raise_for_status()
print(response.json())
import httpx

response = httpx.post(
    "https://api.gov.nominal.io/api/video/v2/videos/channel-dataset-files/batch-update",
    headers={"Authorization": "Bearer <api key>"},
    json={
        "channelSeries": {
            "type": "dataSource",
            "dataSource": {"dataSourceRid": "<data source rid>", "channel": "<channel>"},
        },
        "datasetRid": "<dataset rid>",
        "updates": [{"datasetFileId": "<dataset file id>"}],
    },
)
response.raise_for_status()
print(response.json())
import asyncio

import aiohttp


async def main() -> None:
    async with aiohttp.ClientSession() as session:
        async with session.post(
            "https://api.gov.nominal.io/api/video/v2/videos/channel-dataset-files/batch-update",
            headers={"Authorization": "Bearer <api key>"},
            json={
                "channelSeries": {
                    "type": "dataSource",
                    "dataSource": {
                        "dataSourceRid": "<data source rid>",
                        "channel": "<channel>",
                    },
                },
                "datasetRid": "<dataset rid>",
                "updates": [{"datasetFileId": "<dataset file id>"}],
            },
        ) as response:
            response.raise_for_status()
            print(await response.json())


asyncio.run(main())

Response: 200

{
  "datasetFiles": [
    {
      "datasetFileId": "<dataset file id>",
      "start": {
        "seconds": 1,
        "nanos": 1
      },
      "end": {
        "seconds": 1,
        "nanos": 1
      }
    }
  ]
}

End stream#

POST /video/v1/videos/{videoRid}/streaming/end

Deprecated: Replaced by endStreamV2, which addresses a channel-backed live video series instead of a Video rid.

Marks the active stream session as ended for the video. Throws VIDEO_NOT_FOUND if no active stream exists. Enforces write permission on the video.

Path parameters

videoRid string (RID) required

​

Response

streamId string

​

endedAt Timestamp

​

Fields of Timestamp
seconds integer (int64)

​

nanos integer (int64)

​

Request

curl -X POST "https://api.gov.nominal.io/api/video/v1/videos/<video rid>/streaming/end" \
  -H "Authorization: Bearer <api key>"
import requests

response = requests.post(
    "https://api.gov.nominal.io/api/video/v1/videos/<video rid>/streaming/end",
    headers={"Authorization": "Bearer <api key>"},
)
response.raise_for_status()
print(response.json())
import httpx

response = httpx.post(
    "https://api.gov.nominal.io/api/video/v1/videos/<video rid>/streaming/end",
    headers={"Authorization": "Bearer <api key>"},
)
response.raise_for_status()
print(response.json())
import asyncio

import aiohttp


async def main() -> None:
    async with aiohttp.ClientSession() as session:
        async with session.post(
            "https://api.gov.nominal.io/api/video/v1/videos/<video rid>/streaming/end",
            headers={"Authorization": "Bearer <api key>"},
        ) as response:
            response.raise_for_status()
            print(await response.json())


asyncio.run(main())

Response: 200

{
  "streamId": "<stream id>",
  "endedAt": {
    "seconds": 1,
    "nanos": 1
  }
}

End stream v2#

POST /video/v2/videos/streaming/end

Marks the active stream session as ended for a channel-backed live video series. Returns empty when no active stream exists, so a publisher-disconnect hook that fires more than once — or races the reaper — is a no-op rather than an error. Currently only datasource-backed dataset channels are supported. Enforces write permission on the data source.

Body

channelSeries VideoChannelSeries required

​

Set type to "dataSource".

dataSource VideoDataSourceChannel

​

Fields of VideoDataSourceChannel
dataSourceRid string required

​

channel string required

​

tags map of TagName to string

​

Set type to "asset".

asset VideoAssetChannel

​

Fields of VideoAssetChannel
assetRid string required

​

dataScopeName string required

​

channel string required

​

tags map of TagName to string

​

Response

streamId string

​

endedAt Timestamp

​

Fields of Timestamp
seconds integer (int64)

​

nanos integer (int64)

​

When there is nothing to return, the response is HTTP 204 with no body.

Request

curl -X POST "https://api.gov.nominal.io/api/video/v2/videos/streaming/end" \
  -H "Authorization: Bearer <api key>" \
  -H "Content-Type: application/json" \
  --data '{
  "channelSeries": {
    "type": "dataSource",
    "dataSource": {
      "dataSourceRid": "<data source rid>",
      "channel": "<channel>"
    }
  }
}'
import requests

response = requests.post(
    "https://api.gov.nominal.io/api/video/v2/videos/streaming/end",
    headers={"Authorization": "Bearer <api key>"},
    json={
        "channelSeries": {
            "type": "dataSource",
            "dataSource": {"dataSourceRid": "<data source rid>", "channel": "<channel>"},
        },
    },
)
response.raise_for_status()
print(response.json())
import httpx

response = httpx.post(
    "https://api.gov.nominal.io/api/video/v2/videos/streaming/end",
    headers={"Authorization": "Bearer <api key>"},
    json={
        "channelSeries": {
            "type": "dataSource",
            "dataSource": {"dataSourceRid": "<data source rid>", "channel": "<channel>"},
        },
    },
)
response.raise_for_status()
print(response.json())
import asyncio

import aiohttp


async def main() -> None:
    async with aiohttp.ClientSession() as session:
        async with session.post(
            "https://api.gov.nominal.io/api/video/v2/videos/streaming/end",
            headers={"Authorization": "Bearer <api key>"},
            json={
                "channelSeries": {
                    "type": "dataSource",
                    "dataSource": {
                        "dataSourceRid": "<data source rid>",
                        "channel": "<channel>",
                    },
                },
            },
        ) as response:
            response.raise_for_status()
            print(await response.json())


asyncio.run(main())

Response: 200

{
  "streamId": "<stream id>",
  "endedAt": {
    "seconds": 1,
    "nanos": 1
  }
}

Upload segment from media mtx#

POST /video/v1/segment/upload

MediaMTX segment upload endpoint. Receives video segments from MediaMTX hooks. Validates JWT and logs session. Future: create video segments from uploaded files.

Query parameters

streamPath string required

MTX_PATH from MediaMTX indicating the stream path

filePath string required

File path of the uploaded segment

duration string required

MTX_SEGMENT_DURATION from MediaMTX in seconds

minTimestampSeconds integer (int64) required

Minimum timestamp seconds since epoch

minTimestampNanos integer (int64) required

Nanosecond offset (0-999999999)

Headers

Content-Length integer (int64) required

Size of the segment in bytes from Content-Length header

Body: application/octet-stream

The body is the raw bytes.

Response

No content (HTTP 204).

Request

curl -X POST "https://api.gov.nominal.io/api/video/v1/segment/upload?streamPath=<stream path>&filePath=<file path>&duration=<duration>&minTimestampSeconds=1&minTimestampNanos=1" \
  -H "Authorization: Bearer <api key>" \
  -H "Content-Length: 1" \
  -H "Content-Type: application/octet-stream" \
  --data-binary "@<file>"
from pathlib import Path

import requests

response = requests.post(
    "https://api.gov.nominal.io/api/video/v1/segment/upload?streamPath=<stream path>&filePath=<file path>&duration=<duration>&minTimestampSeconds=1&minTimestampNanos=1",
    headers={
        "Authorization": "Bearer <api key>",
        "Content-Length": "1",
        "Content-Type": "application/octet-stream",
    },
    data=Path("<file>").read_bytes(),
)
response.raise_for_status()
from pathlib import Path

import httpx

response = httpx.post(
    "https://api.gov.nominal.io/api/video/v1/segment/upload?streamPath=<stream path>&filePath=<file path>&duration=<duration>&minTimestampSeconds=1&minTimestampNanos=1",
    headers={
        "Authorization": "Bearer <api key>",
        "Content-Length": "1",
        "Content-Type": "application/octet-stream",
    },
    content=Path("<file>").read_bytes(),
)
response.raise_for_status()
import asyncio
from pathlib import Path

import aiohttp


async def main() -> None:
    async with aiohttp.ClientSession() as session:
        async with session.post(
            "https://api.gov.nominal.io/api/video/v1/segment/upload?streamPath=<stream path>&filePath=<file path>&duration=<duration>&minTimestampSeconds=1&minTimestampNanos=1",
            headers={
                "Authorization": "Bearer <api key>",
                "Content-Length": "1",
                "Content-Type": "application/octet-stream",
            },
            data=Path("<file>").read_bytes(),
        ) as response:
            response.raise_for_status()


asyncio.run(main())

Response: 204

No content.

Types#

ArchivedStatus#

NOT_ARCHIVED

​

ARCHIVED

​

Bounds#

start Timestamp required

​

end Timestamp required

​

DetailedIngestStatus#

Set type to the name of one of the other fields, and set only that field.

success SuccessIngestStatus

​

error ErrorIngestStatus

​

inProgress number

A number between 0 and 1 representing percentage progress.

Empty#

An empty JSON object, {}.

ErrorIngestStatus#

errors array of IngestError

​

FileSummary#

fileRid string (RID) required

​

bounds Bounds required

​

Handle#

Set type to the name of one of the other fields, and set only that field.

s3 string

​

IceServer#

WebRTC ICE server configuration

urls array of string

​

username string

​

credential string

​

IngestError#

errorType string required

​

message string required

​

errorInstanceId string

​

IngestStatus#

SUCCEEDED

​

FAILED

​

IN_PROGRESS

​

McapChannelLocator#

Locator for a channel in an mcap file. Channel name is not guaranteed to be unique, so channel ID should be used for mcap files with duplicate channel names.

Set type to the name of one of the other fields, and set only that field.

topic string

​

id integer

​

McapTimestampManifest#

Timestamps are derived from the mcap file containing the video frames.

mcapChannelLocator McapChannelLocator required

​

NoTimestampManifest#

these values will not be updated after ingest time, to allow for resetting. The updated values are stored implicitly through the segment timestamps.

startingTimestamp Timestamp required

Specifies the original starting timestamp of the video.

scaleParameter ScaleParameter

A field that specifies that the frame rate of the video does not match the frame rate of the camera | i.e. a slowed down or sped up video. Can specify either the camera frame rate or the absolute end time.

Property#

name string required

​

value string required

​

ScaleParameter#

Set type to the name of one of the other fields, and set only that field.

trueFrameRate number

​

endingTimestamp Timestamp

​

scaleFactor number

the scale factor can be used to calculate whether media duration differs from a video’s | real duration, and if so, the true frame rate of the camera. The video time will thus be scaled | by the ratio of the real duration to media duration, or media frame rate to true frame rate.

SearchVideosQuery#

Set type to the name of one of the other fields, and set only that field.

searchText string

​

label string

​

property Property

​

and array of SearchVideosQuery

​

or array of SearchVideosQuery

​

ingestStatus IngestStatus

​

workspace string (RID)

​

SegmentSummary#

Bounding timestamps for the frames within a segment. For non-frame-mapped videos, the min and max media timestamps will be empty.

minAbsoluteTimestamp Timestamp required

​

maxAbsoluteTimestamp Timestamp required

​

minMediaTimestamp number required

​

maxMediaTimestamp number required

​

SegmentSummaryV2#

Bounding timestamps for the frames within a segment. Includes datasetFileId for V2 channel-based API.

datasetFileId string (UUID)

The dataset file ID that this segment belongs to.

minAbsoluteTimestamp Timestamp required

​

maxAbsoluteTimestamp Timestamp required

​

minMediaTimestamp number required

​

maxMediaTimestamp number required

​

SegmentTimestamps#

A video segment will either contain timestamps or timestamp mappings depending on whether it is intended to be frame-mapped. Without a frame-timestamp mapping manifest file, a list of absolute timestamps will be automatically assigned to each segment based on media timestamps.. Otherwise, media timestamps will be extracted and mapped to those in the provided manifest.

Set type to the name of one of the other fields, and set only that field.

timestampMappings TimestampMappings

​

SortField#

CREATED_AT

​

SortOptions#

isDescending boolean required

​

field SortField required

​

SuccessIngestStatus#

An empty JSON object, {}.

Timestamp#

Deprecated for new APIs. Use google.protobuf.Timestamp for absolute instants in proto APIs.

This legacy nanosecond precision timestamp type is represented by an epoch time in seconds and a nanosecond offset. The nanosecond offset is from the start of the epoch second, so must be less than 1 billion.

seconds integer (int64) required

​

nanos integer (int64) required

​

TimestampMappings#

contains 2 equal-length lists, which contain the video media time and user-provided absolute time for the frame at each index. Enables frame-mapping on the front-end.

mediaTimestamps array of number

​

absoluteTimestamps array of Timestamp

​

Video#

rid string (RID) required

​

title string required

​

description string

​

labels array of string

​

properties map of PropertyName to string

​

createdBy string (RID) required

​

createdAt string (date-time) required

​

isArchived boolean required

​

originMetadata VideoOriginMetadata deprecated

Deprecated: deprecated in favor of per-file VideoFileOriginMetadata. Will be removed after April 15th.

allSegmentsMetadata VideoAllSegmentsMetadata

​

VideoAllSegmentsMetadata#

rid string (RID) required

​

numFrames integer required

​

numSegments integer required

​

scaleFactor number

deprecated, in favor of per-file VideoFileSegmentsMetadata scaleFactor. Will be removed after April 15th.

minAbsoluteTimestamp Timestamp required

​

maxAbsoluteTimestamp Timestamp required

the timestamp corresponding to absolute starting timestamp plus absolute duration of the video.

mediaDurationSeconds number required

​

mediaFrameRate number required

The average media frame rate (FPS) of the video calculated as total frames / duration in seconds.

minTimestamp Timestamp

deprecated. Will be removed after April 15th.

maxTimestamp Timestamp

deprecated. Will be removed after April 15th.

durationSeconds number

deprecated. Will be removed after April 15th.

frameRate number

deprecated. Will be removed after April 15th.

VideoAssetChannel#

Reference a video channel via an Asset’s data scope

assetRid string required

​

dataScopeName string required

​

channel string required

​

tags map of TagName to string

​

VideoChannelDatasetFile#

A dataset file backing a video channel, with the min and max absolute timestamps of the segments it contributes to the channel.

datasetFileId string (UUID) required

​

start Timestamp required

​

end Timestamp required

​

VideoChannelDatasetFileUpdate#

An update to apply to a single video dataset file backing a channel. Only the provided fields are changed; at least one must be set. When both start and scaleParameter are set, the file is rescaled first (around its current start) and then shifted to the new start.

datasetFileId string (UUID) required

​

start Timestamp

New absolute start timestamp for the file. The file’s earliest segment is shifted to this timestamp and every other segment in the file is shifted by the same offset.

title string

New name (title) for the dataset file.

scaleParameter ScaleParameter

Rescales the file’s frame timestamps around its start (e.g. a corrected true frame rate, an absolute ending timestamp, or a direct scale factor). The file’s cached segment metadata (scale factor, frame rate) is recomputed.

VideoChannelSeries#

Union type for referencing a video channel. Allows querying video data via datasource/channel, asset data scopes, or run data scopes.

Set type to the name of one of the other fields, and set only that field.

dataSource VideoDataSourceChannel

​

asset VideoAssetChannel

​

VideoDataSourceChannel#

Reference a video channel directly from a datasource/dataset

dataSourceRid string required

​

channel string required

​

tags map of TagName to string

​

VideoFileIngestStatus#

Set type to the name of one of the other fields, and set only that field.

success SuccessIngestStatus

​

error IngestError

​

inProgress Empty

​

VideoIngestStatus#

Set type to the name of one of the other fields, and set only that field.

ready Empty

​

inProgress Empty

​

error Empty

​

VideoOriginMetadata#

videoSources array of Handle deprecated

Deprecated: deprecated in favor of per-file VideoFileOriginMetadata. Will be removed after April 15th.

timestampManifest VideoTimestampManifest required deprecated

Deprecated: deprecated in favor of per-file VideoFileOriginMetadata. Will be removed after April 15th.

VideoStream#

Metadata for a single video stream session.

streamId string required

​

videoRid string (RID) required

​

streamStatus string required

​

start string (date-time)

​

end string (date-time)

​

createdAt string (date-time) required

​

updatedAt string (date-time) required

​

VideoStreamV2#

Metadata for a single channel-backed video stream session.

streamId string required

​

streamStatus string required

​

createdAt string (date-time) required

​

updatedAt string (date-time) required

​

start string (date-time)

​

end string (date-time)

​

VideoTimestampManifest#

Set type to the name of one of the other fields, and set only that field.

mcap McapTimestampManifest

​

s3paths array of string

​

noManifest NoTimestampManifest

​

Page design based on Scalar, MIT License.