---
title: Creating Media Entries
url: https://docs.kaltura.com/docs/rich-media-cms-apis/content-management/upload-ingestion-creating-media-entries
---

## Creating Media Entries


### media.add -- Create Entry Metadata


```
POST /api_v3/service/media/action/add
```


| Parameter | Type | Description |
|-----------|------|-------------|
| `entry[objectType]` | string | `KalturaMediaEntry` |
| `entry[mediaType]` | int | `1`=Video, `2`=Image, `5`=Audio |
| `entry[name]` | string | Display name |
| `entry[description]` | string | Description (optional) |
| `entry[tags]` | string | Comma-separated tags (optional) |
| `entry[referenceId]` | string | External reference ID for cross-system linking (optional) |
| `entry[conversionProfileId]` | int | Override default transcoding profile (optional) |

**Response:** `KalturaMediaEntry` with `id`, `status` (7 = NO_CONTENT until file attached)


```bash
curl -X POST "$KALTURA_SERVICE_URL/service/media/action/add" \
  -d "ks=$KALTURA_KS" \
  -d "format=1" \
  -d "entry[objectType]=KalturaMediaEntry" \
  -d "entry[mediaType]=1" \
  -d "entry[name]=My Uploaded Video" \
  -d "entry[description]=Uploaded via API" \
  -d "entry[tags]=api,upload,demo"
```


### media.addContent -- Attach Upload Token to Entry


```
POST /api_v3/service/media/action/addContent
```


| Parameter | Type | Description |
|-----------|------|-------------|
| `entryId` | string | The entry ID from media.add |
| `resource[objectType]` | string | Resource type (see table below) |
| `resource[token]` | string | Upload token ID (for `KalturaUploadedFileTokenResource`) |

**Content resource types:** The `resource` parameter accepts any of these types:

| Resource Type | Description | Use Case |
|--------------|-------------|----------|
| `KalturaUploadedFileTokenResource` | Attach content from an upload token | Standard upload workflow (most common) |
| `KalturaUrlResource` | Import from HTTP/HTTPS/FTP URL | Remote file import |
| `KalturaEntryResource` | Copy content from another entry's flavor | Entry content duplication |
| `KalturaAssetResource` | Copy from a specific flavor asset by ID | Flavor-level content copy |
| `KalturaOperationResource` | Clip, trim, or apply effects to source content | Clipping, concatenation, effects |
| `KalturaAssetsParamsResourceContainers` | Multi-flavor ingest (multiple renditions at once) | Pre-transcoded multi-bitrate content |
| `KalturaRemoteStorageResource` | Register content on configured remote storage | External CDN/S3 content |
| `KalturaSshUrlResource` | Import via SSH/SFTP with key authentication | Secure server file transfer |
| `KalturaDropFolderFileResource` | Reference a file from a configured drop folder | Drop folder integration |
| `KalturaRemoteStorageResources` | Register content on multiple storage profiles | Multi-CDN/multi-region content |
| `KalturaStringResource` | Inline string content (text, XML, JSON) | Caption content, data entries |
| `KalturaUploadedFileResource` | Direct multipart file upload (no token) | Simple single-request upload |

Two additional types exist for internal/system use only (`KalturaServerFileResource`, `KalturaFileSyncResource`) and are not available to customer accounts.

Triggers transcoding. Entry status changes from `NO_CONTENT (7)` to `IMPORT (0)` or `PENDING (4)`.


```bash
curl -X POST "$KALTURA_SERVICE_URL/service/media/action/addContent" \
  -d "ks=$KALTURA_KS" \
  -d "format=1" \
  -d "entryId=$KALTURA_ENTRY_ID" \
  -d "resource[objectType]=KalturaUploadedFileTokenResource" \
  -d "resource[token]=$UPLOAD_TOKEN_ID"
```


### media.updateContent -- Replace an Entry's Source File


```
POST /api_v3/service/media/action/updateContent
```


| Parameter | Type | Description |
|-----------|------|-------------|
| `entryId` | string | Entry ID to update |
| `resource[objectType]` | string | Resource type (same options as addContent) |
| `resource[token]` | string | Upload token ID |
| `conversionProfileId` | int | Override transcoding profile (optional) |

Replaces the source file while preserving the entry ID, metadata, embed codes, and analytics. The entry enters a "pending replacement" state until transcoding completes. Uses locking to prevent concurrent replacements.


```bash
curl -X POST "$KALTURA_SERVICE_URL/service/media/action/updateContent" \
  -d "ks=$KALTURA_KS" \
  -d "format=1" \
  -d "entryId=$KALTURA_ENTRY_ID" \
  -d "resource[objectType]=KalturaUploadedFileTokenResource" \
  -d "resource[token]=$UPLOAD_TOKEN_ID"
```


