Skip navigation

Video API

Core video operations and uploads.

Videos

The video object

FieldTypeDescription
idstringUnique identifier for the object.
project_idstring
folder_idstring
versionnumber
titlestring
descriptionstring
statusenumAvailable values: pending, uploading, pre-processing, processing, aborted, done, error
progressnumberVideo processing progress
durationnumberVideo duration in seconds
assets[]Asset
has_audioboolWhether the video has any audio.
audio_tracks[]AudioTrackDownloadable audio tracks (id, language, label, file_size, filetype, original_name, download_link). Omitted when the video has no audio tracks.
chaptersChapters
privacy_typeenumAvailable values: anywhere, nowhere, custom
privacy_domains[]stringWhitelist domains
posterPoster
additional_materials[]AdditionalMaterial
additional_materials_enabledbool
annotation_text_enabledbool
annotation_video_enabledbool
created_atdatetime
updated_atdatetime
play_linkstringLink to player
embed_linkstringEmbed player link
subtitlesSubtitles
subtitles_enabledbooleanShow/Hide subtitles in player
hls_linkstringLink to HLS manifest

Concat video

POST https://api.kinescope.io/v1/videos/:video_id/concat

Concatenates the source video with one or more other videos into a single new video. The original video is left unchanged and a new video is created with the combined content.

Request body (json)
{
  "prepend": [
    {
      "video_id": "<UUID>"
    }
  ],
  "append": [
    {
      "video_id": "<UUID>"
    }
  ],
  "replace": false
}

Copy video

POST https://api.kinescope.io/v1/videos/:video_id/copy

Creates a full copy of the video, optionally moving the copy into a different project or folder.

Request body (json)
{
  "parent_id": "<UUID>"
}

Cut video

POST https://api.kinescope.io/v1/videos/:video_id/cut

Trims the video to a given time range. The result is written back to the same video ID; the original bytes are replaced.

Create new trim/crop video.

FieldTypeDescription
project_idstringnot required
folder_idstringnot required
titlestringnot required
descriptionstringnot required
cropcrop_objectw, h — width, height; x, y — left top corner
trim[]trim_objectstart — start time; length — length of video
Request body (json)
{
  "crop": {
    "w": 300,
    "h": 200,
    "x": 100,
    "y": 80,
    "quality": "360p"
  },
  "trim": [
    {
      "start": 6,
      "length": 2
    },
    {
      "start": 1,
      "length": 2
    }
  ]
}

Videos list

GET https://api.kinescope.io/v1/videos

Returns a list of videos. Results are paginated and can be filtered via query parameters.

Responses
{
  "meta": {
    "pagination": {
      "page": 1,
      "per_page": 1,
      "total": 10
    },
    "order": {
      "created_at": "desc",
      "title": "asc"
    }
  },
  "data": [
    {
      "id": "vKSxQyZScoQfP29oothREi",
      "project_id": "mNFQz2wYTBhLkPBCo9oS8m",
      "folder_id": null,
      "version": 0,
      "title": "sample_video",
      "description": "",
      "status": "uploading",
      "progress": 100,
      "duration": 0,
      "assets": [],
      "chapters": {
        "items": [],
        "enabled": false,
        "show_on_load": false
      },
      "privacy_type": "anywhere",
      "privacy_domains": [],
      "poster": null,
      "additional_materials": null,
      "additional_materials_enabled": false,
      "play_link": "https://kinescope.io/199511994",
      "embed_link": "https://kinescope.io/embed/199511994",
      "created_at": "2020-08-31T09:03:00.106436Z",
      "updated_at": null,
      "subtitles": [],
      "subtitles_enabled": false,
      "hls_link": "https://kinescope.io/199511994/master.m3u8"
    }
  ]
}

Get video

GET https://api.kinescope.io/v1/videos/:video_id

Retrieves the details of a single video by its unique ID.

