Skip to main content
View as Markdown

Content Distribution - Integration

Kaltura Content Distribution API​

Kaltura's content distribution system pushes media to external platforms (YouTube, Facebook, FTP servers, cross-Kaltura accounts) via configurable connectors. Distribution profiles define how and when content is pushed to each target platform. Entry distributions track the per-entry lifecycle through a state machine — from validation and submission to status monitoring and error recovery.

Base URL: https://www.kaltura.com/api_v3 (may differ by region/deployment)
Auth: KS passed as ks parameter in POST form data (see Session Guide)
Format: Form-encoded POST, format=1 for JSON responses
Services: contentDistribution_distributionProvider, contentDistribution_distributionProfile, contentDistribution_entryDistribution, contentDistribution_genericDistributionProvider, contentDistribution_genericDistributionProviderAction

1. When to Use​

  • Multi-platform content syndication — Media teams publishing video content simultaneously to YouTube, Facebook, Dailymotion, and other platforms from a single source of truth in Kaltura
  • Cross-account content sharing — Organizations synchronizing content between multiple Kaltura accounts (e.g., from a central production account to regional or departmental accounts)
  • Automated publishing workflows — Operations teams configuring rules that automatically distribute content to external platforms when entries are approved, reach a scheduled sunrise date, or match specific metadata criteria
  • FTP/SFTP content delivery — Enterprise teams pushing video files and metadata to partner systems, archive servers, or CDN origins via automated FTP distribution

2. Prerequisites​

  • A Kaltura account with the Content Distribution plugin enabled (contact your Kaltura account manager if distribution actions return SERVICE_FORBIDDEN)
  • An ADMIN KS (type=2) with disableentitlement privilege for full distribution management
  • At least one distribution profile configured (YouTube API, FTP, Cross-Kaltura, etc.)

3. Core Concepts​

3.1 Distribution Workflow​

  1. Configure a distribution profile — defines the target platform, credentials, and automation rules
  2. Bind an entry to a profile — creates an entryDistribution record linking the entry to the profile
  3. Validate — checks that the entry meets the profile's requirements (flavors, thumbnails, metadata)
  4. Submit — pushes the entry to the remote platform; status tracks progress through the state machine
  5. Monitor — track status changes, dirty flags (content updated), and sunrise/sunset scheduling

3.2 Service Name Prefix​

Distribution services use the contentDistribution_ plugin prefix:

ServiceFull API Service Name
Distribution ProvidercontentDistribution_distributionProvider
Distribution ProfilecontentDistribution_distributionProfile
Entry DistributioncontentDistribution_entryDistribution

4. Distribution Providers​

4.1 Provider Types​

Distribution providers define the available connector types. Providers are system-level (partner 0) and include built-in connectors for major platforms.

Key provider types:

Provider TypeNameDescription
1 (Generic)GenericCustom XSLT-based distribution
2 (Syndication)SyndicationFeed-based distribution bridge
youtubeApiDistribution.YOUTUBE_APIYouTube APIYouTube channel push via OAuth
facebookDistribution.FACEBOOKFacebookFacebook page push via OAuth
crossKalturaDistribution.CROSS_KALTURACross-KalturaMulti-account content sync
ftpDistribution.FTPFTPFTP/SFTP/SCP/HTTPS/Aspera file push
ftpDistribution.FTP_SCHEDULEDFTP ScheduledScheduled FTP push
podcastDistribution.PODCASTPodcastPodcast RSS distribution
dailymotionDistribution.DAILYMOTIONDailymotionVideo platform
doubleClickDistribution.DOUBLECLICKDoubleClickDFP/GAM ad monetization
cortexApiDistribution.CORTEX_APICortex APICortex API connector
tvinciDistribution.TVINCITvinciOTT/Tvinci platform

4.2 distributionProvider.list​

List all available distribution provider types on the account:

curl -X POST "$KALTURA_SERVICE_URL/service/contentDistribution_distributionProvider/action/list" \
-d "ks=$KALTURA_KS" \
-d "format=1"

Response includes provider objects with type, name, and objectType identifying the connector:

{
"objects": [
{
"type": 1,
"name": "Default",
"objectType": "KalturaGenericDistributionProvider"
},
{
"type": "youtubeApiDistribution.YOUTUBE_API",
"name": "YoutubeApi",
"objectType": "KalturaYoutubeApiDistributionProvider"
}
],
"totalCount": 33,
"objectType": "KalturaDistributionProviderListResponse"
}

5. Distribution Profile Management​

Distribution profiles configure how content is distributed to a specific target platform. Each profile specifies the provider type, automation rules (automatic vs manual submit/update/delete), required assets, and provider-specific settings.

5.1 Profile Object Fields​

Base fields (all KalturaDistributionProfile subtypes):

FieldTypeDescription
idintProfile ID (auto-assigned)
namestringDisplay name
statusint1=DISABLED, 2=ENABLED
providerTypestringProvider identifier (e.g., youtubeApiDistribution.YOUTUBE_API)
submitEnabledint1=DISABLED, 2=AUTOMATIC, 3=MANUAL
updateEnabledint1=DISABLED, 2=AUTOMATIC, 3=MANUAL
deleteEnabledint1=DISABLED, 2=AUTOMATIC, 3=MANUAL
reportEnabledint1=DISABLED, 2=AUTOMATIC
requiredFlavorParamsIdsstringComma-separated flavor params IDs required (e.g., "0" = source)
optionalFlavorParamsIdsstringComma-separated optional flavor params IDs
requiredThumbDimensionsarrayRequired thumbnail sizes
optionalThumbDimensionsarrayOptional thumbnail sizes
autoCreateFlavorsboolAuto-create missing flavors during validation
autoCreateThumbboolAuto-create missing thumbnails during validation
distributeTriggerint1=ENTRY_READY, 2=MODERATION_APPROVED
sunriseDefaultOffsetintDefault sunrise offset in seconds
sunsetDefaultOffsetintDefault sunset offset in seconds

Action status values:

ValueNameDescription
1DISABLEDAction is off
2AUTOMATICTriggered automatically when conditions are met
3MANUALRequires an explicit API call

5.2 distributionProfile.add​

Create a new distribution profile. The objectType and provider-specific fields vary by connector type.

Parameters:

ParameterTypeRequiredDescription
partnerIdintYesYour partner ID (must be in the request body, not just the KS)
distributionProfile[objectType]stringYesProfile class (e.g., KalturaYoutubeApiDistributionProfile, KalturaFtpDistributionProfile, KalturaCrossKalturaDistributionProfile, KalturaGenericDistributionProfile)
distributionProfile[name]stringYesDisplay name
distributionProfile[status]intNo1=DISABLED (default), 2=ENABLED
distributionProfile[submitEnabled]intNo1=DISABLED, 2=AUTOMATIC, 3=MANUAL
distributionProfile[updateEnabled]intNo1=DISABLED, 2=AUTOMATIC, 3=MANUAL
distributionProfile[deleteEnabled]intNo1=DISABLED, 2=AUTOMATIC, 3=MANUAL
distributionProfile[reportEnabled]intNo1=DISABLED, 2=AUTOMATIC
distributionProfile[distributeTrigger]intNo1=ENTRY_READY, 2=MODERATION_APPROVED
distributionProfile[requiredFlavorParamsIds]stringNoComma-separated required flavor params IDs (e.g., "0" for source)
distributionProfile[optionalFlavorParamsIds]stringNoComma-separated optional flavor params IDs
distributionProfile[autoCreateFlavors]boolNoAuto-create missing flavors during validation
distributionProfile[autoCreateThumb]boolNoAuto-create missing thumbnails during validation
distributionProfile[sunriseDefaultOffset]intNoDefault sunrise offset in seconds
distributionProfile[sunsetDefaultOffset]intNoDefault sunset offset in seconds