**Business scenario — version management:** A training team records lecture updates. They replace the video file on the existing entry so all existing playlists, embed codes, and analytics continue working with the new version.

### media.approveReplace / media.cancelReplace

When content replacement is configured to require approval:


```bash
# Approve pending replacement
curl -X POST "$KALTURA_SERVICE_URL/service/media/action/approveReplace" \
  -d "ks=$KALTURA_KS" \
  -d "format=1" \
  -d "entryId=$KALTURA_ENTRY_ID"

# Cancel pending replacement
curl -X POST "$KALTURA_SERVICE_URL/service/media/action/cancelReplace" \
  -d "ks=$KALTURA_KS" \
  -d "format=1" \
  -d "entryId=$KALTURA_ENTRY_ID"
```


### Import from URL (KalturaUrlResource)

Use `media.add` + `media.addContent` with `KalturaUrlResource` to import content from a remote URL. Kaltura fetches the file server-side via an async import job. Entry transitions from `NO_CONTENT (7)` → `IMPORT (0)` → `READY (2)`.

| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| `resource[objectType]` | string | Yes | `KalturaUrlResource` |
| `resource[url]` | string | Yes | Direct file URL (HTTP, HTTPS, or FTP) |
| `resource[urlHeaders]` | array | No | Custom HTTP headers for the download request (e.g., auth tokens) |
| `resource[forceAsyncDownload]` | bool | No | Force async import job |


```bash
curl -X POST "$KALTURA_SERVICE_URL/service/media/action/addContent" \
  -d "ks=$KALTURA_KS" \
  -d "format=1" \
  -d "entryId=$KALTURA_ENTRY_ID" \
  -d "resource[objectType]=KalturaUrlResource" \
  -d "resource[url]=https://example.com/sample_video.mp4"
```


With custom headers (e.g., for authenticated sources):


```bash
curl -X POST "$KALTURA_SERVICE_URL/service/media/action/addContent" \
  -d "ks=$KALTURA_KS" \
  -d "format=1" \
  -d "entryId=$KALTURA_ENTRY_ID" \
  -d "resource[objectType]=KalturaUrlResource" \
  -d "resource[url]=https://storage.example.com/assets/video.mp4" \
  -d "resource[urlHeaders][0]=Authorization: Bearer YOUR_TOKEN"
```


The URL must point to a direct downloadable file. Streaming manifests (HLS/DASH), redirect URLs (playManifest), and HTML pages cause import failures. Poll `media.get` until status reaches `2` (READY).

**Business scenario — content migration:** A media company migrating from another platform exports a CSV of asset URLs. A script iterates through the CSV, creating entries and attaching URL resources for each, then polls until entries reach READY status.

### Copy from Existing Entry (KalturaEntryResource)

Use `media.add` + `media.addContent` with `KalturaEntryResource` to create a new entry by copying content from an existing one. The new entry gets its own transcoding run.


```bash
curl -X POST "$KALTURA_SERVICE_URL/service/media/action/add" \
  -d "ks=$KALTURA_KS" \
  -d "format=1" \
  -d "entry[objectType]=KalturaMediaEntry" \
  -d "entry[name]=Copy of Original"
```


Then attach the source entry's content:


```bash
curl -X POST "$KALTURA_SERVICE_URL/service/media/action/addContent" \
  -d "ks=$KALTURA_KS" \
  -d "format=1" \
  -d "entryId=$KALTURA_ENTRY_ID" \
  -d "resource[objectType]=KalturaEntryResource" \
  -d "resource[entryId]=$SOURCE_ENTRY_ID" \
  -d "resource[flavorParamsId]=0"
```


Set `resource[flavorParamsId]=0` to copy the original source flavor. Specify a different flavor params ID to copy a specific rendition only.

**Business scenario — multi-tenant content:** A SaaS platform distributes the same training video to multiple customer accounts, each needing independent analytics and access control.

### Copy from Specific Flavor Asset (KalturaAssetResource)

Use `media.addContent` with `KalturaAssetResource` to create a new entry from a specific transcoded rendition of an existing entry. Unlike `KalturaEntryResource` (which references by entry ID + flavor params), this references a flavor asset directly by its ID.

| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| `resource[objectType]` | string | Yes | `KalturaAssetResource` |
| `resource[assetId]` | string | Yes | The flavor asset ID to copy from |


