---
title: Metadata Instances (CRUD)
url: https://docs.kaltura.com/docs/rich-media-cms-apis/content-management/custom-metadata-metadata-instances-crud
---

## Metadata Instances (CRUD)


A `KalturaMetadata` instance holds the actual XML data conforming to a metadata profile's XSD schema, attached to a specific object. Each object can have at most one metadata instance per profile.

### KalturaMetadata Object

| Field | Type | Description |
|-------|------|-------------|
| `id` | integer | Auto-generated metadata ID (read-only) |
| `metadataProfileId` | integer | Profile this metadata conforms to |
| `metadataProfileVersion` | integer | Profile version this metadata was validated against (read-only, filterable) |
| `objectId` | string | ID of the object this metadata is attached to |
| `objectType` | integer | Type of the object (1=ENTRY, 2=CATEGORY, etc.) |
| `status` | integer | `1` = VALID, `2` = INVALID, `3` = DELETED |
| `xml` | string | The metadata XML content |
| `version` | integer | Version number, incremented on each update (read-only) |
| `partnerId` | integer | Partner ID (read-only) |
| `createdAt` | integer | Unix timestamp (read-only) |
| `updatedAt` | integer | Unix timestamp (read-only) |
| `objectType` | string | Always `"KalturaMetadata"` (read-only) |

### Metadata Status Values

| Value | Name | Description |
|-------|------|-------------|
| 1 | VALID | Metadata XML conforms to its profile XSD |
| 2 | INVALID | Metadata XML failed validation (after XSD change) |
| 3 | DELETED | Soft-deleted |

### Add Metadata (Inline XML)


```
POST /service/metadata_metadata/action/add
```



```bash
curl -X POST "$KALTURA_SERVICE_URL/service/metadata_metadata/action/add" \
  -d "ks=$KALTURA_KS" \
  -d "format=1" \
  -d "metadataProfileId=$PROFILE_ID" \
  -d "objectType=1" \
  -d "objectId=$KALTURA_ENTRY_ID" \
  --data-urlencode 'xmlData=<metadata><Department>Engineering</Department><ProjectName>API Guides</ProjectName><DueDate>1718409600</DueDate><Tag>api</Tag><Tag>docs</Tag></metadata>'
```


| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| `metadataProfileId` | integer | Yes | Profile ID defining the schema |
| `objectType` | integer | Yes | `1`=ENTRY, `2`=CATEGORY, `3`=USER, `4`=PARTNER, `5`=DYNAMIC_OBJECT, `6`=USER_ENTRY |
| `objectId` | string | Yes | ID of the object to attach metadata to |
| `xmlData` | string | Yes | XML data conforming to the profile's XSD |

**Important:** XML field order must match the `<xsd:sequence>` order defined in the profile's XSD. The server validates field ordering against the sequence definition. Field names are case-sensitive.

**Response:**


```json
{
  "id": 67890,
  "partnerId": 123456,
  "metadataProfileId": 12345,
  "metadataProfileVersion": 1,
  "metadataObjectType": 1,
  "objectId": "0_abc123",
  "objectType": "KalturaMetadata",
  "status": 1,
  "version": 1,
  "xml": "<metadata><Department>Engineering</Department><ProjectName>API Guides</ProjectName><DueDate>1718409600</DueDate><Tag>api</Tag><Tag>docs</Tag></metadata>",
  "createdAt": 1718409600,
  "updatedAt": 1718409600
}
```


Each object can have at most one metadata instance per profile. Adding a duplicate returns `METADATA_ALREADY_EXISTS`.

If the profile has an XSLT attached, the server transforms the XML before validation and storage.

### Add from File


```bash
curl -X POST "$KALTURA_SERVICE_URL/service/metadata_metadata/action/addFromFile" \
  -d "ks=$KALTURA_KS" \
  -d "format=1" \
  -d "metadataProfileId=$PROFILE_ID" \
  -d "objectType=1" \
  -d "objectId=$KALTURA_ENTRY_ID" \
  -F "xmlFile=@metadata.xml"
```


| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| `metadataProfileId` | integer | Yes | Profile ID defining the schema |
| `objectType` | integer | Yes | `1`=ENTRY, `2`=CATEGORY, `3`=USER, `4`=PARTNER, `5`=DYNAMIC_OBJECT, `6`=USER_ENTRY |
| `objectId` | string | Yes | ID of the object to attach metadata to |
| `xmlFile` | file | Yes | Metadata XML file upload (multipart form field) |