Additional provider-specific fields depend on the objectType (see section 8 for connector-specific fields).

curl -X POST "$KALTURA_SERVICE_URL/service/contentDistribution_distributionProfile/action/add" \
-d "ks=$KALTURA_KS" \
-d "format=1" \
-d "partnerId=$KALTURA_PARTNER_ID" \
-d "distributionProfile[objectType]=KalturaYoutubeApiDistributionProfile" \
-d "distributionProfile[name]=My YouTube Channel" \
-d "distributionProfile[submitEnabled]=3" \
-d "distributionProfile[updateEnabled]=2" \
-d "distributionProfile[deleteEnabled]=2" \
-d "distributionProfile[reportEnabled]=1" \
-d "distributionProfile[distributeTrigger]=1" \
-d "distributionProfile[requiredFlavorParamsIds]=0" \
-d "distributionProfile[defaultCategory]=22" \
-d "distributionProfile[allowComments]=allowed" \
-d "distributionProfile[allowEmbedding]=allowed" \
-d "distributionProfile[allowRatings]=allowed"

The partnerId parameter is required in the request body. The distribution plugin uses the request-level partnerId (not the KS) to associate the profile with your account. Omitting it creates an orphaned profile that cannot be retrieved.

Profile creation requires provider-specific configuration (OAuth credentials for YouTube/Facebook, connection details for FTP, target account details for Cross-Kaltura). Profiles are typically configured through the Rich Media CMS (KMC) and then managed via API.

5.3 distributionProfile.get​

Retrieve a distribution profile by ID.

ParameterTypeRequiredDescription
idintYesDistribution profile ID
curl -X POST "$KALTURA_SERVICE_URL/service/contentDistribution_distributionProfile/action/get" \
-d "ks=$KALTURA_KS" \
-d "format=1" \
-d "id=$DISTRIBUTION_PROFILE_ID"

Response includes all base fields plus provider-specific fields:

{
"id": 413741,
"name": "YouTube Distribution Demo",
"providerType": "youtubeApiDistribution.YOUTUBE_API",
"status": 2,
"submitEnabled": 3,
"updateEnabled": 3,
"deleteEnabled": 2,
"requiredFlavorParamsIds": "0",
"distributeTrigger": 1,
"defaultCategory": 24,
"allowComments": "allowed",
"allowEmbedding": "allowed",
"objectType": "KalturaYoutubeApiDistributionProfile"
}

5.4 distributionProfile.list​

List distribution profiles with optional filters.

Filter parameters (all optional, use filter[objectType]=KalturaDistributionProfileFilter):

ParameterTypeDescription
filter[statusEqual]intFilter by status: 1=DISABLED, 2=ENABLED
filter[idEqual]intFilter by specific profile ID
filter[idIn]stringComma-separated profile IDs
filter[providerTypeEqual]stringFilter by provider type (e.g., youtubeApiDistribution.YOUTUBE_API)
pager[pageSize]intResults per page (default 30)
pager[pageIndex]intPage number (1-based)

Response: {objects: [...], totalCount: N, objectType: "KalturaDistributionProfileListResponse"}

curl -X POST "$KALTURA_SERVICE_URL/service/contentDistribution_distributionProfile/action/list" \
-d "ks=$KALTURA_KS" \
-d "format=1"

Filter by status:

curl -X POST "$KALTURA_SERVICE_URL/service/contentDistribution_distributionProfile/action/list" \
-d "ks=$KALTURA_KS" \
-d "format=1" \
-d "filter[objectType]=KalturaDistributionProfileFilter" \
-d "filter[statusEqual]=2"

5.5 distributionProfile.update​

Update distribution profile fields. Only include the fields you want to change.

ParameterTypeRequiredDescription
idintYesProfile ID to update
distributionProfile[objectType]stringYesMust match the profile's type
distributionProfile[name]stringNoUpdated name
distributionProfile[submitEnabled]intNoUpdated submit mode (1/2/3)
distributionProfile[updateEnabled]intNoUpdated update mode (1/2/3)
distributionProfile[deleteEnabled]intNoUpdated delete mode (1/2/3)
distributionProfile[distributeTrigger]intNoUpdated trigger (1=ENTRY_READY, 2=MODERATION_APPROVED)

Response: Updated profile object with all fields.

curl -X POST "$KALTURA_SERVICE_URL/service/contentDistribution_distributionProfile/action/update" \
-d "ks=$KALTURA_KS" \
-d "format=1" \
-d "id=$DISTRIBUTION_PROFILE_ID" \
-d "distributionProfile[objectType]=KalturaYoutubeApiDistributionProfile" \
-d "distributionProfile[name]=Updated YouTube Channel" \
-d "distributionProfile[submitEnabled]=2"

The protocol field on FTP profiles is immutable after creation — include it in the initial add call. Updating protocol returns PROPERTY_VALIDATION_NOT_UPDATABLE and rejects the entire request. To change protocol, delete the profile and create a new one.

5.6 distributionProfile.updateStatus​

Enable or disable a distribution profile.

ParameterTypeRequiredDescription
idintYesProfile ID
statusintYes1=DISABLED, 2=ENABLED

Response: Updated profile object.

# Disable
curl -X POST "$KALTURA_SERVICE_URL/service/contentDistribution_distributionProfile/action/updateStatus" \
-d "ks=$KALTURA_KS" \
-d "format=1" \
-d "id=$DISTRIBUTION_PROFILE_ID" \
-d "status=1"
# Re-enable
curl -X POST "$KALTURA_SERVICE_URL/service/contentDistribution_distributionProfile/action/updateStatus" \
-d "ks=$KALTURA_KS" \
-d "format=1" \
-d "id=$DISTRIBUTION_PROFILE_ID" \
-d "status=2"

5.7 distributionProfile.delete​

Delete a distribution profile.

ParameterTypeRequiredDescription
idintYesProfile ID to delete
curl -X POST "$KALTURA_SERVICE_URL/service/contentDistribution_distributionProfile/action/delete" \
-d "ks=$KALTURA_KS" \
-d "format=1" \
-d "id=$DISTRIBUTION_PROFILE_ID"

6. Entry Distribution Lifecycle​

Entry distributions bind a specific media entry to a distribution profile, tracking the full lifecycle of distributing that entry to the external platform.

6.1 Entry Distribution Object Fields​

FieldTypeDescription
idintEntry distribution ID (auto-assigned)
entryIdstringThe Kaltura entry ID
distributionProfileIdintThe distribution profile ID
statusintCurrent status (see section 11.1)
dirtyStatusintWhat changed since last sync (see section 11.3)
sunStatusintSunrise/sunset state (see section 11.3)
thumbAssetIdsstringComma-separated thumbnail asset IDs to distribute
flavorAssetIdsstringComma-separated flavor asset IDs to distribute
sunriseintUnix timestamp — content becomes active
sunsetintUnix timestamp — content expires
remoteIdstringID assigned by the remote platform (e.g., YouTube video ID)
validationErrorsarrayValidation failures from the last validate call
errorTypeintError category if status is ERROR_*
errorNumberintProvider-specific error code
errorDescriptionstringHuman-readable error message

6.2 entryDistribution.add​

Bind an entry to a distribution profile.