```bash
curl -X POST "$KALTURA_SERVICE_URL/service/media/action/addContent" \
  -d "ks=$KALTURA_KS" \
  -d "format=1" \
  -d "entryId=$KALTURA_ENTRY_ID" \
  -d "resource[objectType]=KalturaAssetResource" \
  -d "resource[assetId]=$FLAVOR_ASSET_ID"
```


**Business scenario — derivative content:** A video platform extracts the audio-only rendition from a lecture recording to create a podcast entry.

### Import via SSH/SFTP (KalturaSshUrlResource)

Use `KalturaSshUrlResource` to import files from SSH/SFTP servers with key authentication.

| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| `resource[objectType]` | string | Yes | `KalturaSshUrlResource` |
| `resource[url]` | string | Yes | SFTP URL (e.g., `sftp://host/path/file.mp4`) |
| `resource[privateKey]` | string | No | SSH private key content |
| `resource[publicKey]` | string | No | SSH public key content |
| `resource[keyPassphrase]` | string | No | Passphrase for the SSH key |


```bash
curl -X POST "$KALTURA_SERVICE_URL/service/media/action/addContent" \
  -d "ks=$KALTURA_KS" \
  -d "format=1" \
  -d "entryId=$KALTURA_ENTRY_ID" \
  -d "resource[objectType]=KalturaSshUrlResource" \
  -d "resource[url]=sftp://media-server.example.com/incoming/video.mp4" \
  -d "resource[privateKey]=$SSH_PRIVATE_KEY" \
  -d "resource[publicKey]=$SSH_PUBLIC_KEY"
```


**Business scenario — broadcast ingest:** A television network's production workflow deposits finished segments on an SFTP server. An automated pipeline picks them up via `KalturaSshUrlResource` for publishing.

### Remote Storage (KalturaRemoteStorageResource)

Use `KalturaRemoteStorageResource` to register content that lives on a configured remote storage profile (e.g., your own S3 bucket or CDN) without downloading it into Kaltura storage. The file stays in place — Kaltura creates a reference to serve it from its current location.

| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| `resource[objectType]` | string | Yes | `KalturaRemoteStorageResource` |
| `resource[url]` | string | Yes | Path/URL on the remote storage |
| `resource[storageProfileId]` | int | Yes | ID of the configured storage profile |


```bash
curl -X POST "$KALTURA_SERVICE_URL/service/media/action/addContent" \
  -d "ks=$KALTURA_KS" \
  -d "format=1" \
  -d "entryId=$KALTURA_ENTRY_ID" \
  -d "resource[objectType]=KalturaRemoteStorageResource" \
  -d "resource[url]=/videos/2024/keynote_1080p.mp4" \
  -d "resource[storageProfileId]=$STORAGE_PROFILE_ID"
```


Requires a storage profile configured on your account (one-time setup by your Kaltura account team). For registering the same content on multiple storage profiles simultaneously, use `KalturaRemoteStorageResources` (plural) with an array of resources.

**Business scenario — hybrid storage:** An enterprise keeps original source files in their own S3 bucket for compliance. They register these with Kaltura for playback and metadata management without moving the files.

### Drop Folder Files (KalturaDropFolderFileResource)

Use `KalturaDropFolderFileResource` to reference a file that arrived through a configured drop folder (FTP, SFTP, S3, or local directory watched by Kaltura).

| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| `resource[objectType]` | string | Yes | `KalturaDropFolderFileResource` |
| `resource[dropFolderFileId]` | int | Yes | ID of the drop folder file object |


```bash
curl -X POST "$KALTURA_SERVICE_URL/service/media/action/addContent" \
  -d "ks=$KALTURA_KS" \
  -d "format=1" \
  -d "entryId=$KALTURA_ENTRY_ID" \
  -d "resource[objectType]=KalturaDropFolderFileResource" \
  -d "resource[dropFolderFileId]=$DROP_FOLDER_FILE_ID"
```


Requires the Drop Folder plugin enabled and a configured drop folder on your account. Files deposited in the drop folder are detected automatically; use this resource type when you need to manually associate a drop folder file with an entry.

### Inline String Content (KalturaStringResource)

Use `KalturaStringResource` to create entries from inline text content. Commonly used for data entries, inline caption content, or metadata files.

| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| `resource[objectType]` | string | Yes | `KalturaStringResource` |
| `resource[content]` | string | Yes | The text content to store |


```bash
curl -X POST "$KALTURA_SERVICE_URL/service/data/action/addContent" \
  -d "ks=$KALTURA_KS" \
  -d "format=1" \
  -d "entryId=$DATA_ENTRY_ID" \
  -d "resource[objectType]=KalturaStringResource" \
  -d "resource[content]={\"config\": \"value\", \"version\": 2}"
```


