# 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:

1. **Creating an upload link** — get a link that can be used for uploading (convenient for client applications)
2. **Single-request upload** — send the file and metadata in one request
3. **URL upload** — provide a link to the video file, Kinescope downloads it itself

> **For large files:** We recommend using the [Tus](https://tus.io) protocol for uploading large files in chunks. See the implementation example [here](https://docs.kinescope.com/developer-guides/tus-protocol-implementation/).

## **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](https://docs.kinescope.com/developer-guides/api-general-rules/) — they cover authorization, token format (UUID), pagination, and error handling.

**Get the list of projects:**

```bash
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](https://docs.kinescope.com/developer-guides/api-general-rules/#pagination).

**Get the list of folders in a project:**

```bash
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:

[Видео Kinescope]

Video about setting up and working with folders:

[Видео Kinescope]

## **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:**

```bash
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:**

```json
{
  "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}/preview`<br>Example:<br>`{`<br>`  start: 0,      // Start time in seconds`<br>`  length: 5,     // Clip length in seconds`<br>`  quality: '720p' // Clip resolution (360p, 480p, 720p, 1080p)`<br>`}` |

**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](https://tus.io) protocol.

**Example request:**

```bash
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:**

```bash
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:**

```bash
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:**

```csv
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:

```bash
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:

```bash
#!/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:**

1. Save the script to a file (e.g., `import.sh`)
2. Make it executable: `chmod +x import.sh`
3. Set your API token and project/folder ID in the variables
4. 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?

1. **[Tus protocol implementation example](https://docs.kinescope.com/developer-guides/tus-protocol-implementation/)** — uploading large files in chunks
2. **[General API guidelines](https://docs.kinescope.com/developer-guides/api-general-rules/)** — authorization and request format
3. **[Kinescope API](https://docs.kinescope.com/developer-guides/kinescope-api/)** — full API documentation

Still have questions? Write to the support chat within the Kinescope interface — our specialists will help!

