Skip to content

Create download

POST
/api/v1/downloads
curl --request POST \
--url https://example.com/api/v1/downloads \
--header 'Content-Type: application/json' \
--cookie kivo_session=<kivo_session> \
--data '{ "workId": "2489E9AD-2EE2-8E00-8EC9-32D5F69181C0", "versionId": "2489E9AD-2EE2-8E00-8EC9-32D5F69181C0", "audioTrackId": "2489E9AD-2EE2-8E00-8EC9-32D5F69181C0", "subtitleTrackId": "example", "capabilities": { "file": { "containers": [ "example" ], "trackSelection": true }, "video": [ { "codec": "example", "delivery": [ "file" ], "containers": [ "example" ], "tags": [ "example" ], "profiles": [ "example" ], "maxLevel": 1, "maxBitDepth": 1, "maxWidth": 1, "maxHeight": 1, "maxFrameRate": 1, "maxBitrateBps": 1, "maxRefFrames": 1, "interlaced": true, "anamorphic": true, "hdr": [ "hdr10" ], "dolbyVision": [ { "profile": 1, "compat": [ 1 ], "el": true } ], "doviFallback": true } ], "audio": [ { "codec": "example", "delivery": [ "file" ], "containers": [ "example" ], "maxChannels": 1, "maxSampleRate": 1, "maxBitDepth": 1, "profiles": [ "example" ] } ], "subtitles": [ { "codec": "example", "delivery": [ "file" ], "containers": [ "example" ] } ] }, "settings": { "localQuality": { "mode": "auto", "maxBitrateBps": 1, "bandwidthBps": 1 }, "remoteQuality": { "mode": "auto", "maxBitrateBps": 1, "bandwidthBps": 1 }, "directPlay": true, "burnSubtitles": true }, "quality": "original" }'

Downloads a work to keep in the app. Decides the download as playback is decided, from the capabilities the app plays offline, but always as whole files: the original (delivery file) where the app plays it and it’s no larger than the quality’s estimate, else a conversion to one MP4 per part (delivery conversion), a remux where only the container is wrong, copying what it can. A book is always its original, and one the app can’t play is 409 with code notPlayable and its reason; so is a user without downloads (downloadsNotAllowed). The selected subtitle is kept as a file the app draws; for an app that draws none, a text subtitle is the conversion’s own text track (method stream), which the player shows as it does a stream’s, and any other is burned in.

A download that needs work on the server (a conversion, or its subtitle to prepare) is queued, then preparing, one at a time across the server in the order asked, kept across restarts; then ready, or failed with a reason, which retry asks again. The rest are ready at once. A downloadsChanged event says when the user’s downloads move. Asking again for exactly the same, as when an answer was lost, returns the same download, unless it failed. Downloads don’t count against the user’s stream limit, nor conversions against the server’s video transcodes. A download belongs to a session, so an API key’s caller gets 404.

Media typeapplication/json
object
workId
required

A UUIDv7.

string format: uuid
versionId

Download this version. Default as for playback (PlayCreate).

string format: uuid
audioTrackId

An audio track’s id. Default as for playback (PlayCreate).

string format: uuid
subtitleTrackId

A subtitle track’s id, or off. Default as for playback (PlayCreate).

string
<= 36 characters
capabilities
required

What the client plays offline.

object
file

Files it plays whole, the original or a download. Absent, it plays none.

object
containers
required

Containers it plays, such as mkv, mp4, webm, ts, m2ts, mov, m4a, mp3, flac, ogg.

Array<string>
trackSelection

It plays any audio track inside a file, not only the default one, so choosing another audio track keeps the file. Default false.

boolean
video
required
Array<object>

One kind of video the client decodes.

object
codec
required

Such as h264, hevc, av1, vp9, mpeg2video, vc1.

string
delivery
required

Where it decodes it, file or stream.

Array<string>
Allowed values: file stream external
containers

For file, the containers it decodes this in; other containers don’t match the entry.

Array<string>
tags

For file, the codec tags it takes, such as hvc1, hev1, dvh1, dvhe.

Array<string>
profiles

Profiles as ffprobe prints them, such as High, Main 10, Profile 2.

Array<string>
maxLevel