Also used with `captionAsset.setContent` to set caption text directly:


```bash
curl -X POST "$KALTURA_SERVICE_URL/service/caption_captionAsset/action/setContent" \
  -d "ks=$KALTURA_KS" \
  -d "format=1" \
  -d "id=$CAPTION_ASSET_ID" \
  -d "resource[objectType]=KalturaStringResource" \
  -d "resource[content]=WEBVTT%0A%0A00:00:00.000 --> 00:00:05.000%0AHello world"
```


### Direct File Upload (KalturaUploadedFileResource)

Use `KalturaUploadedFileResource` for a single-request upload where the file is sent as multipart form data directly with the `addContent` call. Simpler than the upload token flow but limited by server upload size limits.


```bash
curl -X POST "$KALTURA_SERVICE_URL/service/media/action/addContent" \
  -F "ks=$KALTURA_KS" \
  -F "format=1" \
  -F "entryId=$KALTURA_ENTRY_ID" \
  -F "resource[objectType]=KalturaUploadedFileResource" \
  -F "resource[fileData]=@/path/to/video.mp4"
```


For files larger than 100 MB, use the upload token workflow (`KalturaUploadedFileTokenResource`) with chunked upload for resumability.

### Clipping, Effects, and Composition (KalturaOperationResource)

Use `KalturaOperationResource` to create entries by extracting a clip (time segment) from existing content. This resource type also supports fade effects, overlays, background replacement, and caption burn-in.

For a quick clip with offset and duration:


```bash
curl -X POST "$KALTURA_SERVICE_URL/service/media/action/addContent" \
  -d "ks=$KALTURA_KS" \
  -d "format=1" \
  -d "entryId=$KALTURA_ENTRY_ID" \
  -d "resource[objectType]=KalturaOperationResource" \
  -d "resource[resource][objectType]=KalturaEntryResource" \
  -d "resource[resource][entryId]=$SOURCE_ENTRY_ID" \
  -d "resource[resource][flavorParamsId]=0" \
  -d "resource[operationAttributes][0][objectType]=KalturaClipAttributes" \
  -d "resource[operationAttributes][0][offset]=60000" \
  -d "resource[operationAttributes][0][duration]=30000"
```


For comprehensive documentation of all editing operations — trim, multi-clip concat, overlays, chroma-key background replacement, caption burn-in, effects, dimension control, and audio mixing — see the **[Video Editing API](/docs/rich-media-cms-apis/content-management/video-editing-overview)**.

### Multi-Clip Concatenation (KalturaOperationResources)

Use `KalturaOperationResources` (plural) to concatenate segments from multiple source entries into a single output. For full documentation including dimension normalization, chapter naming, and advanced composition, see the **[Video Editing API](/docs/rich-media-cms-apis/content-management/video-editing-overview)**.


```bash
curl -X POST "$KALTURA_SERVICE_URL/service/media/action/addContent" \
  -d "ks=$KALTURA_KS" \
  -d "format=1" \
  -d "entryId=$KALTURA_ENTRY_ID" \
  -d "resource[objectType]=KalturaOperationResources" \
  -d "resource[resources][0][objectType]=KalturaOperationResource" \
  -d "resource[resources][0][resource][objectType]=KalturaEntryResource" \
  -d "resource[resources][0][resource][entryId]=$SOURCE_ENTRY_1" \
  -d "resource[resources][0][resource][flavorParamsId]=0" \
  -d "resource[resources][0][operationAttributes][0][objectType]=KalturaClipAttributes" \
  -d "resource[resources][0][operationAttributes][0][offset]=0" \
  -d "resource[resources][0][operationAttributes][0][duration]=10000" \
  -d "resource[resources][1][objectType]=KalturaOperationResource" \
  -d "resource[resources][1][resource][objectType]=KalturaEntryResource" \
  -d "resource[resources][1][resource][entryId]=$SOURCE_ENTRY_2" \
  -d "resource[resources][1][resource][flavorParamsId]=0" \
  -d "resource[resources][1][operationAttributes][0][objectType]=KalturaClipAttributes" \
  -d "resource[resources][1][operationAttributes][0][offset]=0" \
  -d "resource[resources][1][operationAttributes][0][duration]=15000"
```


### Multi-Flavor Ingest (KalturaAssetsParamsResourceContainers)

Use `KalturaAssetsParamsResourceContainers` to ingest multiple pre-transcoded renditions in a single `addContent` call. Each rendition is mapped to a specific flavor params ID.