Same as `add`, but the XML is uploaded as a file. XML field order must match the XSD sequence.

### Add from URL


```bash
curl -X POST "$KALTURA_SERVICE_URL/service/metadata_metadata/action/addFromUrl" \
  -d "ks=$KALTURA_KS" \
  -d "format=1" \
  -d "metadataProfileId=$PROFILE_ID" \
  -d "objectType=1" \
  -d "objectId=$KALTURA_ENTRY_ID" \
  -d "url=https://example.com/metadata/entry_metadata.xml"
```


| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| `metadataProfileId` | integer | Yes | Profile ID defining the schema |
| `objectType` | integer | Yes | `1`=ENTRY, `2`=CATEGORY, `3`=USER, `4`=PARTNER, `5`=DYNAMIC_OBJECT, `6`=USER_ENTRY |
| `objectId` | string | Yes | ID of the object to attach metadata to |
| `url` | string | Yes | URL of the XML file to fetch |

The server fetches the XML from the provided URL, validates against the profile's XSD, and stores it. The same one-per-profile constraint applies.

### Get Metadata


```bash
curl -X POST "$KALTURA_SERVICE_URL/service/metadata_metadata/action/get" \
  -d "ks=$KALTURA_KS" \
  -d "format=1" \
  -d "id=$METADATA_ID"
```


| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| `id` | integer | Yes | Metadata instance ID to retrieve |

Returns the full `KalturaMetadata` object including the XML content. Returns `METADATA_NOT_FOUND` if the instance does not exist.

**Response:**


```json
{
  "id": 67890,
  "partnerId": 123456,
  "metadataProfileId": 12345,
  "metadataProfileVersion": 1,
  "metadataObjectType": 1,
  "objectId": "0_abc123",
  "objectType": "KalturaMetadata",
  "status": 1,
  "version": 1,
  "xml": "<metadata><Department>Engineering</Department><ProjectName>API Guides</ProjectName></metadata>",
  "createdAt": 1718409600,
  "updatedAt": 1718409600
}
```


### List Metadata


```bash
curl -X POST "$KALTURA_SERVICE_URL/service/metadata_metadata/action/list" \
  -d "ks=$KALTURA_KS" \
  -d "format=1" \
  -d "filter[objectType]=KalturaMetadataFilter" \
  -d "filter[objectIdEqual]=$KALTURA_ENTRY_ID" \
  -d "filter[objectTypeEqual]=1" \
  -d "filter[metadataProfileIdEqual]=$PROFILE_ID"
```


| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| `filter[objectType]` | string | Yes | Always `KalturaMetadataFilter` |
| `filter[objectTypeEqual]` | integer | Yes | Object type (`1`=ENTRY, `2`=CATEGORY, etc.). Defaults to ENTRY if null |
| `filter[objectIdEqual]` | string | Conditional | Object ID. **Required** when `objectTypeEqual=1` (ENTRY) |
| `filter[...]` | various | No | Additional filter fields (see table below) |
| `pager[pageSize]` | integer | No | Results per page (default 30, max 500) |
| `pager[pageIndex]` | integer | No | Page number, 1-based (default 1) |

**Filter fields (`KalturaMetadataFilter`):**

| Field | Description |
|-------|-------------|
| `objectIdEqual` / `objectIdIn` | Object ID (REQUIRED for ENTRY type) |
| `objectTypeEqual` | Object type (defaults to ENTRY if null) |
| `metadataProfileIdEqual` / `metadataProfileIdIn` | Filter by profile ID |
| `metadataProfileVersionEqual` / range | Filter by profile version at time of validation |
| `versionEqual` / `versionGreaterThanOrEqual` / `versionLessThanOrEqual` | Filter by metadata version |
| `statusEqual` / `statusIn` | Filter by status (1=VALID, 2=INVALID) |
| `createdAtGreaterThanOrEqual` / `createdAtLessThanOrEqual` | Date range filters |
| `updatedAtGreaterThanOrEqual` / `updatedAtLessThanOrEqual` | Date range filters |
| `orderBy` | `+createdAt`, `-createdAt`, `+updatedAt`, `-updatedAt`, `+metadataProfileVersion`, `-metadataProfileVersion` |