The highest level, as the codec’s specification writes it, such as 4.1 or 5.1.

number format: double
maxBitDepth
integer
maxWidth
integer
maxHeight
integer
maxFrameRate
number format: double
maxBitrateBps

The decoder’s limit in bits per second. A quality the user picks goes in settings instead.

integer format: int64
maxRefFrames
integer
interlaced

Whether it plays interlaced video. Default true.

boolean
anamorphic

Whether it plays video with non-square pixels. Default true.

boolean
hdr

The HDR formats it shows, of hdr10, hdr10plus and hlg; SDR always plays. An HDR10+ video matches hdr10.

Array<string>
Allowed values: hdr10 hdr10plus hlg dolbyVision
dolbyVision

The Dolby Vision profiles it shows.

Array<object>

A Dolby Vision profile a client shows. A video matches when its profile is listed, with its base layer’s compatibility ID among compat when that’s given.

object
profile
required

The profile, 5, 7, 8 or 10.

integer
compat

The base layer compatibility IDs it shows, such as 1, 2, 4.

Array<integer>
el

Whether it plays a video with an enhancement layer. Absent means it does.

boolean
doviFallback

Play a Dolby Vision video whose profile isn’t listed by its base layer, when that layer matches hdr: profile 8.1 and 7 are HDR10, 8.4 is HLG, 8.2 is SDR, and 10 is what its compatibility ID says. Default false.

boolean
audio
required
Array<object>

One kind of audio the client plays.

object
codec
required

Such as aac, ac3, eac3, truehd, dts, flac, opus, mp3, alac.

string
delivery
required

Where it plays it, file or stream.

Array<string>
Allowed values: file stream external
containers

For file, the containers it plays this in.

Array<string>
maxChannels
required

The most channels that reach the output: decoded on the device, no more than its speakers or its own setting; passed through, as many as the receiver takes. Audio with more channels is transcoded to AAC with as many as the client’s AAC entry allows, at most 6; to stereo it’s mixed keeping dialogue clear.

integer
maxSampleRate
integer
maxBitDepth
integer
profiles

Profiles as ffprobe prints them, such as LC, HE-AAC, Dolby TrueHD + Dolby Atmos.

Array<string>
subtitles
required
Array<object>

A subtitle codec a client shows, and how. The server converts a text subtitle to a text codec listed for a delivery. In the stream that’s always WebVTT, the only text HLS carries. As an external file it’s WebVTT too, where webvtt is listed, converted from SubRip, WebVTT, mov_text or ASS as plain text, with styling beyond italics, bold and underline dropped. An ASS track stays ASS for a client that lists ass, and an embedded one is burned in for a client that doesn’t. Image subtitles are never converted; a client that can’t show one has it burned in.

object
codec
required

Such as webvtt, subrip, ass, mov_text, hdmv_pgs_subtitle, dvd_subtitle.

string
delivery
required

file read from the played file, stream a WebVTT rendition of the HLS stream, external its own file. In picture-in-picture or on AirPlay a client leaves out external.

Array<string>
Allowed values: file stream external
containers

For file, the containers it reads this from; other containers don’t match the entry.

Array<string>
settings

The settings a download applies, directPlay and burnSubtitles.

object
localQuality

The client’s quality on the server’s local networks.

object
mode
required

A quality pick: auto chosen from limits and measured bandwidth, original with no cap, limit capped at maxBitrateBps.

string
Allowed values: auto original limit
maxBitrateBps

For limit, from the fixed ladder.

integer format: int64
bandwidthBps

For auto, the client’s last measured download rate from this server; the play stays below about 80% of it.

integer format: int64
remoteQuality

The client’s quality anywhere else, used instead of localQuality when the server counts the client as remote.

object
mode
required

A quality pick: auto chosen from limits and measured bandwidth, original with no cap, limit capped at maxBitrateBps.

string
Allowed values: auto original limit
maxBitrateBps

For limit, from the fixed ladder.

integer format: int64
bandwidthBps

For auto, the client’s last measured download rate from this server; the play stays below about 80% of it.

integer format: int64
directPlay

Play files directly. Default true.

boolean
burnSubtitles

Always burn in subtitles. Default false.

