---
title: Upload Token API
url: https://docs.kaltura.com/docs/rich-media-cms-apis/content-management/upload-ingestion-upload-token-api
---

## Upload Token API


The `uploadToken` service manages server-side containers for receiving file data. Tokens support single-shot uploads, chunked uploads with parallel transfers, and auto-finalization.

### Create an Upload Token


```
POST /api_v3/service/uploadToken/action/add
```


| Parameter | Type | Description |
|-----------|------|-------------|
| `uploadToken[fileName]` | string | Original file name (optional, for tracking) |
| `uploadToken[fileSize]` | float | Expected file size in bytes (optional; **required** when using `autoFinalize`) |
| `uploadToken[autoFinalize]` | int | Set to `1` to auto-complete the upload when `uploadedFileSize` matches `fileSize`. Eliminates the need to send `finalChunk=true` on the last chunk |

**Response:** `KalturaUploadToken` object:

| Field | Type | Description |
|-------|------|-------------|
| `id` | string | Unique token ID (use in subsequent upload/addContent calls) |
| `status` | int | Token status (see table below) |
| `fileName` | string | File name set at creation |
| `fileSize` | float | Expected file size |
| `uploadedFileSize` | float | Bytes uploaded so far |
| `uploadUrl` | string | DC-specific URL for upload calls (use when your account spans multiple data centers) |
| `createdAt` | int | Unix timestamp |

**Token statuses:**

| Value | Name | Meaning |
|-------|------|---------|
| 0 | PENDING | Created, no data uploaded yet |
| 1 | PARTIAL_UPLOAD | Some chunks received |
| 2 | FULL_UPLOAD | All data received |
| 3 | CLOSED | Token consumed by addContent |
| 4 | TIMED_OUT | Token expired (partial uploads expire after 7 days) |
| 5 | DELETED | Token deleted |


```bash
curl -X POST "$KALTURA_SERVICE_URL/service/uploadToken/action/add" \
  -d "ks=$KALTURA_KS" \
  -d "format=1" \
  -d "uploadToken[fileName]=my_video.mp4" \
  -d "uploadToken[fileSize]=15728640"
```


### Upload File Data (Single or Chunked)


```
POST /api_v3/service/uploadToken/action/upload
```


| Parameter | Type | Description |
|-----------|------|-------------|
| `uploadTokenId` | string | The token ID from step 1 |
| `fileData` | file | The file or chunk (multipart form data) |
| `resume` | bool | `false` for first/only chunk, `true` for subsequent chunks |
| `resumeAt` | float | Byte offset to resume at (use `-1` or omit for first chunk) |
| `finalChunk` | bool | `true` if this is the last (or only) chunk, `false` otherwise |

#### Single-file upload (small files)


```bash
curl -X POST "$KALTURA_SERVICE_URL/service/uploadToken/action/upload" \
  -F "ks=$KALTURA_KS" \
  -F "format=1" \
  -F "uploadTokenId=$UPLOAD_TOKEN_ID" \
  -F "resume=false" \
  -F "finalChunk=true" \
  -F "resumeAt=-1" \
  -F "fileData=@my_video.mp4;type=video/mp4"
```


#### Chunked upload (large files, resumable)

Split the file into chunks and upload each sequentially. The server accepts parallel chunk uploads — chunks can arrive out of order as long as each specifies the correct `resumeAt` offset.

**Protocol:**
1. **First chunk:** `resume=false`, `finalChunk=false`  
2. **Middle chunks:** `resume=true`, `finalChunk=false`, with `resumeAt` = byte offset  
3. **Final chunk:** `resume=true`, `finalChunk=true`, with `resumeAt` = byte offset. Can be zero-size (just signals completion)  