ParameterTypeRequiredDescription
entryDistribution[objectType]stringYesMust be KalturaEntryDistribution
entryDistribution[entryId]stringYesKaltura entry ID to distribute
entryDistribution[distributionProfileId]intYesTarget distribution profile ID
entryDistribution[thumbAssetIds]stringNoComma-separated thumbnail asset IDs to distribute
entryDistribution[flavorAssetIds]stringNoComma-separated flavor asset IDs to distribute
entryDistribution[sunrise]intNoUnix timestamp when content becomes active on remote
entryDistribution[sunset]intNoUnix timestamp when content expires on remote

Response: Entry distribution object with id, entryId, distributionProfileId, status (0=PENDING).

curl -X POST "$KALTURA_SERVICE_URL/service/contentDistribution_entryDistribution/action/add" \
-d "ks=$KALTURA_KS" \
-d "format=1" \
-d "entryDistribution[objectType]=KalturaEntryDistribution" \
-d "entryDistribution[entryId]=$KALTURA_ENTRY_ID" \
-d "entryDistribution[distributionProfileId]=$DISTRIBUTION_PROFILE_ID"

The new entry distribution starts in PENDING status (0). Optionally set thumbAssetIds and flavorAssetIds to control which assets are distributed, and sunrise/sunset for time-based scheduling.

6.3 entryDistribution.validate​

Validate an entry against the distribution profile requirements before submitting.

ParameterTypeRequiredDescription
idintYesEntry distribution ID
curl -X POST "$KALTURA_SERVICE_URL/service/contentDistribution_entryDistribution/action/validate" \
-d "ks=$KALTURA_KS" \
-d "format=1" \
-d "id=$ENTRY_DISTRIBUTION_ID"

Response includes validationErrors array with detailed error objects:

{
"id": 93294543,
"status": 0,
"validationErrors": [
{
"objectType": "KalturaDistributionValidationErrorMissingFlavor",
"action": 1,
"errorType": 1,
"flavorParamsId": "0",
"description": "missing flavor param"
}
]
}

Validation checks:

  • Required flavors — entry must have all flavors listed in requiredFlavorParamsIds
  • Required thumbnails — entry must have thumbnails matching requiredThumbDimensions
  • Required metadata — provider-specific required fields must be present
  • Data format — field values must pass format validation (string length, allowed values)

If autoCreateFlavors or autoCreateThumb is enabled on the profile, missing assets are automatically queued for creation.

6.4 entryDistribution.submitAdd​

Submit an entry to the remote platform.

ParameterTypeRequiredDescription
idintYesEntry distribution ID
submitWhenReadyboolNotrue to queue until entry is ready; false to submit immediately
curl -X POST "$KALTURA_SERVICE_URL/service/contentDistribution_entryDistribution/action/submitAdd" \
-d "ks=$KALTURA_KS" \
-d "format=1" \
-d "id=$ENTRY_DISTRIBUTION_ID" \
-d "submitWhenReady=true"

Response: Updated entry distribution object. Status transitions to QUEUED (1) or SUBMITTING (4). On success, status becomes READY (2) and remoteId is populated.

The submitWhenReady parameter (boolean):

  • true — if the entry is still processing, queue the submission until the entry reaches READY status
  • false — submit immediately; fails if entry is not ready

The submission pipeline:

  1. Checks profile.submitEnabled is not DISABLED
  2. Validates the entry against profile requirements
  3. If the entry is not ready and submitWhenReady=true, queues with status QUEUED (1)
  4. If sunrise is in the future, queues until the sunrise time
  5. If validation passes, creates a batch job and sets status to SUBMITTING (4)
  6. On success, status becomes READY (2) and remoteId is populated with the external platform ID

6.5 entryDistribution.list​

List entry distributions with filters.

Filter parameters (all optional, use filter[objectType]=KalturaEntryDistributionFilter):

ParameterTypeDescription
filter[entryIdEqual]stringFilter by Kaltura entry ID
filter[distributionProfileIdEqual]intFilter by distribution profile ID
filter[statusEqual]intFilter by status (see section 11.1)
filter[statusIn]stringComma-separated statuses
filter[dirtyStatusEqual]intFilter by dirty status
filter[sunriseGreaterThanOrEqual]intFilter by minimum sunrise timestamp
filter[sunsetLessThanOrEqual]intFilter by maximum sunset timestamp
pager[pageSize]intResults per page (default 30)
pager[pageIndex]intPage number (1-based)

Response: {objects: [...], totalCount: N, objectType: "KalturaEntryDistributionListResponse"}

# List all entry distributions
curl -X POST "$KALTURA_SERVICE_URL/service/contentDistribution_entryDistribution/action/list" \
-d "ks=$KALTURA_KS" \
-d "format=1"
# Filter by entry ID
curl -X POST "$KALTURA_SERVICE_URL/service/contentDistribution_entryDistribution/action/list" \
-d "ks=$KALTURA_KS" \
-d "format=1" \
-d "filter[objectType]=KalturaEntryDistributionFilter" \
-d "filter[entryIdEqual]=$KALTURA_ENTRY_ID"
# Filter by distribution profile
curl -X POST "$KALTURA_SERVICE_URL/service/contentDistribution_entryDistribution/action/list" \
-d "ks=$KALTURA_KS" \
-d "format=1" \
-d "filter[objectType]=KalturaEntryDistributionFilter" \
-d "filter[distributionProfileIdEqual]=$DISTRIBUTION_PROFILE_ID"
# Filter by status
curl -X POST "$KALTURA_SERVICE_URL/service/contentDistribution_entryDistribution/action/list" \
-d "ks=$KALTURA_KS" \
-d "format=1" \
-d "filter[objectType]=KalturaEntryDistributionFilter" \
-d "filter[statusEqual]=2"

6.6 entryDistribution.get​

Retrieve a specific entry distribution.

ParameterTypeRequiredDescription
idintYesEntry distribution ID
curl -X POST "$KALTURA_SERVICE_URL/service/contentDistribution_entryDistribution/action/get" \
-d "ks=$KALTURA_KS" \
-d "format=1" \
-d "id=$ENTRY_DISTRIBUTION_ID"

Response: Full entry distribution object (see section 6.1 for field definitions).

6.7 entryDistribution.update​

Update entry distribution fields (sunrise/sunset scheduling, asset selection).

ParameterTypeRequiredDescription
idintYesEntry distribution ID
entryDistribution[objectType]stringYesMust be KalturaEntryDistribution
entryDistribution[sunrise]intNoUpdated sunrise Unix timestamp
entryDistribution[sunset]intNoUpdated sunset Unix timestamp
entryDistribution[thumbAssetIds]stringNoUpdated thumbnail asset IDs
entryDistribution[flavorAssetIds]stringNoUpdated flavor asset IDs

Response: Updated entry distribution object.

curl -X POST "$KALTURA_SERVICE_URL/service/contentDistribution_entryDistribution/action/update" \
-d "ks=$KALTURA_KS" \
-d "format=1" \
-d "id=$ENTRY_DISTRIBUTION_ID" \
-d "entryDistribution[objectType]=KalturaEntryDistribution" \
-d "entryDistribution[sunrise]=$SUNRISE_TIMESTAMP" \
-d "entryDistribution[sunset]=$SUNSET_TIMESTAMP"

6.8 entryDistribution.submitUpdate​

Push metadata or content updates to the remote platform.

ParameterTypeRequiredDescription
idintYesEntry distribution ID
curl -X POST "$KALTURA_SERVICE_URL/service/contentDistribution_entryDistribution/action/submitUpdate" \
-d "ks=$KALTURA_KS" \
-d "format=1" \
-d "id=$ENTRY_DISTRIBUTION_ID"

Response: Updated entry distribution object. Status transitions to UPDATING (5).

Valid when current status is READY (2), ERROR_UPDATING (8), ERROR_DELETING (9), or IMPORT_UPDATING (12).