boolean
quality

A video’s quality, default high. The original goes as it is wherever the app plays it and it’s no larger than the quality’s estimate. A book is always its original.

string
Allowed values: original high standard

The download.

Media typeapplication/json

A download as the server holds it for its session. Media URLs are relative to the API root (/api/v1/) and need the user’s authorization.

object
id
required

A UUIDv7.

string format: uuid
workId
required

A UUIDv7.

string format: uuid
versionId
required

A UUIDv7.

string format: uuid
quality
required

The quality asked for, original for a book.

string
Allowed values: original high standard
state
required

Where a download is: queued waiting in line on the server (queuePosition says where); preparing its subtitles or conversion being made (progress and remainingMs say how far); ready to fetch each part’s url, and each subtitle’s; failed (reason says why, and retry asks again).

string
Allowed values: queued preparing ready failed
queuePosition

While queued, its place in line, 1 when it’s next.

integer
progress

While preparing, how much is converted, from 0 to 1.

number
remainingMs

While converting, about how long it has left, once that can be told.

integer
reason

When failed, why: transcodeFailed, storageFull, sourceUnreadable, subtitlesUnavailable or planUnreadable.

string
Allowed values: noTracks fileUnplayable subtitleUnplayable keyframeIndexMissing transcodeFailed transcodeLimit storageFull downloadsNotAllowed sourceUnreadable subtitlesUnavailable planUnreadable
delivery
required

What a download fetches: the original file, or a conversion, an MP4 per part made for the download.

string
Allowed values: file conversion
tracks
required

Every track of the version, and the subtitle choice off, as a play gives them (PlayStarted.tracks), for playing the download offline. A track inside the downloaded file has delivery file and its stream index in that file: in a conversion the video, the audio, then each text track it carries, the chosen one first. A subtitle delivered external is fetched with the download, at url, once the download is ready; one that couldn’t be extracted has no delivery. A choice without a delivery isn’t in the download.

Array<object>

One choice of a play: a track of its version, or the subtitle choice off, and how it shows.

object
trackId
required

A track’s id, or off.

string
<= 36 characters
type
required

A track’s type.

string
Allowed values: video audio subtitle
selected

True for the tracks the play shows; absent otherwise.

boolean
delivery

Absent when choosing it starts a new play.

string
Allowed values: file stream external burn none
codec

The codec it’s delivered as, such as hevc, aac or webvtt.

string
hdr

The video’s HDR as delivered; absent for SDR.

string
Allowed values: hdr10 hdr10plus hlg dolbyVision
transcode

What a transcoded track becomes.

object
width
integer
height
integer
bitrateBps
integer format: int64
channels
integer
encoder

Video only; what encodes it, the accelerator’s name as GET /api/v1/accelerators gives it, such as Intel Quick Sync (QSV), or CPU.

string
reason

Why the track isn’t delivered unchanged in the file, or why choosing it starts a new play, when there’s a reason to give.

string
Allowed values: containerUnsupported videoCodecUnsupported videoCodecTagUnsupported videoProfileUnsupported videoLevelUnsupported videoBitDepthUnsupported videoResolutionUnsupported videoFrameRateUnsupported videoBitrateUnsupported videoRefFramesUnsupported videoInterlacedUnsupported videoAnamorphicUnsupported videoHdrUnsupported audioCodecUnsupported audioChannelsUnsupported audioSampleRateUnsupported audioBitDepthUnsupported audioProfileUnsupported subtitleCodecUnsupported trackSelectionUnsupported streamCodecUnsupported directPlayDisabled burnSubtitlesEnabled clientQualityLimit remoteQualityLimit bandwidthLimit dialogueBoost keyframeIndexMissing subtitlePreparing fallback downloadQuality
mismatch

The capability that failed: its field (such as maxLevel, codec or containers), what the client declared, and what the track has.

object
field
required
string
declared

The declared value, lists joined by commas; absent when the client declared none.

string
actual
required
string
index

For file, the track’s stream index, to select it in the player.

integer
url

For external, the file, relative to the API root.

string
fonts

For an ass subtitle delivered external, the URLs of the fonts it uses, each once, relative to the API root: GET /api/v1/fonts/{sha256}, cacheable for good. Load them before drawing.

