Skip to main content

library.

The library. endpoints under /api/v1/library manage media of any kind: videos, programmes, clips, podcasts, music or not. There is no entity layer: you work on the media and its files directly.

  • Media is one piece of content. It carries a name, free-form metadata, workflow status values and the DMRNs that identify it in your systems.
  • Assets are the files of a media: video, audio, image and WebVTT subtitle files. Each asset lists the storage locations holding its file.
  • Storage lists where your files live: your organisation's deliver.media platform storage, and your own storage account when you connected one.
  • Subtitle tracks are parsed from WebVTT files, one or more versions per language.
  • Channels and timelines say which media plays when. They are the same timelines managedradio. plays out.

A media created through the API is the same media your team sees in the library. app, and the reverse.

Access​

The library. endpoints need an API key with the deliverdotmedia:library:api permission (see Authentication). API access is part of the library. Enterprise plan and of the Public API option. A request from an organisation whose plan does not include API access answers 402 with the error code plan_required.

Identify media with your own IDs​

Attach the identifier your system already uses, as a DMRN, and look the media up by it instead of storing our ids:

# Create the media with your reference
curl -X POST https://public-api.deliver.media/api/v1/library/media \
-H "Authorization: Bearer sk_..." -H "Content-Type: application/json" \
-d '{
"name": "Evening news 2026-09-28",
"metadata": { "programme": "Evening news", "season": 12 },
"reference": "dmrn:customer:mam:ch:acme:programme/EN-20260928"
}'

# Find it again later
curl "https://public-api.deliver.media/api/v1/library/media?reference=dmrn:customer:mam:ch:acme:programme/EN-20260928" \
-H "Authorization: Bearer sk_..."

A media may carry several DMRNs (add more with POST /api/v1/library/media/{id}/references), but a DMRN identifies one object only: attaching one that is already in use answers 409.

Metadata and statuses​

  • PATCH /api/v1/library/media/{id} merges metadata one top-level key at a time: keys you send replace their value, keys you leave out are kept. Values may be strings, numbers, booleans, null, nested objects or arrays.
  • PATCH /api/v1/library/media/{id}/status sets workflow states such as { "status": { "subtitles": "DONE", "legal": "PENDING" } }. The library. app shows each status type as a column and filters by it. Set a type to null to remove it.

Upload a file​

Files never pass through the API itself: you upload them straight to storage with a signed URL.

  1. Create the asset on the media. The MIME type decides the asset type (video/*, audio/*, image/*, text/vtt):

    curl -X POST https://public-api.deliver.media/api/v1/library/media/{id}/assets \
    -H "Authorization: Bearer sk_..." -H "Content-Type: application/json" \
    -d '{ "name": "evening-news.mp4", "mimeType": "video/mp4", "sizeInBytes": 734003200 }'

    The response carries an assetId and an upload target.

  2. PUT the raw file bytes (not multipart form data) to upload.url, sending every header of upload.headers, before upload.expiresOn.

  3. Confirm it with POST /api/v1/library/assets/{assetId}/confirm. The asset becomes ONLINE. A confirmed video is queued for video analysis, exactly as when it is uploaded in the library. app.

Read the file back with GET /api/v1/library/assets/{id}/download, which signs a short-lived URL. Request a fresh one each time rather than storing it. GET /api/v1/library/assets/{id} returns the asset's technical data (once the file has been probed) and its storage locations; storageId points to an entry of GET /api/v1/library/storage (it is null only for files stored before your organisation had a storage of its own).

Add subtitles​

  1. Upload the .vtt file as an asset of the media with mimeType: text/vtt, PUT it and confirm it, as above. Subtitle files are limited to 10 MiB.

  2. Create the track:

    curl -X POST https://public-api.deliver.media/api/v1/library/media/{id}/subtitles \
    -H "Authorization: Bearer sk_..." -H "Content-Type: application/json" \
    -d '{ "assetId": "…", "language": "de-CH" }'

Each upload of a language becomes a new version and the active one of that language: the version the player shows and AI AutoCut uses. Promote an older version with POST /api/v1/library/subtitles/{trackId}/activate, read the cues with GET /api/v1/library/subtitles/{trackId}/cues. A track used by an AI AutoCut session cannot be deleted (409).

Import a schedule​

PUT /api/v1/library/channels/{channelId}/timelines creates or updates timelines, their events and the media the events play. Everything is keyed by DMRNs from your system, so you can resend a day whenever it changes: the same references update the same timelines, events and media. List channel ids with GET /api/v1/library/channels.

{
"timelines": [
{
"reference": "dmrn:customer:playout:ch:acme:timeline/2026-09-28-morning",
"name": "Morning show",
"startTime": "2026-09-28T06:00:00+02:00",
"events": [
{
"reference": "dmrn:customer:playout:ch:acme:event/81723",
"startTime": "2026-09-28T06:00:00+02:00",
"endTime": "2026-09-28T06:03:30+02:00",
"media": {
"reference": "dmrn:customer:mam:ch:acme:programme/JINGLE-07",
"name": "Station jingle 07",
"metadata": { "category": "jingle" }
}
}
]
}
]
}

Rules worth knowing:

  • Times must carry an offset (Z or +02:00).
  • Send events in play order. Each timeline and event reference may appear once per import.
  • The import is a sliding window: events of a timeline that start after the first event you send and are missing from your list are deleted. Events before it are kept, so resending the rest of the day never touches what already aired.
  • An event's media.metadata replaces that media's metadata: send all of it.

Read timelines back with GET /api/v1/library/timelines (filter by channelId, from and to) and GET /api/v1/library/timelines/{id}, which returns every event in play order with the mediaId it plays.

Errors and limits​

Errors use the same envelope as every endpoint of the API:

{ "error": { "code": "media_not_found", "message": "No media with id …" } }

The library. endpoints share the ordinary limit of 120 requests per minute per API key described in Getting started.