6.9 entryDistribution.submitDelete​

Remove the entry from the remote platform.

ParameterTypeRequiredDescription
idintYesEntry distribution ID
curl -X POST "$KALTURA_SERVICE_URL/service/contentDistribution_entryDistribution/action/submitDelete" \
-d "ks=$KALTURA_KS" \
-d "format=1" \
-d "id=$ENTRY_DISTRIBUTION_ID"

Response: Updated entry distribution object. Status transitions to DELETING (6), then REMOVED (10) on success.

Valid when current status is READY (2), ERROR_DELETING (9), or ERROR_UPDATING (8).

6.10 entryDistribution.submitFetchReport​

Request a delivery report from the remote platform.

ParameterTypeRequiredDescription
idintYesEntry distribution ID
curl -X POST "$KALTURA_SERVICE_URL/service/contentDistribution_entryDistribution/action/submitFetchReport" \
-d "ks=$KALTURA_KS" \
-d "format=1" \
-d "id=$ENTRY_DISTRIBUTION_ID"

Valid only when status is READY (2). The distribution profile must have reportEnabled set to AUTOMATIC (2).

6.11 entryDistribution.retrySubmit​

Retry the last failed operation.

ParameterTypeRequiredDescription
idintYesEntry distribution ID (must be in an ERROR_* status)
curl -X POST "$KALTURA_SERVICE_URL/service/contentDistribution_entryDistribution/action/retrySubmit" \
-d "ks=$KALTURA_KS" \
-d "format=1" \
-d "id=$ENTRY_DISTRIBUTION_ID"

Use this when an entry distribution is in an ERROR_* status (7, 8, or 9) to re-attempt the failed operation. The operation retried corresponds to the status: ERROR_SUBMITTING retries submit, ERROR_UPDATING retries update, ERROR_DELETING retries delete.

6.12 entryDistribution.serveSentData / serveReturnedData​

Retrieve the raw XML data sent to or received from the remote platform for debugging.

ParameterTypeRequiredDescription
idintYesEntry distribution ID
actionTypeintYes1=SUBMIT, 2=UPDATE, 3=DELETE
# Get XML sent to the remote platform (actionType: 1=SUBMIT, 2=UPDATE, 3=DELETE)
curl -X POST "$KALTURA_SERVICE_URL/service/contentDistribution_entryDistribution/action/serveSentData" \
-d "ks=$KALTURA_KS" \
-d "format=1" \
-d "id=$ENTRY_DISTRIBUTION_ID" \
-d "actionType=1"
# Get XML returned from the remote platform
curl -X POST "$KALTURA_SERVICE_URL/service/contentDistribution_entryDistribution/action/serveReturnedData" \
-d "ks=$KALTURA_KS" \
-d "format=1" \
-d "id=$ENTRY_DISTRIBUTION_ID" \
-d "actionType=1"

These endpoints return text/html with the raw XML payload. The body is empty (0 bytes) if no data exists for the given action type — this is normal for entries that have not yet been submitted or for action types that have not been executed.

Action type values:

ValueName
1SUBMIT
2UPDATE
3DELETE

6.13 entryDistribution.delete​

Delete the entry distribution record.

ParameterTypeRequiredDescription
idintYesEntry distribution ID
curl -X POST "$KALTURA_SERVICE_URL/service/contentDistribution_entryDistribution/action/delete" \
-d "ks=$KALTURA_KS" \
-d "format=1" \
-d "id=$ENTRY_DISTRIBUTION_ID"

This removes the entry distribution record. To also remove the content from the remote platform, call submitDelete first.

7. Distribution Triggers & Automation​

7.1 Automatic Distribution on Entry Ready​

When submitEnabled=2 (AUTOMATIC) and distributeTrigger=1 (ENTRY_READY), entries are automatically submitted to the remote platform when they finish processing:

curl -X POST "$KALTURA_SERVICE_URL/service/contentDistribution_distributionProfile/action/update" \
-d "ks=$KALTURA_KS" \
-d "format=1" \
-d "id=$DISTRIBUTION_PROFILE_ID" \
-d "distributionProfile[objectType]=KalturaYoutubeApiDistributionProfile" \
-d "distributionProfile[submitEnabled]=2" \
-d "distributionProfile[distributeTrigger]=1"

7.2 Moderation-Gated Distribution​

When distributeTrigger=2 (MODERATION_APPROVED), entries are only submitted after passing content moderation:

curl -X POST "$KALTURA_SERVICE_URL/service/contentDistribution_distributionProfile/action/update" \
-d "ks=$KALTURA_KS" \
-d "format=1" \
-d "id=$DISTRIBUTION_PROFILE_ID" \
-d "distributionProfile[objectType]=KalturaYoutubeApiDistributionProfile" \
-d "distributionProfile[distributeTrigger]=2"

7.3 Sunrise / Sunset Scheduling​

Control when distributed content becomes active and expires using Unix timestamps:

curl -X POST "$KALTURA_SERVICE_URL/service/contentDistribution_entryDistribution/action/update" \
-d "ks=$KALTURA_KS" \
-d "format=1" \
-d "id=$ENTRY_DISTRIBUTION_ID" \
-d "entryDistribution[objectType]=KalturaEntryDistribution" \
-d "entryDistribution[sunrise]=1735689600" \
-d "entryDistribution[sunset]=1738368000"

The sunStatus field tracks the current state:

ValueNameDescription
1BEFORE_SUNRISEContent not yet active — queued for future activation
2AFTER_SUNRISEContent is active
3AFTER_SUNSETContent has expired

When submitWhenReady=true and sunrise is in the future, the entry distribution is queued and automatically submitted at the sunrise time.

7.4 Dirty Status & Update Propagation​

When a distributed entry changes (metadata update, new flavors, thumbnail change), the dirtyStatus is set:

ValueNameDescription
0NONEClean — no pending changes
1SUBMIT_REQUIREDContent needs initial submission
2DELETE_REQUIREDContent needs removal from remote
3UPDATE_REQUIREDMetadata or content changed since last sync
4ENABLE_REQUIREDDistribution needs re-enabling

When updateEnabled=2 (AUTOMATIC), the system auto-submits updates when the dirty flag is set. When updateEnabled=3 (MANUAL), call submitUpdate explicitly to push changes.

7.5 Status State Machine​

The distribution engine enforces strict status transitions:

ActionValid From Statuses
submitAddPENDING (0), QUEUED (1), ERROR_SUBMITTING (7), ERROR_UPDATING (8), ERROR_DELETING (9), IMPORT_SUBMITTING (11), READY (2), REMOVED (10)
submitUpdateREADY (2), ERROR_UPDATING (8), ERROR_DELETING (9), IMPORT_UPDATING (12)
submitDeleteREADY (2), ERROR_DELETING (9), ERROR_UPDATING (8)
submitFetchReportREADY (2) only

8. Distribution Connector Reference​

8.1 YouTube API Distribution​

The YouTube API connector pushes video entries to a YouTube channel via OAuth 2.0.

Profile type: KalturaYoutubeApiDistributionProfile
Provider type: youtubeApiDistribution.YOUTUBE_API

Key fields:

FieldDescription
usernameYouTube channel username
defaultCategoryDefault YouTube category ID
allowCommentsallowed or denied
allowEmbeddingallowed or denied
allowRatingsallowed or denied
privacyStatuspublic, private, or unlisted
googleClientIdOAuth 2.0 client ID
googleClientSecretOAuth 2.0 client secret
apiAuthorizeUrlOAuth authorization URL (auto-generated)

YouTube category IDs (used in defaultCategory):