Array<string>
durationMs
required
integer
sizeBytes
required

Every part’s bytes. Exact when sizeExact; until a conversion is ready, an estimate from the quality’s cap, which a grainy title can exceed.

integer format: int64
sizeExact
required

sizeBytes is exact: the download is ready, or the original goes as it is. Otherwise it’s an estimate.

boolean
parts
required

The version’s parts in order; positions are on their joined timeline.

Array<object>
object
durationMs
required
integer
url
required

The part’s file, fetched with the user’s authorization and range requests.

string
contentType
required

The file’s type, as it’s served (video/mp4 for a conversion; for an original, as the version’s files are).

string
sizeBytes

The file’s exact size, once ready.

integer format: int64
etag

The file’s strong ETag, once ready, for If-Range.

string
sha256

A converted file’s SHA-256 in lowercase hex, to check it once fetched.

string
chapters
required
Array<object>
object
startMs
required
integer
endMs
required
integer
title
string
markers

The version’s markers on its timeline, in order.

Array<object>

A part of a video’s timeline a player offers to skip. An episode has intro, recap and credits markers, a movie credits only, any other video none. Each kind comes from an admin’s marker, else, for an episode, what the server found in its season’s audio and pictures, else the file’s own chapters (a chapter whose whole name is the marker’s: Intro, Opening Credits, OP; Recap, Previously On; Credits, End Credits, ED, where it belongs and as long as one lasts).

object
kind
required

What a marker skips. A later server may add kinds; skip a marker of a kind you don’t know.

string
Allowed values: intro recap credits
startMs
required
integer
endMs
required
integer
source
required

Where a marker comes from: the file’s chapters, the audio its episode shares with others in its season (and, for credits, its pictures), or an admin. A later server may add sources.

string
Allowed values: chapter fingerprint manual
final

Set on final credits: nothing follows them to the video’s end but, perhaps, a next episode’s preview, so up next may appear at their start.

boolean
expiresAt

Once ready or failed, when the server forgets it, unless deleted sooner.

string format: date-time

Example

{
"quality": "original",
"state": "queued",
"reason": "noTracks",
"delivery": "file",
"tracks": [
{
"type": "video",
"delivery": "file",
"hdr": "hdr10",
"reason": "containerUnsupported"
}
],
"markers": [
{
"kind": "intro",
"source": "chapter"
}
]
}

The request is malformed or a field is invalid (code invalidRequest).

Media typeapplication/problem+json

An RFC 9457 problem document. code is stable and is what clients translate.

object
type
required

A URI naming the problem type; about:blank when only code matters.

string
title
required

A short English summary, for logs.

string
status
required
integer
detail

English detail for logs and developers; never internal error text.

string
instance
string
code
required

A problem’s stable code, which clients translate. A client that doesn’t know a code goes by the response’s status.

string
Allowed values: invalidRequest unauthenticated invalidCredentials wrongPassword forbidden crossOrigin denied notFound expired notReady rangeNotSatisfiable conflict alreadySetUp nameTaken lastAdmin ownUser fileStillPresent kindMismatch notStoppable streamLimit notPlayable noFallback playEnded throttled rateLimited providerUnavailable notConfigured quotaUsed transcodeBusy transcodeFailed internal
requestId
required

The request ID, also in the X-Request-Id header and the server log.

string
reason

For transcodeBusy and notPlayable, why. For transcodeBusy: transcodeLimit or storageFull. For notPlayable: noTracks, fileUnplayable, subtitleUnplayable, transcodeFailed, keyframeIndexMissing or downloadsNotAllowed.

string
Allowed values: noTracks fileUnplayable subtitleUnplayable keyframeIndexMissing transcodeFailed transcodeLimit storageFull downloadsNotAllowed sourceUnreadable subtitlesUnavailable planUnreadable
mismatch

For fileUnplayable, the capability the file failed.

object
field
required
string
declared

The declared value, lists joined by commas; absent when the client declared none.

string
actual
required
string
retryAfterSeconds

For throttled and rateLimited, the Retry-After header’s value.

integer
errors

For invalidRequest, what’s wrong with which field.

Array<object>
object
field
required