Responses
{
  "data": {
    "id": "<UUID>",
    "project_id": "<UUID>",
    "folder_id": null,
    "player_id": "<UUID>",
    "version": 1,
    "title": " Encrypted, saved (2024.09.08 13:35)",
    "subtitle": "",
    "description": "",
    "status": "done",
    "progress": 0,
    "duration": 66.00001,
    "assets": [
      {
        "id": "<UUID>",
        "video_id": "<UUID>",
        "original_name": "original.ts",
        "file_size": 4862244,
        "md5": "a05d6c66884dc7f8c5136b6c9d95fef7",
        "filetype": "ts",
        "quality": "original",
        "resolution": "1920x1080",
        "created_at": "2024-09-08T10:35:17.087638Z",
        "url": "https://kinescopecdn.net/<UUID>/videos/<UUID>/assets/<UUID>/original.mp4?expires=<EXPIRES>&sign=<SIGNATURE>",
        "download_link": "https://s3.kinescope.io/<UUID>/videos/<UUID>/mp4/original.ts?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=<CREDENTIAL>"
      },
      {
        "id": "<UUID>",
        "video_id": "<UUID>",
        "original_name": "1080p.mp4",
        "file_size": 4292636,
        "filetype": "mp4",
        "quality": "1080p",
        "resolution": "1920x1080",
        "created_at": "2024-09-08T10:35:30.549646Z",
        "download_link": ""
      },
      {
        "id": "<UUID>",
        "video_id": "<UUID>",
        "original_name": "720p.mp4",
        "file_size": 3217594,
        "filetype": "mp4",
        "quality": "720p",
        "resolution": "1280x720",
        "created_at": "2024-09-08T10:35:30.549646Z",
        "download_link": ""
      },
      {
        "id": "<UUID>",
        "video_id": "<UUID>",
        "original_name": "480p.mp4",
        "file_size": 2031032,
        "filetype": "mp4",
        "quality": "480p",
        "resolution": "852x480",
        "created_at": "2024-09-08T10:35:30.549646Z",
        "download_link": ""
      },
      {
        "id": "<UUID>",
        "video_id": "<UUID>",
        "original_name": "360p.mp4",
        "file_size": 1451443,
        "filetype": "mp4",
        "quality": "360p",
        "resolution": "640x360",
        "created_at": "2024-09-08T10:35:30.549646Z",
        "download_link": ""
      }
    ],
    "has_audio": true,
    "audio_tracks": [
      {
        "id": "<UUID>",
        "language": "en",
        "label": "English",
        "file_size": 4292636,
        "filetype": "mp4",
        "original_name": "audio_en.mp4",
        "download_link": "https://s3.kinescope.io/<UUID>/videos/<UUID>/audio/<UUID>.mp4?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=<CREDENTIAL>"
      },
      {
        "id": "<UUID>",
        "language": "ru",
        "label": "Русский",
        "file_size": 4185220,
        "filetype": "mp4",
        "original_name": "audio_ru.mp4",
        "download_link": "https://s3.kinescope.io/<UUID>/videos/<UUID>/audio/<UUID>.mp4?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=<CREDENTIAL>"
      }
    ],
    "chapters": {
      "items": [],
      "enabled": false
    },
    "privacy_type": "anywhere",
    "privacy_domains": [],
    "privacy_email_domains": [],
    "privacy_share": {},
    "tags": [],
    "poster": {
      "id": "<UUID>",
      "type": "image",
      "media_id": "<UUID>",
      "status": "done",
      "active": true,
      "original": "https://kinescopecdn.net/<UUID>/posters/<UUID>/<UUID>.jpg",
      "md": "https://kinescopecdn.net/<UUID>/posters/<UUID>/md/<UUID>.jpg",
      "sm": "https://kinescopecdn.net/<UUID>/posters/<UUID>/sm/<UUID>.jpg",
      "xs": "https://kinescopecdn.net/<UUID>/posters/<UUID>/xs/<UUID>.jpg",
      "from_time": 0,
      "to_time": 0
    },
    "additional_materials": [],
    "additional_materials_enabled": false,
    "annotation_text_enabled": false,
    "annotation_video_enabled": false,
    "play_link": "https://kinescope.io/vN1xLXadcCk94aCuZHR5i2",
    "embed_link": "https://kinescope.io/embed/vN1xLXadcCk94aCuZHR5i2",
    "created_at": "2024-09-08T10:35:11.674333Z",
    "updated_at": "2026-03-05T14:04:37.150678Z",
    "subtitles": [],
    "subtitles_enabled": false,
    "hls_link": "https://kinescope.io/vN1xLXadcCk94aCuZHR5i2/master.m3u8",
    "chat_preview": false,
    "chat_inside_player": "",
    "chat_expand_on_load": false,
    "meta": {
      "event_id": "<UUID>",
      "stream_id": "<UUID>"
    }
  }
}
{
  "error": {
    "code": 400404,
    "message": "not found"
  }
}