```bash
# First chunk (offset 0)
dd if=big_video.mp4 bs=2097152 count=1 skip=0 2>/dev/null | \
curl -X POST "$KALTURA_SERVICE_URL/service/uploadToken/action/upload" \
  -F "ks=$KALTURA_KS" \
  -F "format=1" \
  -F "uploadTokenId=$UPLOAD_TOKEN_ID" \
  -F "resume=false" \
  -F "resumeAt=0" \
  -F "finalChunk=false" \
  -F "fileData=@-;filename=chunk_0"

# Subsequent chunks (resume=true, resumeAt=byte offset)
dd if=big_video.mp4 bs=2097152 count=1 skip=1 2>/dev/null | \
curl -X POST "$KALTURA_SERVICE_URL/service/uploadToken/action/upload" \
  -F "ks=$KALTURA_KS" \
  -F "format=1" \
  -F "uploadTokenId=$UPLOAD_TOKEN_ID" \
  -F "resume=true" \
  -F "resumeAt=2097152" \
  -F "finalChunk=false" \
  -F "fileData=@-;filename=chunk_2097152"

# Final chunk (finalChunk=true)
dd if=big_video.mp4 bs=2097152 count=1 skip=2 2>/dev/null | \
curl -X POST "$KALTURA_SERVICE_URL/service/uploadToken/action/upload" \
  -F "ks=$KALTURA_KS" \
  -F "format=1" \
  -F "uploadTokenId=$UPLOAD_TOKEN_ID" \
  -F "resume=true" \
  -F "resumeAt=4194304" \
  -F "finalChunk=true" \
  -F "fileData=@-;filename=chunk_4194304"
```


**Resume after failure:** Call `uploadToken.get` to check `uploadedFileSize`, then resume from that offset:


```bash
curl -X POST "$KALTURA_SERVICE_URL/service/uploadToken/action/get" \
  -d "ks=$KALTURA_KS" \
  -d "format=1" \
  -d "uploadTokenId=$UPLOAD_TOKEN_ID"
# Response includes: "uploadedFileSize": 4194304

RESUME_AT=4194304
dd if=largefile.mp4 bs=2097152 skip=$((RESUME_AT / 2097152)) 2>/dev/null | \
curl -X POST "$KALTURA_SERVICE_URL/service/uploadToken/action/upload" \
  -F "ks=$KALTURA_KS" \
  -F "format=1" \
  -F "uploadTokenId=$UPLOAD_TOKEN_ID" \
  -F "resume=true" \
  -F "resumeAt=$RESUME_AT" \
  -F "finalChunk=false" \
  -F "fileData=@-;filename=chunk_$RESUME_AT"
```


**Chunk sizing guidance:** Use 2-5 MB chunks for files under 100 MB and 10-50 MB chunks for larger files. Smaller chunks mean more HTTP requests but easier recovery; larger chunks reduce overhead but require re-uploading more data on failure.

**Auto-finalize:** When creating a token with `autoFinalize=1` and `fileSize` set, the server automatically marks the upload complete when `uploadedFileSize` matches `fileSize`. This eliminates the need for a zero-byte final chunk.

### Check Token Status


```
POST /api_v3/service/uploadToken/action/get
```


| Parameter | Type | Description |
|-----------|------|-------------|
| `uploadTokenId` | string | The token ID |

Returns the token object with `uploadedFileSize` (bytes uploaded so far) and `status`. User sessions are restricted to their own tokens.

### List Upload Tokens


```
POST /api_v3/service/uploadToken/action/list
```


| Parameter | Type | Description |
|-----------|------|-------------|
| `filter[statusEqual]` | int | Filter by token status |
| `filter[statusIn]` | string | Comma-separated status values |
| `filter[fileNameEqual]` | string | Filter by file name |
| `filter[userIdEqual]` | string | Filter by user (admin only) |
| `pager[pageSize]` | int | Results per page |
| `pager[pageIndex]` | int | Page number (1-based) |

User sessions only see their own tokens.

### Delete an Upload Token


```
POST /api_v3/service/uploadToken/action/delete
```


Use this to clean up abandoned uploads. Tokens are auto-deleted after consumption by `addContent`. Partial uploads expire after 7 days (`TIMED_OUT` status).