A JSON pointer into the body, or a parameter name.

string
code
required

What’s wrong with a field: tooLarge for a file or list over its size, unsupported for a file in a format the server doesn’t take, unknownEpisodeGroup for a group:<ID> ordering TMDb doesn’t list for the series, and notABook for a work edited with books that isn’t one.

string
Allowed values: required invalid tooShort tooLong tooLarge unsupported outOfRange unknownEpisodeGroup notABook
plays

For streamLimit, the user’s plays, to show what is playing where.

Array<object>

One of the user’s plays, for the stream limit.

object
id
required

A UUIDv7.

string format: uuid
workId
required

A UUIDv7.

string format: uuid
title
required
string
clientName

The name of the session or API key it was started by.

string
startedAt
required
string format: date-time
message

For playEnded, the admin’s words to the viewer, when they gave any.

string
resetsAt

For quotaUsed, when the quota resets, when the provider said.

string format: date-time

Example

{
"code": "invalidRequest",
"reason": "noTracks",
"errors": [
{
"code": "required"
}
]
}

No valid session or API key (code unauthenticated), or a failed sign-in (code invalidCredentials).

Media typeapplication/problem+json

An RFC 9457 problem document. code is stable and is what clients translate.

object
type
required

A URI naming the problem type; about:blank when only code matters.

string
title
required

A short English summary, for logs.

string
status
required
integer
detail

English detail for logs and developers; never internal error text.

string
instance
string
code
required

A problem’s stable code, which clients translate. A client that doesn’t know a code goes by the response’s status.

string
Allowed values: invalidRequest unauthenticated invalidCredentials wrongPassword forbidden crossOrigin denied notFound expired notReady rangeNotSatisfiable conflict alreadySetUp nameTaken lastAdmin ownUser fileStillPresent kindMismatch notStoppable streamLimit notPlayable noFallback playEnded throttled rateLimited providerUnavailable notConfigured quotaUsed transcodeBusy transcodeFailed internal
requestId
required

The request ID, also in the X-Request-Id header and the server log.

string
reason

For transcodeBusy and notPlayable, why. For transcodeBusy: transcodeLimit or storageFull. For notPlayable: noTracks, fileUnplayable, subtitleUnplayable, transcodeFailed, keyframeIndexMissing or downloadsNotAllowed.

string
Allowed values: noTracks fileUnplayable subtitleUnplayable keyframeIndexMissing transcodeFailed transcodeLimit storageFull downloadsNotAllowed sourceUnreadable subtitlesUnavailable planUnreadable
mismatch

For fileUnplayable, the capability the file failed.

object
field
required
string
declared

The declared value, lists joined by commas; absent when the client declared none.

string
actual
required
string
retryAfterSeconds

For throttled and rateLimited, the Retry-After header’s value.

integer
errors

For invalidRequest, what’s wrong with which field.

Array<object>
object
field
required

A JSON pointer into the body, or a parameter name.

string
code
required

What’s wrong with a field: tooLarge for a file or list over its size, unsupported for a file in a format the server doesn’t take, unknownEpisodeGroup for a group:<ID> ordering TMDb doesn’t list for the series, and notABook for a work edited with books that isn’t one.

string
Allowed values: required invalid tooShort tooLong tooLarge unsupported outOfRange unknownEpisodeGroup notABook
plays

For streamLimit, the user’s plays, to show what is playing where.

Array<object>

One of the user’s plays, for the stream limit.

object
id
required

A UUIDv7.

string format: uuid
workId
required

A UUIDv7.

string format: uuid
title
required
string
clientName

The name of the session or API key it was started by.

string
startedAt
required
string format: date-time
message

For playEnded, the admin’s words to the viewer, when they gave any.

string
resetsAt

For quotaUsed, when the quota resets, when the provider said.

string format: date-time

Example

{
"code": "invalidRequest",
"reason": "noTracks",
"errors": [
{
"code": "required"
}
]
}

No such resource, or the caller may not see it (code notFound).

Media typeapplication/problem+json

An RFC 9457 problem document. code is stable and is what clients translate.

object
type
required

A URI naming the problem type; about:blank when only code matters.

string
title
required

A short English summary, for logs.