Move video to another project and folder

PUT https://api.kinescope.io/v1/videos/:video_id/move

Moves the video into a different project and/or folder. The video ID stays the same.

Request body (json)
{
  "project_id": "3kAyiWTAZQKKZxg1GfjKvS",
  "folder_id": "2MxB8wx35jHQjhCPczBamu"
}

Update chapters

PUT https://api.kinescope.io/v1/videos/:video_id/chapters

Replaces the chapter markers of the video with the provided list. Pass an empty array to clear all chapters.

Request body (json)
{
  "items": [
    {
      "time": 10000,
      "title": "Chapter at 10sec"
    }
  ],
  "enabled": true
}
Responses
{
  "data": {
    "items": [
      {
        "time": 10000,
        "title": "Chapter at 10sec"
      }
    ],
    "enabled": true
  }
}

Update video

PATCH https://api.kinescope.io/v1/videos/:video_id

Updates the specified video. Only fields provided in the request body are changed; others are left unchanged.

This request update only passed fields.

Fields which can update: title, description, privacy_type, privacy_domains, additional_materials_enabled

Request body (json)
{
  "title": "New title",
  "description": "New description",
  "privacy_type": "custom",
  "privacy_domains": [
    "example.com"
  ],
  "additional_materials_enabled": false,
  "tags": [
    "tag 1",
    "tag 2",
    "tag 3"
  ]
}
Responses
{
  "data": {
    "id": "iuFPEzdC2Jtf8aCcvMJQ8h",
    "workspace_id": "s8vL2Zr3CxCj1A8HmxoGhp",
    "project_id": "hfHfAgq4g2nxxtg8DQ3Twi",
    "folder_id": null,
    "storage_id": "mucjva43n3sLsw5YRwsZYS",
    "short_id": 199511990,
    "version": 0,
    "title": "New title",
    "description": "New description",
    "status": "done",
    "progress": 0,
    "duration": 179.305,
    "assets": [
      {
        "id": "i7r58w3Lt3bPoPyX27tprT",
        "video_id": "iuFPEzdC2Jtf8aCcvMJQ8h",
        "original_name": "original.mp4",
        "file_size": 5603249,
        "filetype": "QuickTime / MOV",
        "quality": "original",
        "resolution": "320x240",
        "created_at": "2020-08-30T16:10:08.091561Z",
        "updated_at": null,
        "deleted_at": null
      },
      {
        "id": "kdwSHkB2e1AH8veDLuCnUP",
        "video_id": "iuFPEzdC2Jtf8aCcvMJQ8h",
        "original_name": "360p.mp4",
        "file_size": 4196287,
        "filetype": "QuickTime / MOV",
        "quality": "360p",
        "resolution": "320x240",
        "created_at": "2020-08-30T16:10:14.087606Z",
        "updated_at": null,
        "deleted_at": null
      }
    ],
    "chapters": {
      "items": [],
      "enabled": false,
      "show_on_load": false
    },
    "privacy_type": "custom",
    "privacy_domains": [
      "example.com"
    ],
    "poster": {
      "id": "eHqAqKuMi4JTsAoMvf5GRs",
      "video_id": "iuFPEzdC2Jtf8aCcvMJQ8h",
      "storage_id": "mucjva43n3sLsw5YRwsZYS"
    },
    "additional_materials": [],
    "additional_materials_enabled": false,
    "created_at": "2020-08-30T16:10:05.702154Z",
    "updated_at": null,
    "deleted_at": null
  }
}

Delete video

DELETE https://api.kinescope.io/v1/videos/:video_id

Permanently deletes the video. This action cannot be undone.

Responses
{
  "data": {
    "success": true
  }
}

Videos

Create upload session

POST https://uploader.kinescope.io/v2/init

Creates an upload session and returns the address the file is sent to. Use it when the file is large, the network is unreliable, or the upload happens in a browser you do not want to hand the API token to: the address itself authorises the upload.

The returned endpoint is geo-routed — https://eu-ams-uploader-1.kinescope.io/v2/upload/… — so send the file exactly there, do not rebuild the URL from the base host.