```bash
curl -X POST "$KALTURA_SERVICE_URL/service/media/action/addContent" \
  -d "ks=$KALTURA_KS" \
  -d "format=1" \
  -d "entryId=$KALTURA_ENTRY_ID" \
  -d "resource[objectType]=KalturaAssetsParamsResourceContainers" \
  -d "resource[resources][0][objectType]=KalturaAssetParamsResourceContainer" \
  -d "resource[resources][0][assetParamsId]=0" \
  -d "resource[resources][0][resource][objectType]=KalturaUrlResource" \
  -d "resource[resources][0][resource][url]=https://example.com/source_original.mp4" \
  -d "resource[resources][1][objectType]=KalturaAssetParamsResourceContainer" \
  -d "resource[resources][1][assetParamsId]=$FLAVOR_PARAMS_720P" \
  -d "resource[resources][1][resource][objectType]=KalturaUrlResource" \
  -d "resource[resources][1][resource][url]=https://example.com/video_720p.mp4" \
  -d "resource[resources][2][objectType]=KalturaAssetParamsResourceContainer" \
  -d "resource[resources][2][assetParamsId]=$FLAVOR_PARAMS_1080P" \
  -d "resource[resources][2][resource][objectType]=KalturaUrlResource" \
  -d "resource[resources][2][resource][url]=https://example.com/video_1080p.mp4"
```


Each `KalturaAssetParamsResourceContainer` maps:
- `assetParamsId` — the target flavor params ID (use `0` for original source, or specific flavor params IDs from your conversion profile)
- `resource` — any content resource type (`KalturaUrlResource`, `KalturaUploadedFileTokenResource`, etc.)

**Business scenario — broadcast workflow:** A broadcaster already has renditions at multiple bitrates from their production pipeline. They ingest all renditions at once, skipping re-transcoding and reducing time-to-publish.

### Entry Statuses

| Value | Name | Description |
|-------|------|-------------|
| -2 | ERROR_IMPORTING | Import failed |
| -1 | ERROR_CONVERTING | Transcoding failed |
| 0 | IMPORT | File being fetched/imported |
| 1 | PRECONVERT | Preparing for transcoding |
| 2 | READY | Fully processed, playable |
| 3 | DELETED | Entry deleted |
| 4 | PENDING | Pending processing |
| 5 | MODERATE | Awaiting moderation |
| 6 | BLOCKED | Blocked by admin |
| 7 | NO_CONTENT | Entry created, no file attached |
| virusScan.Infected | INFECTED | File failed virus scan (requires virusScan plugin) |
| virusScan.ScanFailure | SCAN_FAILURE | Virus scan could not complete |

`KalturaEntryStatus` is a string enum. Core values are numeric strings (`"-2"` through `"7"`), and the virusScan plugin contributes dot-notation values. In practice, passing integer `2` or string `"2"` both work for core statuses in filter parameters. Live stream media types (201-204: LIVE_STREAM_FLASH, LIVE_STREAM_WINDOWS_MEDIA, LIVE_STREAM_REAL_MEDIA, LIVE_STREAM_QUICKTIME) are created via the `liveStream` service — they use `KalturaMediaType`, not entry status.

### Flavor Asset Statuses

When polling flavor assets during transcoding (`flavorAsset.list` with `entryIdEqual`):

| Value | Name | Description |
|-------|------|-------------|
| -1 | ERROR | Transcoding failed for this flavor |
| 0 | QUEUED | Waiting in transcoding queue |
| 1 | CONVERTING | Transcoding in progress |
| 2 | READY | Transcoded and playable |
| 3 | DELETED | Flavor deleted |
| 4 | NOT_APPLICABLE | Flavor params exist but don't apply to this entry |
| 5 | TEMP | Temporary intermediate flavor |
| 6 | WAIT_FOR_CONVERT | Waiting for a dependency flavor to finish |
| 7 | IMPORTING | Source file being imported |
| 8 | VALIDATING | File validation in progress |
| 9 | EXPORTING | Being exported to external storage |

### Entry Moderation Statuses

When content moderation is enabled on the account, entries have a `moderationStatus` field:

| Value | Name | Description |
|-------|------|-------------|
| 1 | PENDING_MODERATION | Awaiting moderator review |
| 2 | APPROVED | Approved for publishing |
| 3 | REJECTED | Rejected by moderator |
| 4 | DELETED | Deleted |
| 5 | FLAGGED_FOR_REVIEW | Flagged by user for review |
| 6 | AUTO_APPROVED | Automatically approved by rules |

For user flagging, moderator approve/reject, AI moderation via REACH, and category-level content gating, see the [Moderation API Guide](/docs/rich-media-cms-apis/content-moderation/moderation-overview).