string
status
required
integer
detail

English detail for logs and developers; never internal error text.

string
instance
string
code
required

A problem’s stable code, which clients translate. A client that doesn’t know a code goes by the response’s status.

string
Allowed values: invalidRequest unauthenticated invalidCredentials wrongPassword forbidden crossOrigin denied notFound expired notReady rangeNotSatisfiable conflict alreadySetUp nameTaken lastAdmin ownUser fileStillPresent kindMismatch notStoppable streamLimit notPlayable noFallback playEnded throttled rateLimited providerUnavailable notConfigured quotaUsed transcodeBusy transcodeFailed internal
requestId
required

The request ID, also in the X-Request-Id header and the server log.

string
reason

For transcodeBusy and notPlayable, why. For transcodeBusy: transcodeLimit or storageFull. For notPlayable: noTracks, fileUnplayable, subtitleUnplayable, transcodeFailed, keyframeIndexMissing or downloadsNotAllowed.

string
Allowed values: noTracks fileUnplayable subtitleUnplayable keyframeIndexMissing transcodeFailed transcodeLimit storageFull downloadsNotAllowed sourceUnreadable subtitlesUnavailable planUnreadable
mismatch

For fileUnplayable, the capability the file failed.

object
field
required
string
declared

The declared value, lists joined by commas; absent when the client declared none.

string
actual
required
string
retryAfterSeconds

For throttled and rateLimited, the Retry-After header’s value.

integer
errors

For invalidRequest, what’s wrong with which field.

Array<object>
object
field
required

A JSON pointer into the body, or a parameter name.

string
code
required

What’s wrong with a field: tooLarge for a file or list over its size, unsupported for a file in a format the server doesn’t take, unknownEpisodeGroup for a group:<ID> ordering TMDb doesn’t list for the series, and notABook for a work edited with books that isn’t one.

string
Allowed values: required invalid tooShort tooLong tooLarge unsupported outOfRange unknownEpisodeGroup notABook
plays

For streamLimit, the user’s plays, to show what is playing where.

Array<object>

One of the user’s plays, for the stream limit.

object
id
required

A UUIDv7.

string format: uuid
workId
required

A UUIDv7.

string format: uuid
title
required
string
clientName

The name of the session or API key it was started by.

string
startedAt
required
string format: date-time
message

For playEnded, the admin’s words to the viewer, when they gave any.

string
resetsAt

For quotaUsed, when the quota resets, when the provider said.

string format: date-time

Example

{
"code": "invalidRequest",
"reason": "noTracks",
"errors": [
{
"code": "required"
}
]
}

The resource’s state doesn’t allow this; the code says why.

Media typeapplication/problem+json

An RFC 9457 problem document. code is stable and is what clients translate.

object
type
required

A URI naming the problem type; about:blank when only code matters.

string
title
required

A short English summary, for logs.

string
status
required
integer
detail

English detail for logs and developers; never internal error text.

string
instance
string
code
required

A problem’s stable code, which clients translate. A client that doesn’t know a code goes by the response’s status.

string
Allowed values: invalidRequest unauthenticated invalidCredentials wrongPassword forbidden crossOrigin denied notFound expired notReady rangeNotSatisfiable conflict alreadySetUp nameTaken lastAdmin ownUser fileStillPresent kindMismatch notStoppable streamLimit notPlayable noFallback playEnded throttled rateLimited providerUnavailable notConfigured quotaUsed transcodeBusy transcodeFailed internal
requestId
required

The request ID, also in the X-Request-Id header and the server log.

string
reason

For transcodeBusy and notPlayable, why. For transcodeBusy: transcodeLimit or storageFull. For notPlayable: noTracks, fileUnplayable, subtitleUnplayable, transcodeFailed, keyframeIndexMissing or downloadsNotAllowed.

string
Allowed values: noTracks fileUnplayable subtitleUnplayable keyframeIndexMissing transcodeFailed transcodeLimit storageFull downloadsNotAllowed sourceUnreadable subtitlesUnavailable planUnreadable
mismatch

For fileUnplayable, the capability the file failed.

object
field
required
string
declared

The declared value, lists joined by commas; absent when the client declared none.

string
actual
required
string
retryAfterSeconds