**Important:** When `objectTypeEqual` is null, it defaults to ENTRY. For ENTRY type, always include `objectIdEqual` or `objectIdIn` — the server enforces this with `MUST_FILTER_ON_OBJECT_ID`.

**Response:**


```json
{
  "totalCount": 1,
  "objects": [
    {
      "id": 67890,
      "metadataProfileId": 12345,
      "metadataProfileVersion": 1,
      "objectId": "0_abc123",
      "objectType": 1,
      "status": 1,
      "version": 1,
      "xml": "<metadata><Department>Engineering</Department><ProjectName>API Guides</ProjectName></metadata>",
      "objectType": "KalturaMetadata"
    }
  ],
  "objectType": "KalturaMetadataListResponse"
}
```


### Update Metadata


```bash
curl -X POST "$KALTURA_SERVICE_URL/service/metadata_metadata/action/update" \
  -d "ks=$KALTURA_KS" \
  -d "format=1" \
  -d "id=$METADATA_ID" \
  --data-urlencode 'xmlData=<metadata><Department>Marketing</Department><ProjectName>API Guides</ProjectName><DueDate>1718409600</DueDate></metadata>'
```


| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| `id` | integer | Yes | Metadata instance ID |
| `xmlData` | string | Yes | Updated XML conforming to the profile's XSD. Field order must match XSD sequence |
| `version` | integer | No | Optimistic lock — update succeeds only if this matches the current version |

**Optimistic locking:** Pass the `version` parameter to prevent concurrent update conflicts. If the metadata was modified by another process since you read it, the server returns `INVALID_METADATA_VERSION`. Read the latest version, merge changes, and retry.


```bash
# Optimistic lock example — update only if version is still 3
curl -X POST "$KALTURA_SERVICE_URL/service/metadata_metadata/action/update" \
  -d "ks=$KALTURA_KS" \
  -d "format=1" \
  -d "id=$METADATA_ID" \
  -d "version=3" \
  --data-urlencode 'xmlData=<metadata><Department>Marketing</Department></metadata>'
```


**Response:** Full updated `KalturaMetadata` object with incremented `version`.

### Update from File


```bash
curl -X POST "$KALTURA_SERVICE_URL/service/metadata_metadata/action/updateFromFile" \
  -d "ks=$KALTURA_KS" \
  -d "format=1" \
  -d "id=$METADATA_ID" \
  -F "xmlFile=@updated_metadata.xml"
```


| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| `id` | integer | Yes | Metadata instance ID to update |
| `xmlFile` | file | Yes | Updated metadata XML file (multipart form field) |

Same as `update`, but the XML is uploaded as a file. XML field order must match the XSD sequence.

### Update via XSLT


```bash
curl -X POST "$KALTURA_SERVICE_URL/service/metadata_metadata/action/updateFromXSL" \
  -d "ks=$KALTURA_KS" \
  -d "format=1" \
  -d "id=$METADATA_ID" \
  -F "xslFile=@transform.xsl"
```


| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| `id` | integer | Yes | Metadata instance ID to transform |
| `xslFile` | file | Yes | XSLT stylesheet file (multipart form field) |

Applies a one-time XSLT transformation to the existing metadata XML. The server reads the current XML, transforms it using the provided XSL file, validates the result against the profile XSD, and saves. Uses locking (`kLock::runLocked`) for concurrency safety. This is different from the profile-level XSLT (section 7) which auto-applies on every add/update.

### Serve (Raw XML)


```bash
curl -X POST "$KALTURA_SERVICE_URL/service/metadata_metadata/action/serve" \
  -d "ks=$KALTURA_KS" \
  -d "format=1" \
  -d "id=$METADATA_ID"
```


| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| `id` | integer | Yes | Metadata instance ID whose raw XML to serve |

Returns the raw XML content of the metadata instance. Useful for programmatic XML processing without the surrounding `KalturaMetadata` object fields.

### Delete Metadata


```bash
curl -X POST "$KALTURA_SERVICE_URL/service/metadata_metadata/action/delete" \
  -d "ks=$KALTURA_KS" \
  -d "format=1" \
  -d "id=$METADATA_ID"
```


| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| `id` | integer | Yes | Metadata instance ID to delete |

Deletes the metadata instance. Does not affect the metadata profile or the object it was attached to.