IDCategory
1Film & Animation
2Autos & Vehicles
10Music
15Pets & Animals
17Sports
19Travel & Events
20Gaming
22People & Blogs
23Comedy
24Entertainment
25News & Politics
26Howto & Style
27Education
28Science & Technology
29Nonprofits & Activism

YouTube OAuth setup: The YouTube connector requires OAuth 2.0 authorization to access a YouTube channel. The setup flow is:

  1. Configure googleClientId and googleClientSecret on the distribution profile (obtain these from the Google Cloud Console for your project)
  2. The profile's apiAuthorizeUrl field contains the OAuth authorization URL. Open this URL in a browser to grant the Kaltura distribution engine access to the target YouTube channel
  3. Complete the Google OAuth consent flow — the resulting refresh token is stored server-side on the profile
  4. Once authorized, the profile can push content to the YouTube channel via the YouTube Data API

This authorization is typically done once during profile setup through the Rich Media CMS (KMC). The refresh token is automatically renewed by the distribution engine.

When an entry is successfully distributed to YouTube, the remoteId field on the entry distribution is populated with the YouTube video ID.

8.2 Facebook Distribution​

The Facebook connector pushes video entries to a Facebook page.

Profile type: KalturaFacebookDistributionProfile
Provider type: facebookDistribution.FACEBOOK

Key fields:

FieldDescription
pageIdTarget Facebook page ID
pageAccessTokenPage-level access token
userAccessTokenUser-level access token
apiAuthorizeUrlOAuth authorization URL
permissionsRequested Facebook permissions

Facebook OAuth setup: The Facebook connector requires OAuth authorization to post to a Facebook Page. The setup flow is:

  1. Configure the distribution profile with your Facebook app credentials
  2. The profile's apiAuthorizeUrl field contains the Facebook OAuth authorization URL. Open this URL in a browser to grant the Kaltura distribution engine access to the target Facebook Page
  3. Complete the Facebook OAuth consent flow, granting the required permissions (pages_manage_posts, pages_read_engagement, etc.)
  4. The resulting pageAccessToken and userAccessToken are stored on the profile. Facebook page tokens are long-lived but may need re-authorization if permissions change

This authorization is typically done once during profile setup through the Rich Media CMS (KMC).

8.3 Cross-Kaltura Distribution​

The Cross-Kaltura connector syncs content between Kaltura accounts, including metadata, flavors, thumbnails, captions, and cue points.

Profile type: KalturaCrossKalturaDistributionProfile
Provider type: crossKalturaDistribution.CROSS_KALTURA

Key fields:

FieldDescription
targetServiceUrlDestination Kaltura API URL
targetAccountIdDestination partner ID
targetLoginId / targetLoginPasswordAuth credentials for target account
metadataXsltXSLT to transform metadata between accounts
distributeCaptionsPush caption assets
distributeCuePointsPush cue points
distributeRemoteFlavorAssetContentPush flavor files
distributeRemoteThumbAssetContentPush thumbnail files
mapAccessControlProfileIdsSource-to-target access control ID mapping
mapConversionProfileIdsSource-to-target conversion profile mapping
mapMetadataProfileIdsSource-to-target metadata profile mapping

8.4 FTP Distribution​

The FTP connector pushes content and MRSS metadata files to an FTP/SFTP/SCP server.

Profile type: KalturaFtpDistributionProfile
Provider type: ftpDistribution.FTP

Key fields:

FieldDescription
protocol1=FTP, 2=SCP, 3=SFTP, 5=HTTPS, 10=ASPERA
host, portServer connection
basePathRemote directory path
username, passwordAuth credentials
sftpPublicKey, sftpPrivateKeySFTP key-based auth
metadataXsltXSLT for MRSS transformation
flavorAssetFilenameXsltXSLT to generate flavor filenames
thumbnailAssetFilenameXsltXSLT for thumbnail filenames
disableMetadataSkip MRSS metadata file
sendMetadataAfterAssetsSend MRSS file after asset uploads

9. MRSS & Field Configuration​

9.1 MRSS Structure​

Kaltura generates an internal MRSS (Media RSS) feed for each entry that includes all metadata, content URLs, thumbnails, and distribution-specific data. This MRSS is the input for distribution connectors — each connector transforms it into the provider-specific format.

Each entry's MRSS includes a <distribution> block per active distribution:

<distribution entryDistributionId="[ID]"
distributionProfileId="[ID]"
distributionProfileName="[name]"
provider="[provider_name]">
<remoteId>[YouTube video ID, etc.]</remoteId>
<sunrise>[timestamp]</sunrise>
<sunset>[timestamp]</sunset>
<flavorAssetIds>
<flavorAssetId>[ID]</flavorAssetId>
</flavorAssetIds>
<thumbAssetIds>
<thumbAssetId>[ID]</thumbAssetId>
</thumbAssetIds>
<status>[status]</status>
<dirtyStatus>[status]</dirtyStatus>
<sunStatus>[status]</sunStatus>
</distribution>

9.2 Field Configuration (fieldConfigArray)​

Configurable distribution profiles (YouTube, Facebook, etc.) use fieldConfigArray to map Kaltura MRSS elements to provider fields:

{
"fieldName": "MEDIA_TITLE",
"userFriendlyFieldName": "Entry name",
"entryMrssXslt": "<xsl:value-of select=\"string(title)\" />",
"isRequired": 1,
"updateOnChange": true,
"updateParams": [{ "value": "entry.NAME" }]
}
FieldDescription
fieldNameProvider field identifier (e.g., MEDIA_TITLE, MEDIA_DESCRIPTION, MEDIA_KEYWORDS)
entryMrssXsltXSLT expression to extract the value from MRSS
isRequired1=REQUIRED, 2=NOT_REQUIRED, 3=SYSTEM
updateOnChangeWhen true, changes to the mapped entry field set the dirtyStatus flag
updateParamsEntry field names that trigger the update check

When updateOnChange=true and the corresponding entry field changes, the dirtyStatus is automatically set, triggering an update cycle if updateEnabled=AUTOMATIC.

10. Building a Custom Connector​

Kaltura's built-in connectors cover major platforms (YouTube, Facebook, FTP, Cross-Kaltura). For platforms not covered by a built-in connector, there are two paths:

  • Generic Distribution (XSLT-based) — Configure a custom connector entirely through API calls. Kaltura's internal MRSS feed (section 9.1) is transformed into the target platform's expected format via XSLT and delivered over FTP, SFTP, SCP, HTTP, or HTTPS. This approach works for any target that accepts XML or file-based ingest.

  • Custom built-in connector — For platforms requiring OAuth authentication, complex REST API interactions, or custom business logic beyond XML transformation, contact your Kaltura account manager to submit a feature request for a new built-in distribution connector. Built-in connectors are developed and maintained by Kaltura as server-side plugins.

The rest of this section covers the Generic Distribution approach.

10.1 Generic Distribution Provider​

A Generic Distribution Provider defines a custom connector type. It specifies the provider's name, required and optional assets, and which entry fields trigger distribution updates.

curl -X POST "$KALTURA_SERVICE_URL/service/contentDistribution_genericDistributionProvider/action/add" \
-d "ks=$KALTURA_KS" \
-d "format=1" \
-d "genericDistributionProvider[name]=My Custom Platform" \
-d "genericDistributionProvider[requiredFlavorParamsIds]=0" \
-d "genericDistributionProvider[optionalFlavorParamsIds]=$FLAVOR_PARAMS_ID" \
-d "genericDistributionProvider[isDefault]=false"

Response:

{
"id": 123,
"name": "My Custom Platform",
"partnerId": 976461,
"status": 1,
"isDefault": false,
"requiredFlavorParamsIds": "0",
"optionalFlavorParamsIds": "487041",
"objectType": "KalturaGenericDistributionProvider"
}

Provider fields:

FieldTypeDescription
idintProvider ID (auto-assigned, read-only)
namestringDisplay name (required)
statusint1=ACTIVE, 2=DELETED (read-only)
isDefaultboolWhether this is the default generic provider
requiredFlavorParamsIdsstringComma-separated flavor params IDs that entries must have
optionalFlavorParamsIdsstringComma-separated optional flavor params IDs
requiredThumbDimensionsarrayRequired thumbnail sizes for validation
optionalThumbDimensionsarrayOptional thumbnail sizes
editableFieldsstringFields users can edit per entry distribution
mandatoryFieldsstringFields that must be filled before submission

Other provider actions:

# Get provider by ID
curl -X POST "$KALTURA_SERVICE_URL/service/contentDistribution_genericDistributionProvider/action/get" \
-d "ks=$KALTURA_KS" \
-d "format=1" \
-d "id=$GENERIC_PROVIDER_ID"

# List providers
curl -X POST "$KALTURA_SERVICE_URL/service/contentDistribution_genericDistributionProvider/action/list" \
-d "ks=$KALTURA_KS" \
-d "format=1"

# Update provider
curl -X POST "$KALTURA_SERVICE_URL/service/contentDistribution_genericDistributionProvider/action/update" \
-d "ks=$KALTURA_KS" \
-d "format=1" \
-d "id=$GENERIC_PROVIDER_ID" \
-d "genericDistributionProvider[name]=Updated Platform Name"

# Delete provider
curl -X POST "$KALTURA_SERVICE_URL/service/contentDistribution_genericDistributionProvider/action/delete" \
-d "ks=$KALTURA_KS" \
-d "format=1" \
-d "id=$GENERIC_PROVIDER_ID"

10.2 Provider Actions​

Each provider needs one or more actions that define how content is delivered to the target platform. Create a separate action for each operation the connector supports.

Action types:

ValueNameDescription
1SUBMITInitial content push to remote platform
2UPDATEPush metadata or content updates
3DELETERemove content from remote platform
4FETCH_REPORTRetrieve delivery/engagement reports

Delivery protocols:

ValueName
1FTP
2SCP
3SFTP
4HTTP
5HTTPS
# Create a SUBMIT action that delivers XML via SFTP
curl -X POST "$KALTURA_SERVICE_URL/service/contentDistribution_genericDistributionProviderAction/action/add" \
-d "ks=$KALTURA_KS" \
-d "format=1" \
-d "genericDistributionProviderAction[genericDistributionProviderId]=$GENERIC_PROVIDER_ID" \
-d "genericDistributionProviderAction[action]=1" \
-d "genericDistributionProviderAction[protocol]=3" \
-d "genericDistributionProviderAction[serverAddress]=sftp.targetplatform.com" \
-d "genericDistributionProviderAction[remotePath]=/ingest/incoming" \
-d "genericDistributionProviderAction[remoteUsername]=kaltura_feed" \
-d "genericDistributionProviderAction[remotePassword]=secret"

Response:

{
"id": 456,
"genericDistributionProviderId": 123,
"action": 1,
"status": 1,
"protocol": 3,
"serverAddress": "sftp.targetplatform.com",
"remotePath": "/ingest/incoming",
"remoteUsername": "kaltura_feed",
"objectType": "KalturaGenericDistributionProviderAction"
}

Action fields:

FieldTypeDescription
idintAction ID (auto-assigned, read-only)
genericDistributionProviderIdintParent provider ID (insert-only)
actionintAction type: 1=SUBMIT, 2=UPDATE, 3=DELETE, 4=FETCH_REPORT (insert-only)
statusint1=ACTIVE, 2=DELETED (read-only)
protocolintDelivery protocol (see table above)
serverAddressstringTarget server hostname or URL
remotePathstringPath on the target server (supports \{REMOTE_ID\} placeholder)
remoteUsernamestringAuthentication username
remotePasswordstringAuthentication password
resultsParserintHow to parse the remote response: 1=XSL, 2=XPATH, 3=REGEX
editableFieldsstringEditable field names for this action
mandatoryFieldsstringRequired field names for this action
mrssTransformerstringThe XSLT transform (read-only — set via addMrssTransform)
mrssValidatorstringThe XSD validator (read-only — set via addMrssValidate)
resultsTransformerstringThe results parser data (read-only — set via addResultsTransform)

The remotePath field supports the \{REMOTE_ID\} placeholder, which is replaced with the entry distribution's remoteId at runtime. This is useful for UPDATE and DELETE actions that target a specific remote resource.

10.3 XSLT Transforms​

Three transforms can be attached to each provider action to control the data pipeline:

MRSS Transformer — XSLT stylesheet that converts Kaltura's internal MRSS (section 9.1) into the target platform's expected XML format. This is where you map Kaltura entry fields (title, description, tags, content URLs) to the target's schema.

MRSS Validator — XSD schema that validates the transformed XML before delivery. If validation fails, the distribution job reports a validation error instead of sending malformed data.

Results Transformer — Parses the target platform's response to extract the remoteId (the external platform's identifier for the distributed content). Three parser types are supported:

ValueParserDescription
1XSLApply XSLT to the response XML, extract comma-separated values
2XPATHEvaluate an XPath expression against the response XML
3REGEXMatch a regular expression against the response body

Upload transforms​

Transforms are uploaded separately after creating the action:

# Upload MRSS transform XSLT
curl -X POST "$KALTURA_SERVICE_URL/service/contentDistribution_genericDistributionProviderAction/action/addMrssTransform" \
-d "ks=$KALTURA_KS" \
-d "format=1" \
-d "id=$ACTION_ID" \
--data-urlencode "xslData=<xsl:stylesheet version=\"1.0\" xmlns:xsl=\"http://www.w3.org/1999/XSL/Transform\">
<xsl:output method=\"xml\" indent=\"yes\"/>
<xsl:template match=\"/\">
<item>
<title><xsl:value-of select=\"//item/title\"/></title>
<description><xsl:value-of select=\"//item/description\"/></description>
<videoUrl><xsl:value-of select=\"//item/content/@url\"/></videoUrl>
</item>
</xsl:template>
</xsl:stylesheet>"
# Upload MRSS validation XSD
curl -X POST "$KALTURA_SERVICE_URL/service/contentDistribution_genericDistributionProviderAction/action/addMrssValidate" \
-d "ks=$KALTURA_KS" \
-d "format=1" \
-d "id=$ACTION_ID" \
--data-urlencode "xsdData=<xs:schema xmlns:xs=\"http://www.w3.org/2001/XMLSchema\">
<xs:element name=\"item\">
<xs:complexType>
<xs:sequence>
<xs:element name=\"title\" type=\"xs:string\"/>
<xs:element name=\"description\" type=\"xs:string\"/>
<xs:element name=\"videoUrl\" type=\"xs:anyURI\"/>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>"
# Upload results transform (XPath to extract remote ID from response)
curl -X POST "$KALTURA_SERVICE_URL/service/contentDistribution_genericDistributionProviderAction/action/addResultsTransform" \
-d "ks=$KALTURA_KS" \
-d "format=1" \
-d "id=$ACTION_ID" \
--data-urlencode "transformData=//response/id"

Transforms can also be uploaded from files using the addMrssTransformFromFile, addMrssValidateFromFile, and addResultsTransformFromFile actions.

10.4 Creating a Generic Distribution Profile​

Once the provider and its actions are configured, create a distribution profile that references the provider:

curl -X POST "$KALTURA_SERVICE_URL/service/contentDistribution_distributionProfile/action/add" \
-d "ks=$KALTURA_KS" \
-d "format=1" \
-d "partnerId=$KALTURA_PARTNER_ID" \
-d "distributionProfile[objectType]=KalturaGenericDistributionProfile" \
-d "distributionProfile[name]=My Custom Platform Distribution" \
-d "distributionProfile[status]=2" \
-d "distributionProfile[genericProviderId]=$GENERIC_PROVIDER_ID" \
-d "distributionProfile[submitEnabled]=3" \
-d "distributionProfile[updateEnabled]=3" \
-d "distributionProfile[deleteEnabled]=2"

The genericProviderId field links the profile to the provider you created in section 10.1. The profile inherits the provider's required assets, and the actions you defined in section 10.2 control how each operation is executed.

The partnerId parameter is required in the request body (same requirement as all distribution profiles — see section 5.2).

From here, the standard entry distribution workflow applies: bind an entry (section 6.2), validate (section 6.3), and submit (section 6.4).

10.5 Generic Distribution Data Flow​

When an entry distribution is submitted against a Generic Distribution profile:

  1. Kaltura generates the entry's MRSS XML (section 9.1), including all metadata, content URLs, thumbnails, and distribution-specific data
  2. The SUBMIT action's MRSS Transformer XSLT is applied, converting the MRSS into the target platform's format
  3. If an MRSS Validator XSD is configured, the transformed XML is validated — failures are reported as validation errors
  4. The transformed XML is delivered to the target server via the configured protocol (FTP, SFTP, SCP, HTTP, or HTTPS)
  5. If the target returns a response, the Results Transformer parses it (via XSL, XPath, or Regex) to extract the remoteId
  6. The entry distribution status updates to READY (2) with the extracted remoteId

The same pipeline runs for UPDATE and DELETE actions using their respective transforms and server configurations.

11. Status & Error Reference​

11.1 Entry Distribution Status Values​

ValueNameDescription
0PENDINGAwaiting submission
1QUEUEDIn processing queue (waiting for entry ready or sunrise)
2READYSuccessfully distributed to remote platform
3DELETEDMarked for deletion
4SUBMITTINGActively submitting to remote
5UPDATINGPushing updates to remote
6DELETINGRemoving from remote
7ERROR_SUBMITTINGSubmit failed
8ERROR_UPDATINGUpdate failed
9ERROR_DELETINGDelete failed
10REMOVEDSuccessfully removed from remote
11IMPORT_SUBMITTINGImporting from remote
12IMPORT_UPDATINGUpdating import

11.2 Distribution Validation Error Types​

Error ObjecterrorTypeDescription
KalturaDistributionValidationErrorMissingFlavor1Required flavor not found on entry
KalturaDistributionValidationErrorMissingThumbnail2Required thumbnail dimensions not found
KalturaDistributionValidationErrorMissingMetadata3Required metadata field is empty
KalturaDistributionValidationErrorInvalidData4Field value fails format validation
KalturaDistributionValidationErrorMissingAsset5Required asset not found
KalturaDistributionValidationErrorConditionNotMet6XSLT distribution condition not satisfied

11.3 Dirty Status & Sun Status Flags​

Dirty status (tracks what changed since last sync):

ValueNameDescription
0NONEClean — no pending changes
1SUBMIT_REQUIREDInitial submission needed
2DELETE_REQUIREDRemoval needed
3UPDATE_REQUIREDMetadata or content changed
4ENABLE_REQUIREDRe-enabling needed

Sun status (sunrise/sunset state):

ValueNameDescription
1BEFORE_SUNRISEContent not yet active
2AFTER_SUNRISEContent is active
3AFTER_SUNSETContent has expired

12. API Actions Reference​

ServiceActionDescription
contentDistribution_distributionProviderlistList available provider types
contentDistribution_distributionProfileaddCreate distribution profile
contentDistribution_distributionProfilegetGet profile by ID
contentDistribution_distributionProfilelistList profiles (with filters)
contentDistribution_distributionProfileupdateUpdate profile fields
contentDistribution_distributionProfileupdateStatusEnable/disable profile
contentDistribution_distributionProfiledeleteDelete profile
contentDistribution_genericDistributionProvideraddCreate custom generic provider
contentDistribution_genericDistributionProvidergetGet provider by ID
contentDistribution_genericDistributionProviderlistList generic providers
contentDistribution_genericDistributionProviderupdateUpdate provider fields
contentDistribution_genericDistributionProviderdeleteDelete provider
contentDistribution_genericDistributionProviderActionaddCreate provider action (submit/update/delete)
contentDistribution_genericDistributionProviderActiongetGet action by ID
contentDistribution_genericDistributionProviderActiongetByProviderIdGet action by provider ID and action type
contentDistribution_genericDistributionProviderActionlistList provider actions
contentDistribution_genericDistributionProviderActionupdateUpdate action fields
contentDistribution_genericDistributionProviderActiondeleteDelete action
contentDistribution_genericDistributionProviderActionaddMrssTransformUpload XSLT transform for MRSS
contentDistribution_genericDistributionProviderActionaddMrssValidateUpload XSD validation schema
contentDistribution_genericDistributionProviderActionaddResultsTransformUpload results parser (XSL/XPath/Regex)
contentDistribution_entryDistributionaddBind entry to distribution profile
contentDistribution_entryDistributiongetGet entry distribution by ID
contentDistribution_entryDistributionlistList entry distributions (with filters)
contentDistribution_entryDistributionupdateUpdate entry distribution fields
contentDistribution_entryDistributiondeleteDelete entry distribution record
contentDistribution_entryDistributionvalidateValidate entry against profile requirements
contentDistribution_entryDistributionsubmitAddSubmit entry to remote platform
contentDistribution_entryDistributionsubmitUpdatePush updates to remote
contentDistribution_entryDistributionsubmitDeleteRemove from remote platform
contentDistribution_entryDistributionsubmitFetchReportRequest delivery report
contentDistribution_entryDistributionretrySubmitRetry last failed operation
contentDistribution_entryDistributionserveSentDataRetrieve XML sent to remote
contentDistribution_entryDistributionserveReturnedDataRetrieve XML returned from remote

13. Error Handling​

Error CodeMeaningResolution
ENTRY_DISTRIBUTION_NOT_FOUNDEntry distribution ID does not existVerify the ID; may have been deleted
DISTRIBUTION_PROFILE_NOT_FOUNDDistribution profile ID does not existVerify the profile ID
DISTRIBUTION_PROFILE_DISABLEDProfile is currently disabled (status=1)Re-enable with distributionProfile.updateStatus
ENTRY_NOT_FOUNDThe entry ID in the distribution binding does not existVerify the entry ID
SERVICE_FORBIDDENContent Distribution plugin not enabledContact your Kaltura account manager
PROPERTY_VALIDATION_CANNOT_BE_NULLA required field is missingAdd the required parameter
INVALID_KSKS is invalid, expired, or lacks privilegesGenerate a fresh admin KS

Retry strategy: For transient errors (HTTP 5xx, timeouts), retry with exponential backoff: 1s, 2s, 4s, with jitter, up to 3 retries. For client errors (ENTRY_DISTRIBUTION_NOT_FOUND, SERVICE_FORBIDDEN), fix the request before retrying. Distribution submission is asynchronous — after calling submitAdd, poll the entry distribution status rather than retrying the submit call.