For throttled and rateLimited, the Retry-After header’s value.

integer
errors

For invalidRequest, what’s wrong with which field.

Array<object>
object
field
required

A JSON pointer into the body, or a parameter name.

string
code
required

What’s wrong with a field: tooLarge for a file or list over its size, unsupported for a file in a format the server doesn’t take, unknownEpisodeGroup for a group:<ID> ordering TMDb doesn’t list for the series, and notABook for a work edited with books that isn’t one.

string
Allowed values: required invalid tooShort tooLong tooLarge unsupported outOfRange unknownEpisodeGroup notABook
plays

For streamLimit, the user’s plays, to show what is playing where.

Array<object>

One of the user’s plays, for the stream limit.

object
id
required

A UUIDv7.

string format: uuid
workId
required

A UUIDv7.

string format: uuid
title
required
string
clientName

The name of the session or API key it was started by.

string
startedAt
required
string format: date-time
message

For playEnded, the admin’s words to the viewer, when they gave any.

string
resetsAt

For quotaUsed, when the quota resets, when the provider said.

string format: date-time

Example

{
"code": "invalidRequest",
"reason": "noTracks",
"errors": [
{
"code": "required"
}
]
}

A server-side failure: 500 (code internal, or transcodeFailed for a play’s media), or 503 for something unavailable (codes providerUnavailable and transcodeBusy, for now; notConfigured, until an admin configures it).

Media typeapplication/problem+json

An RFC 9457 problem document. code is stable and is what clients translate.

object
type
required

A URI naming the problem type; about:blank when only code matters.

string
title
required

A short English summary, for logs.

string
status
required
integer
detail

English detail for logs and developers; never internal error text.

string
instance
string
code
required

A problem’s stable code, which clients translate. A client that doesn’t know a code goes by the response’s status.

string
Allowed values: invalidRequest unauthenticated invalidCredentials wrongPassword forbidden crossOrigin denied notFound expired notReady rangeNotSatisfiable conflict alreadySetUp nameTaken lastAdmin ownUser fileStillPresent kindMismatch notStoppable streamLimit notPlayable noFallback playEnded throttled rateLimited providerUnavailable notConfigured quotaUsed transcodeBusy transcodeFailed internal
requestId
required

The request ID, also in the X-Request-Id header and the server log.

string
reason

For transcodeBusy and notPlayable, why. For transcodeBusy: transcodeLimit or storageFull. For notPlayable: noTracks, fileUnplayable, subtitleUnplayable, transcodeFailed, keyframeIndexMissing or downloadsNotAllowed.

string
Allowed values: noTracks fileUnplayable subtitleUnplayable keyframeIndexMissing transcodeFailed transcodeLimit storageFull downloadsNotAllowed sourceUnreadable subtitlesUnavailable planUnreadable
mismatch

For fileUnplayable, the capability the file failed.

object
field
required
string
declared

The declared value, lists joined by commas; absent when the client declared none.

string
actual
required
string
retryAfterSeconds

For throttled and rateLimited, the Retry-After header’s value.

integer
errors

For invalidRequest, what’s wrong with which field.

Array<object>
object
field
required

A JSON pointer into the body, or a parameter name.

string
code
required

What’s wrong with a field: tooLarge for a file or list over its size, unsupported for a file in a format the server doesn’t take, unknownEpisodeGroup for a group:<ID> ordering TMDb doesn’t list for the series, and notABook for a work edited with books that isn’t one.

string
Allowed values: required invalid tooShort tooLong tooLarge unsupported outOfRange unknownEpisodeGroup notABook
plays

For streamLimit, the user’s plays, to show what is playing where.

Array<object>

One of the user’s plays, for the stream limit.

object
id
required

A UUIDv7.

string format: uuid
workId
required

A UUIDv7.

string format: uuid
title
required
string
clientName

The name of the session or API key it was started by.

string
startedAt
required
string format: date-time
message

For playEnded, the admin’s words to the viewer, when they gave any.

string
resetsAt

For quotaUsed, when the quota resets, when the provider said.

string format: date-time

Example

{
"code": "invalidRequest",
"reason": "noTracks",
"errors": [
{
"code": "required"
}
]
}