Body
ParameterTypeDescription
typeenumRequired. video, attachment or replace.
parent_iduuidRequired for type: video. Project or folder the video lands in. Get it from GET /v1/projects or GET /v1/projects/:project_id/folders.
titlestringRequired for type: video. Video title.
video_iduuidRequired for type: attachment. The video the material is attached to.
filesizeintegerRequired for tus. File size in bytes. Drives the progress indicator.
filenamestringFile name. Informational.
subtitlestringVideo subtitle.
descriptionstringVideo description.
client_ipstringEnd-client IP address. Picks the closest upload server.
previewobjectCreates a preview clip available at https://kinescope.io/{video_id}/preview. Fields: start and length in seconds, quality — 360p, 480p, 720p or 1080p.

The parameter set for type: replace is not described in the guide and requires confirmation.

Request body (json)
{
  "type": "video",
  "parent_id": "e51e55a1-7615-493e-9055-10ac9cc44ccd",
  "title": "Product demo",
  "filename": "demo.mp4",
  "filesize": 48622440
}
Responses
{
  "data": {
    "id": "7127f2d7-0e96-40d0-9a03-2e987c096466",
    "endpoint": "https://eu-ams-uploader-1.kinescope.io/v2/upload/0966958f-638b-4aab-bf4a-7f9860a57a93"
  }
}

Step 2: send the file to the returned address

The address from data.endpoint accepts both a plain POST with the file in the body and the tus protocol. The access token is not sent on this step — the address itself is the permission.

curl -X POST \
  'https://eu-ams-uploader-1.kinescope.io/v2/upload/0966958f-638b-4aab-bf4a-7f9860a57a93' \
  --data-binary '@demo.mp4'

For resumable uploads use a tus client library: it sends HEAD to read the current Upload-Offset and continues with PATCH from that byte, receiving 204 No Content with the new offset after every chunk. A plain POST has no resume — after a drop the upload starts from zero.

How long the returned address stays valid is not documented and requires confirmation. The threshold above which tus becomes mandatory is not documented either.

Upload video

POST https://uploader.kinescope.io/v2/video

Uploads a video in a single request. Metadata goes in headers, the file goes in the body — or, with the X-Video-URL header, the body stays empty and Kinescope downloads the file itself.

Use it for small files on a stable connection and for imports from your own storage. For large files use POST /v2/init and tus: this endpoint has no resume, and a dropped connection means starting over.

Headers
ParameterTypeDescription
X-Parent-IDuuidRequired. Project or folder the video lands in.
X-Video-TitlestringRequired. Video title.
X-Video-URLstringRequired for URL upload. Direct link to the file, or a YouTube address of the form https://www.youtube.com/watch?v=… or https://youtu.be/…. With this header the request body stays empty.
X-Video-DescriptionstringVideo description.
X-File-NamestringFile name.
X-Replace-Video-IDuuidVideo to replace. Whether the identifier, metadata and links survive the replacement is not documented and requires confirmation.
X-Video-TrimjsonTrim on upload, values in seconds: {"start": 1, "length": 2}. Without length the video is trimmed from start to the end.
Content-TypestringType of the data in the body, for example video/mp4.

X-Poster-URL appears in the previous version of this page but not in the developer guide: its support requires confirmation.

The body format is described as multipart in the previous version of this page, while the guide passes the file as a raw body. Maximum file size for this endpoint is not published. Both require confirmation.

Responses
{
  "data": {
    "id": "8d1c4b7e-2f39-4a06-b5c8-71e0a9d3f462",
    "project_id": "3f2a9c14-7b6d-4e58-9a21-0c5e8d47b193",
    "title": "Product demo",
    "status": "uploading",
    "progress": 0,
    "play_link": "https://kinescope.io/bK3mQx7ZtNvRs2WdYpLc9F"
  }
}

After the upload

A finished upload does not mean a ready video. Poll GET /v1/videos/{video_id} by the identifier returned at the first step, no more than once every 5 seconds, or subscribe to the media.update.status webhook. Terminal statuses are done, error and aborted; progress is not a readiness signal.

If the file behind X-Video-URL is unreachable, the video ends up in status: error and the reason arrives in the webhook payload.

Repeating a POST after a timeout creates a second video: Idempotency-Key is not supported. Before retrying, look the video up with GET /v1/videos filtered by project and title, or replace the failed attempt through X-Replace-Video-ID.