14. Best Practices​

  • Validate before submitting. Call entryDistribution.validate before submitAdd to catch missing flavors, thumbnails, or metadata. Fix validation errors before attempting submission.
  • Use submitWhenReady=true for newly uploaded content. Entries that are still processing will be automatically submitted once they reach READY status, avoiding timing issues.
  • Monitor dirty status for content updates. When updateEnabled=MANUAL, periodically check for entry distributions with dirtyStatus != 0 and call submitUpdate to push changes.
  • Use sunrise/sunset for time-based releases. Schedule content activation and expiration via timestamps rather than manual submit/delete calls.
  • Check serveSentData / serveReturnedData for debugging. When distribution fails, inspect the raw XML sent to and received from the remote platform.
  • Use entry distribution list with filters for monitoring. Filter by statusEqual to find failed distributions (status 7, 8, 9) and retry or investigate.
  • Call submitDelete before delete. To remove content from both the remote platform and Kaltura, call submitDelete first (removes from remote), then delete (removes the local record).
  • Use Generic Distribution for custom XML-based targets. Build a custom connector via API (section 10) for any platform that accepts XML file delivery. For platforms requiring OAuth or custom REST API integration, contact your Kaltura account manager to request a new built-in connector.

Common Integration Patterns​

Multi-Platform Publishing Pipeline​

Distribute a single entry to multiple platforms simultaneously by binding it to multiple distribution profiles:

# Bind to YouTube
curl -X POST "$KALTURA_SERVICE_URL/service/contentDistribution_entryDistribution/action/add" \
-d "ks=$KALTURA_KS" \
-d "format=1" \
-d "entryDistribution[objectType]=KalturaEntryDistribution" \
-d "entryDistribution[entryId]=$KALTURA_ENTRY_ID" \
-d "entryDistribution[distributionProfileId]=$YOUTUBE_PROFILE_ID"

# Bind to Facebook
curl -X POST "$KALTURA_SERVICE_URL/service/contentDistribution_entryDistribution/action/add" \
-d "ks=$KALTURA_KS" \
-d "format=1" \
-d "entryDistribution[objectType]=KalturaEntryDistribution" \
-d "entryDistribution[entryId]=$KALTURA_ENTRY_ID" \
-d "entryDistribution[distributionProfileId]=$FACEBOOK_PROFILE_ID"

# Submit both with submitWhenReady
curl -X POST "$KALTURA_SERVICE_URL/service/contentDistribution_entryDistribution/action/submitAdd" \
-d "ks=$KALTURA_KS" \
-d "format=1" \
-d "id=$YOUTUBE_ENTRY_DIST_ID" \
-d "submitWhenReady=true"

curl -X POST "$KALTURA_SERVICE_URL/service/contentDistribution_entryDistribution/action/submitAdd" \
-d "ks=$KALTURA_KS" \
-d "format=1" \
-d "id=$FACEBOOK_ENTRY_DIST_ID" \
-d "submitWhenReady=true"

YouTube Channel Distribution​

Full workflow for distributing content to YouTube:

  1. Get profile — retrieve the YouTube distribution profile to verify configuration
  2. Bind entry — create an entry distribution linking the entry to the YouTube profile
  3. Validate — check that required flavors and metadata are present
  4. Submit — push to YouTube; the entry gets a YouTube video ID in remoteId
  5. Monitor — check status transitions; READY (2) means the video is live on YouTube
# Step 1: Verify YouTube profile
curl -X POST "$KALTURA_SERVICE_URL/service/contentDistribution_distributionProfile/action/get" \
-d "ks=$KALTURA_KS" \
-d "format=1" \
-d "id=$YOUTUBE_PROFILE_ID"

# Step 2: Bind entry
curl -X POST "$KALTURA_SERVICE_URL/service/contentDistribution_entryDistribution/action/add" \
-d "ks=$KALTURA_KS" \
-d "format=1" \
-d "entryDistribution[objectType]=KalturaEntryDistribution" \
-d "entryDistribution[entryId]=$KALTURA_ENTRY_ID" \
-d "entryDistribution[distributionProfileId]=$YOUTUBE_PROFILE_ID"

# Step 3: Validate
curl -X POST "$KALTURA_SERVICE_URL/service/contentDistribution_entryDistribution/action/validate" \
-d "ks=$KALTURA_KS" \
-d "format=1" \
-d "id=$ENTRY_DISTRIBUTION_ID"

# Step 4: Submit
curl -X POST "$KALTURA_SERVICE_URL/service/contentDistribution_entryDistribution/action/submitAdd" \
-d "ks=$KALTURA_KS" \
-d "format=1" \
-d "id=$ENTRY_DISTRIBUTION_ID" \
-d "submitWhenReady=true"

# Step 5: Check status
curl -X POST "$KALTURA_SERVICE_URL/service/contentDistribution_entryDistribution/action/get" \
-d "ks=$KALTURA_KS" \
-d "format=1" \
-d "id=$ENTRY_DISTRIBUTION_ID"

Time-Based Content Release​

Schedule content to go live on a remote platform at a future date and expire automatically:

curl -X POST "$KALTURA_SERVICE_URL/service/contentDistribution_entryDistribution/action/add" \
-d "ks=$KALTURA_KS" \
-d "format=1" \
-d "entryDistribution[objectType]=KalturaEntryDistribution" \
-d "entryDistribution[entryId]=$KALTURA_ENTRY_ID" \
-d "entryDistribution[distributionProfileId]=$DISTRIBUTION_PROFILE_ID" \
-d "entryDistribution[sunrise]=$GO_LIVE_TIMESTAMP" \
-d "entryDistribution[sunset]=$EXPIRE_TIMESTAMP"

curl -X POST "$KALTURA_SERVICE_URL/service/contentDistribution_entryDistribution/action/submitAdd" \
-d "ks=$KALTURA_KS" \
-d "format=1" \
-d "id=$ENTRY_DISTRIBUTION_ID" \
-d "submitWhenReady=true"

Monitoring Distribution Health​

Find all failed distributions and retry them:

# Find distributions with ERROR_SUBMITTING status
curl -X POST "$KALTURA_SERVICE_URL/service/contentDistribution_entryDistribution/action/list" \
-d "ks=$KALTURA_KS" \
-d "format=1" \
-d "filter[objectType]=KalturaEntryDistributionFilter" \
-d "filter[statusEqual]=7"

# View what was sent to the remote platform
curl -X POST "$KALTURA_SERVICE_URL/service/contentDistribution_entryDistribution/action/serveSentData" \
-d "ks=$KALTURA_KS" \
-d "format=1" \
-d "id=$FAILED_ENTRY_DIST_ID" \
-d "actionType=1"

# Retry the submission
curl -X POST "$KALTURA_SERVICE_URL/service/contentDistribution_entryDistribution/action/retrySubmit" \
-d "ks=$KALTURA_KS" \
-d "format=1" \
-d "id=$FAILED_ENTRY_DIST_ID"

Webhook-Triggered Distribution​

Combine distribution with webhooks for event-driven publishing. Set up a webhook that fires when entry metadata changes, then programmatically manage distribution updates:

  1. Create a webhook template for OBJECT_DATA_CHANGED on ENTRY objects
  2. In your webhook handler, check if the entry has active distributions
  3. If dirtyStatus != 0, call entryDistribution.submitUpdate to push changes
  • Session Guide — KS generation and management
  • AppTokens API — Secure server-to-server auth for automated distribution workflows
  • Syndication Feeds API — Generate RSS/MRSS/iTunes/Roku feeds for external platforms to pull (pull model vs distribution's push model)
  • Upload & Ingestion — Content upload, flavors, and ingestion (entries and assets that feed distribution)
  • Webhooks API — Event-driven automation (trigger distribution on content events)
  • Analytics Reports API — Engagement analytics for distributed content