File Upload via API
Kinescope lets you upload video via API. This lets you send files directly to projects and folders, control access to upload links, and keep your API token hidden from users of client applications.
Who this article is for
- Developers — need to integrate video upload into their systems
- Platform administrators — need to automate content upload
- DevOps engineers — need to set up bulk video uploads
When you need API upload
API upload is useful if:
- Integration with your system is needed — automatic video upload from your application
- Access control is required — you want to manage who can upload files
- Security — the API token stays on the server, not in the client application
- Bulk upload — you need to upload many videos from CSV or another source
Upload methods
Kinescope supports three upload methods:
- Creating an upload link — get a link that can be used for uploading (convenient for client applications)
- Single-request upload — send the file and metadata in one request
- URL upload — provide a link to the video file, Kinescope downloads it itself
For large files: We recommend using the Tus protocol for uploading large files in chunks. See the implementation example here .
Preparation: getting the project or folder ID
Before uploading a video, you need to select a project or folder for the file. The project or folder ID can be obtained via API:
Before you start: If this is your first time using the Kinescope API, we recommend reviewing the general API guidelines — they cover authorization, token format (UUID), pagination, and error handling.
Get the list of projects:
curl --location 'https://api.kinescope.io/v1/projects' \
--header 'Authorization: Bearer ${KINESCOPE_API_TOKEN}'
The response will contain a list of projects with their IDs. Use the id from the response to get the list of folders in a specific project.
Pagination and sorting: Project and folder lists support pagination (
page,per_page) and sorting (order). See more in the general API guidelines .
Get the list of folders in a project:
curl --location 'https://api.kinescope.io/v1/projects/${PROJECT_ID}/folders' \
--header 'Authorization: Bearer ${KINESCOPE_API_TOKEN}'
Replace ${PROJECT_ID} with the project ID from the previous request.
The response will contain a list of folders with their IDs. The project or folder ID can be used in the parent_id parameter when uploading video.
Video about setting up and working with projects:
Video about setting up and working with folders:
Method 1: Creating an upload link
This method is convenient when you need to enable uploading directly through a client application. You get a link that can be passed to the client for uploading the file.
Example request:
curl --location --request POST 'https://uploader.kinescope.io/v2/init' \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer ${KINESCOPE_API_TOKEN}' \
--data-raw '{
"filesize": 10485760,
"type": "video",
"title": "My Video",
"parent_id": "e51e55a1-7615-493e-9055-10ac9cc44ccd",
"filename": "video.mp4",
"description": "Video description",
"client_ip": "11.22.33.44"
}'
Response:
{
"data": {
"id": "7127f2d7-0e96-40d0-9a03-2e987c096466",
"endpoint": "https://eu-ams-uploader-1.kinescope.io/v2/upload/0966958f-638b-4aab-bf4a-7f9860a57a93"
}
}
What next? Use the endpoint from the response to upload the file (see “Uploading a file using the received link” below).
Request parameters
Common parameters:
| Field | Type | Description |
|---|---|---|
type | string | Required. Values: video, attachment, replace |
client_ip | string | Client IP address. Determines the nearest upload server |
filesize | int | Required for Tus. File size in bytes. Used to display progress |
Parameters for type video:
| Field | Type | Description |
|---|---|---|
parent_id | uuid | Required. Project or folder ID for video upload |
title | string | Required. Video title |
subtitle | string | Video subtitle |
description | string | Video description |
filename | string | Filename (informational field) |
preview | object | After passing this parameter, an .mp4 clip of the video is created, accessible at: https://kinescope.io/${video_id}/previewExample: {start: 0, // Start time in secondslength: 5, // Clip length in secondsquality: '720p' // Clip resolution (360p, 480p, 720p, 1080p)} |
Parameters for type attachment:
| Field | Type | Description |
|---|---|---|
video_id | uuid | ID of the video to which the supplementary material is being uploaded |
Uploading a file using the received link
After getting the link (endpoint), upload the file via a POST request. The same link can be used to upload large files in chunks via the Tus
protocol.
Example request:
curl --location --request POST 'https://eu-ams-uploader-1.kinescope.io/v2/upload/0966958f-638b-4aab-bf4a-7f9860a57a93' \
--data-binary '@/path/to/video.mp4'
Method 2: Single-request video upload
In this case, metadata is passed in the request headers and the video file in the body. This is suitable for small files or when you need to upload a file and immediately specify metadata.
Example request:
curl --location --request POST 'https://uploader.kinescope.io/v2/video' \
--header 'Authorization: Bearer ${KINESCOPE_API_TOKEN}' \
--header 'X-Parent-ID: ${PARENT_ID}' \
--header 'X-Video-Title: ${TITLE}' \
--header 'X-Video-Description: ${DESCRIPTION}' \
--header 'Content-Type: video/mp4' \
--data-binary '@/path/to/video.mp4'
Request headers:
| Field | Type | Description |
|---|---|---|
X-Parent-ID | uuid | Required. Project or folder ID for upload |
X-Video-Title | string | Required. Video title |
X-Video-Description | string | Video description |
X-File-Name | string | Filename |
X-Replace-Video-ID | uuid | ID of the video to replace |
Content-Type | string | Type of data passed in the request body |
X-Video-Trim | json | Data for trimming the video in seconds, e.g.: {"start": 1, "length": 2}. If the length parameter is not passed, the video will be trimmed from the specified start to the end |
Method 3: URL video upload
You can use a direct link to a video file or a YouTube URL (e.g., https://www.youtube.com/watch?v=UTgSnM3mA-4 or https://youtu.be/UTgSnM3mA-4). Kinescope will download the file from the provided link itself.
Example request:
curl --location --request POST 'https://uploader.kinescope.io/v2/video' \
--header 'Authorization: Bearer ${KINESCOPE_API_TOKEN}' \
--header 'X-Parent-ID: ${PARENT_ID}' \
--header 'X-Video-Title: ${TITLE}' \
--header 'X-Video-URL: ${URL_TO_VIDEO_FILE}'
Request headers:
| Field | Type | Description |
|---|---|---|
X-Video-URL | string | Required. Direct link to the video file or YouTube URL |
X-Parent-ID | uuid | Required. Project or folder ID for upload |
X-Video-Title | string | Required. Video title |
X-Video-Description | string | Video description |
Direct poster links
After uploading a video, you can get direct links to posters (preview images). Available sizes: xs, sm, md, lg.
Link format:
https://kinescope.io/{video_id}/poster.{jpg|webp}
https://kinescope.io/{video_id}/poster/{size}.{jpg|webp}
Examples:
https://kinescope.io/2WFmbHsNz1W72DL9DGz2ps/poster.jpg
https://kinescope.io/2WFmbHsNz1W72DL9DGz2ps/poster/md.webp
Example: Bulk import from CSV
If you need to upload many videos from a CSV file, you can use a simple bash script with curl. This is simpler than writing a full application.
Important: The CSV file must have columns named url and title.
CSV file example:
url,title
https://example.com/video1.mp4,Video Title 1
https://example.com/video2.mp4,Video Title 2
Single request (example)
To upload one video by URL, use this curl request:
curl --location --request POST 'https://uploader.kinescope.io/v2/video' \
--header 'Authorization: Bearer ${KINESCOPE_API_TOKEN}' \
--header 'X-Video-URL: https://example.com/video1.mp4' \
--header 'X-Video-Title: Video Title 1' \
--header 'X-Parent-ID: ${PARENT_ID}'
Bash script for bulk import
Here is a simple script that reads CSV and uploads all videos:
#!/bin/bash
# Settings
KINESCOPE_API_TOKEN="your_api_token"
PARENT_ID="project_or_folder_id"
CSV_FILE="videos.csv"
# Check file exists
if [ ! -f "$CSV_FILE" ]; then
echo "Error: file $CSV_FILE not found"
exit 1
fi
# Skip CSV header (first line)
tail -n +2 "$CSV_FILE" | while IFS=',' read -r url title; do
url=$(echo "$url" | tr -d ' "')
title=$(echo "$title" | tr -d ' "')
if [ -z "$url" ] || [ -z "$title" ]; then
continue
fi
echo "Uploading: $title ($url)"
response=$(curl -s -w "\n%{http_code}" --location --request POST 'https://uploader.kinescope.io/v2/video' \
--header "Authorization: Bearer $KINESCOPE_API_TOKEN" \
--header "X-Video-URL: $url" \
--header "X-Video-Title: $title" \
--header "X-Parent-ID: $PARENT_ID")
http_code=$(echo "$response" | tail -n1)
body=$(echo "$response" | sed '$d')
if [ "$http_code" -eq 200 ] || [ "$http_code" -eq 201 ]; then
video_id=$(echo "$body" | grep -o '"id":"[^"]*"' | cut -d'"' -f4)
echo " ✓ Uploaded successfully. ID: $video_id"
else
echo " ✗ Error (HTTP $http_code): $body"
fi
echo ""
done
echo "Import complete"
How to use:
- Save the script to a file (e.g.,
import.sh) - Make it executable:
chmod +x import.sh - Set your API token and project/folder ID in the variables
- Run:
./import.sh
For developers: If you need more complex logic (error handling, parallel uploads, mapping storage), use Python, Node.js, or another language. But for simple cases, a bash script with curl is the quickest option.
Which method to choose?
- Creating an upload link — if you need to let clients upload files directly
- Single-request upload — for small files or when you need to specify all metadata immediately
- URL upload — if files are already on the internet (YouTube, your storage, etc.)
Done! You can now upload video via the Kinescope API using any convenient method.
What’s next?
- Tus protocol implementation example — uploading large files in chunks
- General API guidelines — authorization and request format
- Kinescope API — full API documentation
Still have questions? Write to the support chat within the Kinescope interface — our specialists will help!