Kaltura App Registry API¶
The App Registry is a centralized service for registering and managing Kaltura application instances — KMS sites, Events Platform instances, custom applications, and more. Each registered app gets a unique GUID (id) used by other platform services (such as the User Profile API) to associate data with specific application contexts.
When you create a virtual event through the Events Platform, an app is automatically registered with appType: "epmEvent". You can also register apps directly for custom integrations.
Base URL: https://app-registry.nvp1.ovp.kaltura.com/api/v1 (production NVP region)
Auth: Authorization: Bearer <KS> header (ADMIN KS, type=2, requires ADMIN_BASE permission)
Format: JSON request/response bodies, all endpoints use POST
Regions: NVP (default nvp1), EU (irp2), DE (frp2)
1. When to Use¶
- Partner application management — Platform administrators registering and tracking all application instances (KMS sites, Events Platform portals, custom integrations) across the organization
- SSO and domain-based routing — Developers configuring organization domain bindings so users are automatically directed to the correct application instance based on their email domain
- Developer app lifecycle — Development teams registering custom application instances, enabling/disabling them across environments, and syncing app metadata with external systems
- Cross-service context linking — Backend systems resolving virtual event IDs to app GUIDs for use with the User Profile API, Messaging API, and other services that associate data with specific application contexts
2. Prerequisites¶
- An ADMIN KS (type=2) with
ADMIN_BASEpermission for all write operations, orANALYTICS_BASEfor read-only list access (see Session Guide) - A Kaltura account with App Registry access enabled
- For production integrations, use AppTokens for secure KS generation (see AppTokens API)
3. Authentication¶
All requests require an ADMIN KS (type=2) with ADMIN_BASE permission in the Authorization header:
The list endpoint also accepts KS with ANALYTICS_BASE permission.
Generate an ADMIN KS via session.start (see Session Guide) or appToken.startSession (see AppTokens Guide).
# Set up environment
export KALTURA_APP_REGISTRY_URL="https://app-registry.nvp1.ovp.kaltura.com/api/v1"
4. App Entity¶
Every registered application has this structure:
| Field | Type | Description |
|---|---|---|
id |
string | Auto-generated GUID (read-only) |
partnerId |
integer | Partner ID extracted from KS (read-only) |
appCustomId |
string | Your custom identifier for this app instance |
appCustomName |
string | Display name for the app instance |
appType |
string | Application type (see enum below) |
status |
string | enabled or disabled |
version |
integer | Starts at 0, increments on each update (read-only) |
createdAt |
string | ISO 8601 timestamp, e.g. "2026-04-09T04:56:27.940Z" (read-only) |
updatedAt |
string | ISO 8601 timestamp, e.g. "2026-04-09T04:56:27.940Z" (read-only) |
organizationDomain |
object | Optional organization/domain binding |
objectType |
string | Always "App" in responses (read-only) |
4.1 App Types¶
| Value | Description |
|---|---|
kms |
Kaltura MediaSpace (KMS) |
kmc |
Kaltura Management Console |
ep |
Events Platform |
sites |
Kaltura Sites |
pitch |
Kaltura Pitch |
test |
Test application |
games |
Kaltura Games |
empAccount |
Employee account |
epmEvent |
Events Platform Manager — Event (auto-created when a virtual event is created) |
epmSystem |
Events Platform Manager — System |
mr |
Meeting Room |
kalturaServer |
Kaltura Server |
4.2 Organization Domain¶
Optional object for binding an app instance to a specific domain and organization:
| Field | Type | Required | Description |
|---|---|---|---|
organizationId |
string | No | Organization identifier (max 255 chars) |
domain |
string | Yes | Domain name (max 255 chars, comma-separated for multiple). Whitespace is automatically stripped. |
5. Register an App¶
{
"appCustomId": "my-events-site-01",
"appType": "ep",
"appCustomName": "Annual Conference Portal"
}
| Field | Type | Required | Description |
|---|---|---|---|
appCustomId |
string | Yes | Custom identifier (unique per partner) |
appType |
string | Yes | Application type (see section 4.1) |
appCustomName |
string | Yes | Display name |
organizationDomain |
object | No | Domain binding (see section 4.2) |
The status is always set to "enabled" on creation (cannot be overridden). The version starts at 0. The partnerId is extracted from the KS — it cannot be set in the request body.
Response: Full app object with generated id.
{
"id": "6f8a3c12-4b5d-4e9f-a1c7-8d2e3f4a5b6c",
"partnerId": 1234567,
"appCustomId": "my-events-site-01",
"appCustomName": "Annual Conference Portal",
"appType": "ep",
"status": "enabled",
"version": 0,
"createdAt": "2026-04-09T04:56:27.940Z",
"updatedAt": "2026-04-09T04:56:27.940Z",
"objectType": "App"
}
curl -X POST "$KALTURA_APP_REGISTRY_URL/app-registry/add" \
-H "Authorization: Bearer $KALTURA_KS" \
-H "Content-Type: application/json" \
-d '{
"appCustomId": "my-events-site-01",
"appType": "ep",
"appCustomName": "Annual Conference Portal"
}'
Save the id from the response — this is the appGuid used by other services like the User Profile API.
Uniqueness Constraints¶
appCustomIdmust be unique within your partner account- If
organizationDomainis provided, the combination oforganizationId+domain+appTypemust be globally unique. Each comma-separated domain in thedomainfield is validated individually.
Error Codes¶
| Code | Meaning |
|---|---|
APP_REGISTRY_ALREADY_EXISTS_WITH_THIS_APP_CUSTOM_ID |
Duplicate appCustomId for your partner |
ORGANIZATION_ID_DOMAIN_AND_APP_TYPE_MUST_BE_UNIQUE |
Domain/org/type combination already exists |
6. Get an App¶
| Field | Type | Required | Description |
|---|---|---|---|
id |
string | Yes | App GUID to retrieve |
Response: Full app object.
{
"id": "6f8a3c12-4b5d-4e9f-a1c7-8d2e3f4a5b6c",
"partnerId": 1234567,
"appCustomId": "my-events-site-01",
"appCustomName": "Annual Conference Portal",
"appType": "ep",
"status": "enabled",
"version": 0,
"createdAt": "2026-04-09T04:56:27.940Z",
"updatedAt": "2026-04-09T04:56:27.940Z",
"objectType": "App"
}
curl -X POST "$KALTURA_APP_REGISTRY_URL/app-registry/get" \
-H "Authorization: Bearer $KALTURA_KS" \
-H "Content-Type: application/json" \
-d "{\"id\": \"$APP_GUID\"}"
Returns OBJECT_NOT_FOUND if the app does not exist or belongs to a different partner.
7. Update an App¶
| Field | Type | Required | Description |
|---|---|---|---|
id |
string | Yes | App GUID to update |
appCustomId |
string | No | Updated custom identifier |
appCustomName |
string | No | Updated display name |
appType |
string | No | Updated app type |
organizationDomain |
object | No | Updated domain binding |
Fields not included in the request body (or set to null) remain unchanged. The partnerId, status, version, createdAt, and updatedAt fields cannot be set — status is managed via enable/disable, version auto-increments.
Response: Full app object with version incremented by 1 and updatedAt refreshed.
{
"id": "6f8a3c12-4b5d-4e9f-a1c7-8d2e3f4a5b6c",
"partnerId": 1234567,
"appCustomId": "my-events-site-01",
"appCustomName": "Updated Conference Portal",
"appType": "ep",
"status": "enabled",
"version": 1,
"createdAt": "2026-04-09T04:56:27.940Z",
"updatedAt": "2026-04-09T05:12:44.310Z",
"objectType": "App"
}
curl -X POST "$KALTURA_APP_REGISTRY_URL/app-registry/update" \
-H "Authorization: Bearer $KALTURA_KS" \
-H "Content-Type: application/json" \
-d "{
\"id\": \"$APP_GUID\",
\"appCustomName\": \"Updated Conference Portal\"
}"
8. Delete an App¶
Permanently removes the app registration.
| Field | Type | Required | Description |
|---|---|---|---|
id |
string | Yes | App GUID to delete |
Response: Empty body on success (HTTP 200). Returns OBJECT_NOT_FOUND if the app does not exist for your partner.
curl -X POST "$KALTURA_APP_REGISTRY_URL/app-registry/delete" \
-H "Authorization: Bearer $KALTURA_KS" \
-H "Content-Type: application/json" \
-d "{\"id\": \"$APP_GUID\"}"
9. Enable / Disable an App¶
Toggle an app's status without deleting it. Disabled apps remain in the registry but are excluded from list results when filtering by status: "enabled".
9.1 Enable¶
curl -X POST "$KALTURA_APP_REGISTRY_URL/app-registry/enable" \
-H "Authorization: Bearer $KALTURA_KS" \
-H "Content-Type: application/json" \
-d "{\"id\": \"$APP_GUID\"}"
9.2 Disable¶
curl -X POST "$KALTURA_APP_REGISTRY_URL/app-registry/disable" \
-H "Authorization: Bearer $KALTURA_KS" \
-H "Content-Type: application/json" \
-d "{\"id\": \"$APP_GUID\"}"
Both endpoints accept a single parameter:
| Parameter | Type | Required | Description |
|---|---|---|---|
id |
string | Yes | App GUID to enable or disable |
Response: Full app object with updated status.
{
"id": "6f8a3c12-4b5d-4e9f-a1c7-8d2e3f4a5b6c",
"partnerId": 1234567,
"appCustomId": "my-events-site-01",
"appCustomName": "Annual Conference Portal",
"appType": "ep",
"status": "disabled",
"version": 2,
"createdAt": "2026-04-09T04:56:27.940Z",
"updatedAt": "2026-04-09T05:30:12.880Z",
"objectType": "App"
}
The version increments only if the status actually changed. Enabling an already-enabled app (or disabling an already-disabled one) returns the current state without incrementing version.
10. List Apps¶
All filter fields are optional. If no filter is provided, all apps for your partner are returned.
10.1 Filter Fields¶
| Field | Type | Description |
|---|---|---|
idIn |
string[] | Filter by app GUIDs. Invalid IDs are silently ignored; if all IDs are invalid, returns empty results. |
appCustomIdIn |
string[] | Filter by custom IDs |
appCustomNameIn |
string[] | Filter by custom names |
appType |
string | Filter by app type |
status |
string | enabled or disabled |
domain |
string | Filter by organization domain |
organizationId |
string | Filter by organization ID |
createdAtGreaterThanOrEqual |
string | ISO 8601 minimum creation date |
createdAtLessThanOrEqual |
string | ISO 8601 maximum creation date |
updatedAtGreaterThanOrEqual |
string | ISO 8601 minimum update date |
updatedAtLessThanOrEqual |
string | ISO 8601 maximum update date |
10.2 Pager¶
| Field | Type | Default | Constraints | Description |
|---|---|---|---|---|
offset |
integer | 0 | min: 0 | Number of records to skip |
limit |
integer | 30 | min: 1, max: 5000 | Maximum records to return |
If the pager is omitted entirely, defaults of offset: 0, limit: 30 are used.
Response:
{
"objects": [
{
"id": "6f8a3c12-4b5d-4e9f-a1c7-8d2e3f4a5b6c",
"partnerId": 1234567,
"appCustomId": "my-events-site-01",
"appCustomName": "Annual Conference Portal",
"appType": "ep",
"status": "enabled",
"version": 0,
"createdAt": "2026-04-09T04:56:27.940Z",
"updatedAt": "2026-04-09T04:56:27.940Z",
"objectType": "App"
}
],
"totalCount": 42
}
# List all enabled Events Platform apps
curl -X POST "$KALTURA_APP_REGISTRY_URL/app-registry/list" \
-H "Authorization: Bearer $KALTURA_KS" \
-H "Content-Type: application/json" \
-d '{
"filter": {
"appType": "ep",
"status": "enabled"
},
"pager": {
"offset": 0,
"limit": 50
}
}'
11. Find Apps by Organization Domain¶
Look up app instances bound to a specific domain and app type.
POST /api/v1/app-registry/findByOrganizationDomain
Content-Type: application/json
Authorization: Bearer <KS>
| Field | Type | Required | Description |
|---|---|---|---|
domain |
string | Yes | Domain to search (max 255 chars, whitespace auto-stripped) |
appType |
string | Yes | App type to filter by |
organizationId |
string | No | Organization to filter by |
pager |
object | No | Pagination (offset/limit, same defaults as list) |
Response: Same { objects, totalCount } structure as list:
{
"objects": [
{
"id": "a2b3c4d5-6e7f-8a9b-0c1d-2e3f4a5b6c7d",
"partnerId": 1234567,
"appCustomId": "kms-main",
"appCustomName": "Corporate MediaSpace",
"appType": "kms",
"status": "enabled",
"version": 3,
"organizationDomain": {
"organizationId": "org-123",
"domain": "example.com"
},
"createdAt": "2026-03-15T10:22:00.000Z",
"updatedAt": "2026-04-01T14:30:00.000Z",
"objectType": "App"
}
],
"totalCount": 1
}
The domain search supports comma-separated domain lists in app records — a search for example.com matches apps registered with example.com, example.com,other.com, etc.
curl -X POST "$KALTURA_APP_REGISTRY_URL/app-registry/findByOrganizationDomain" \
-H "Authorization: Bearer $KALTURA_KS" \
-H "Content-Type: application/json" \
-d '{
"domain": "example.com",
"appType": "kms"
}'
12. Versioning¶
Each app record has a version field (starts at 0). The version increments by 1 on each successful update, enable, or disable call that changes the record. Use versioning to detect concurrent modifications — if you read an app at version 3 and update it, the response returns version 4.
The version does NOT increment if an enable/disable call matches the current status (idempotent no-op).
13. Error Handling¶
Application-level errors return HTTP 200 with an error object:
Validation errors (missing required fields, invalid enum values) return HTTP 400:
{
"code": "VALIDATION_ERROR",
"message": "appCustomId is required",
"objectType": "KalturaAPIException"
}
| Error Code | Meaning |
|---|---|
OBJECT_NOT_FOUND |
App not found for your partner |
APP_REGISTRY_ALREADY_EXISTS_WITH_THIS_APP_CUSTOM_ID |
Duplicate appCustomId |
ORGANIZATION_ID_DOMAIN_AND_APP_TYPE_MUST_BE_UNIQUE |
Domain/org/type combination already taken |
APP_CANNOT_BE_ASSIGNED_TO_PARTNER |
Invalid app type for your partner |
UNKNOWN_PARTNER_ID |
KS does not contain a valid partner ID |
Retry strategy: For transient errors (HTTP 5xx, timeouts), retry with exponential backoff: 1s, 2s, 4s, with jitter, up to 3 retries. For client errors (HTTP 400, OBJECT_NOT_FOUND, APP_REGISTRY_ALREADY_EXISTS_WITH_THIS_APP_CUSTOM_ID), fix the request before retrying — these will not resolve on their own.
14. Common Integration Patterns¶
14.1 Virtual Event ID to App GUID Mapping¶
When the Events Platform creates a virtual event, it automatically registers an app in the App Registry with appType: "epmEvent" and sets the appCustomId to the virtual event ID. This is the primary cross-service linkage — to work with registration data for a specific event, resolve the virtual event ID to an appGuid first:
# Step 1: Get the virtual event ID
# (from virtualEvent_virtualEvent/action/list or an existing workflow)
VIRTUAL_EVENT_ID="12345"
# Step 2: Resolve to App GUID via appCustomIdIn filter
APP_GUID=$(curl -s -X POST "$KALTURA_APP_REGISTRY_URL/app-registry/list" \
-H "Authorization: Bearer $KALTURA_KS" \
-H "Content-Type: application/json" \
-d "{
\"filter\": {
\"appCustomIdIn\": [\"$VIRTUAL_EVENT_ID\"]
},
\"pager\": {\"offset\": 0, \"limit\": 1}
}" | jq -r '.objects[0].id')
echo "App GUID for event $VIRTUAL_EVENT_ID: $APP_GUID"
# Use this APP_GUID with the User Profile API to get registration/attendance data
The appCustomIdIn filter accepts an array, so you can resolve multiple events in a single call:
# Resolve multiple virtual events at once
curl -s -X POST "$KALTURA_APP_REGISTRY_URL/app-registry/list" \
-H "Authorization: Bearer $KALTURA_KS" \
-H "Content-Type: application/json" \
-d '{
"filter": {
"appCustomIdIn": ["12345", "12346", "12347"]
}
}'
14.2 Register App for Custom Integration¶
For custom integrations outside the Events Platform, register apps explicitly:
APP_GUID=$(curl -s -X POST "$KALTURA_APP_REGISTRY_URL/app-registry/add" \
-H "Authorization: Bearer $KALTURA_KS" \
-H "Content-Type: application/json" \
-d '{
"appCustomId": "annual-conference-2025",
"appType": "ep",
"appCustomName": "Annual Conference 2025"
}' | jq -r '.id')
echo "App GUID: $APP_GUID"
14.3 Register App -> Manage User Profiles¶
The User Profile API associates user data with specific app instances. The appGuid parameter in user profile operations must reference a registered, enabled app:
# Use the app GUID from registration when creating user profiles
curl -X POST "$KALTURA_USER_PROFILE_URL/user-profile/add" \
-H "Authorization: Bearer $KALTURA_KS" \
-H "Content-Type: application/json" \
-d "{
\"appGuid\": \"$APP_GUID\",
\"userId\": \"user@example.com\",
\"profileData\": {\"name\": \"Jane Doe\"}
}"
The User Profile service validates that the appGuid exists and is enabled in the App Registry. Validation results are cached for up to 24 hours — if you disable or delete an app, existing user profile operations may continue to work briefly.
14.4 Cross-Service Registration Data Retrieval¶
The full flow for extracting event registration and attendance data spans four services:
# Step 1: List virtual events
curl -s -X POST "$KALTURA_SERVICE_URL/service/virtualevent_virtualevent/action/list" \
-d "ks=$KALTURA_KS" -d "format=1" | jq '.objects[] | {id, name}'
# → Get virtual event IDs
# Step 2: Resolve virtual event ID → App GUID
APP_GUID=$(curl -s -X POST "$KALTURA_APP_REGISTRY_URL/app-registry/list" \
-H "Authorization: Bearer $KALTURA_KS" \
-H "Content-Type: application/json" \
-d "{\"filter\": {\"appCustomIdIn\": [\"$VIRTUAL_EVENT_ID\"]}}" \
| jq -r '.objects[0].id')
# Step 3: Get registration/attendance data from User Profile
curl -s -X POST "$KALTURA_USER_PROFILE_URL/user-profile/list" \
-H "Authorization: Bearer $KALTURA_KS" \
-H "Content-Type: application/json" \
-d "{
\"filter\": {\"appGuidIn\": [\"$APP_GUID\"]},
\"pager\": {\"offset\": 0, \"limit\": 500},
\"orderBy\": \"createdAt\",
\"includeTotalCount\": true
}"
# → eventData has attendance status, profileData has registration form fields
# Step 4: Join with core user data (email, name, company)
# Extract userIds from step 3, then call user.list
USER_IDS="user1@example.com,user2@example.com"
curl -s -X POST "$KALTURA_SERVICE_URL/service/user/action/list" \
-d "ks=$KALTURA_KS" -d "format=1" \
-d "filter[objectType]=KalturaUserFilter" \
-d "filter[idIn]=$USER_IDS"
# → firstName, lastName, email, company, jobTitle, country, state
For incremental syncs, use updatedAtGreaterThanOrEqual in both App Registry list and User Profile list filters to pull only records changed since your last sync.
14.5 Incremental Data Sync¶
Use date filters for efficient delta pulls instead of full data dumps:
# Pull only apps updated since yesterday
curl -s -X POST "$KALTURA_APP_REGISTRY_URL/app-registry/list" \
-H "Authorization: Bearer $KALTURA_KS" \
-H "Content-Type: application/json" \
-d '{
"filter": {
"updatedAtGreaterThanOrEqual": "2025-06-14T00:00:00Z",
"appType": "epmEvent"
},
"pager": {"offset": 0, "limit": 500}
}'
Store the last record's updatedAt timestamp as a watermark and use it as the start of the next sync window.
15. Best Practices¶
- Use
appCustomIdfor external system mapping. Map virtual event IDs or external identifiers to app GUIDs for cross-service lookups (e.g., Events Platform auto-registers withappCustomId= virtual event ID). - Track
versionnumbers for concurrency detection. The version increments on each state change — use it to detect concurrent modifications. - Enable apps after configuration is complete. Create and configure first, then enable — other services (User Profile, Messaging) only interact with enabled apps.
- Use the delta sync pattern for production integrations. Filter by
updatedAtrange and paginate to keep your system in sync without full re-scans. - Use AppTokens for production access. Generate KS via
appToken.startSessionwith HMAC — keep admin secrets off application servers.
16. Related Guides¶
- Session Guide — KS generation and management
- AppTokens API — Secure server-to-server auth
- User Profile API — Per-app user profile management (depends on App Registry)
- Events Platform API — Virtual events (auto-creates app registrations)
- Messaging API — Template-based email messaging (uses appGuid for message context)
- Webhooks API — Event-driven HTTP callbacks and email notifications
- Auth Broker — App subscriptions link auth profiles to registered apps