Skip to main content
View as Markdown

Syndication Feeds - Integration

Kaltura Syndication Feeds API​

Syndication feeds generate RSS/MRSS/XML feeds that external platforms pull via HTTP GET. Create a feed, configure its content scope and format, and share the feed URL — external platforms (Google, Apple Podcasts, Roku, news aggregators) fetch the XML on their own schedule. Feeds are stateless: Kaltura serves the current content each time the URL is requested.

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
Service: syndicationFeed

1. When to Use​

  • RSS feed generation — Automatically generate standards-compliant RSS/MRSS feeds from your Kaltura content library for distribution to external consumers
  • Podcast distribution — Publish audio and video content as iTunes-compatible podcast feeds for Apple Podcasts, Spotify, and other podcast platforms
  • Content syndication to external platforms — Distribute video content to Google (Video Sitemaps), Roku (Direct Publisher), and news aggregators via pull-based XML feeds

2. Prerequisites​

  • A Kaltura account with an ADMIN KS (type=2) with disableentitlement privilege
  • Syndication feed creation is available to all accounts — no additional plugin activation required

3. Core Concepts​

3.1 How Syndication Feeds Work​

  1. Create a feed — choose a feed type (Google Video Sitemap, iTunes Podcast, MRSS, Roku) and optionally scope it to specific content
  2. Get the feed URL — the API returns a feedUrl that serves XML at a public HTTP endpoint
  3. Share the URL — register the feed URL with external platforms (Google Search Console, Apple Podcasts Connect, Roku Developer Dashboard)
  4. External platforms poll — each platform fetches the feed on its own schedule; Kaltura serves the current content

3.2 Feed Types​

TypeValueObject TypeOutput Format
Google Video Sitemap1KalturaGoogleVideoSyndicationFeedXML sitemap with <video:video> elements
Yahoo MRSS2KalturaYahooSyndicationFeedRSS 2.0 with <media:*> namespace
iTunes Podcast3KalturaITunesSyndicationFeedRSS with <itunes:*> namespace
Flexible Format (XSLT)6KalturaGenericXsltSyndicationFeedCustom XSLT-transformed MRSS
Roku Direct Publisher7KalturaRokuSyndicationFeedRoku-specific MRSS
Opera TV8KalturaOperaSyndicationFeedOpera TV format

3.3 Feed Object Fields​

Base fields (all feed types):

FieldTypeDescription
idstringFeed ID (auto-assigned, e.g., 1_abc12345)
feedUrlstringPublic URL to fetch the feed XML
namestringFeed display name
typeintFeed type enum
statusintFeed status
playlistIdstringContent filter — restrict to a specific playlist
landingPagestringTemplate URL for video links (use {entry_id} placeholder)
allowEmbedboolInclude embed URLs in feed
enforceEntitlementboolApply access control to feed entries
entryFilterobjectKalturaMediaEntryFilter — filter by tags, mediaType, categories
feedContentTypeHeaderstringResponse Content-Type (default: text/xml; charset=utf-8)

iTunes-specific fields:

FieldDescription
feedDescriptionChannel description
languageFeed language code (e.g., EN)
ownerNamePodcast owner name
ownerEmailPodcast owner email
feedImageUrlAlbum art / channel logo URL
feedAuthorPodcast author
adultContentExplicit content flag

4. syndicationFeed.add​

Create a syndication feed. The objectType must match the desired feed type.

Google Video Sitemap:

curl -X POST "$KALTURA_SERVICE_URL/service/syndicationFeed/action/add" \
-d "ks=$KALTURA_KS" \
-d "format=1" \
-d "syndicationFeed[objectType]=KalturaGoogleVideoSyndicationFeed" \
-d "syndicationFeed[name]=Video Sitemap" \
-d "syndicationFeed[type]=1" \
-d "syndicationFeed[landingPage]=https://example.com/video/{entry_id}"

Yahoo MRSS:

curl -X POST "$KALTURA_SERVICE_URL/service/syndicationFeed/action/add" \
-d "ks=$KALTURA_KS" \
-d "format=1" \
-d "syndicationFeed[objectType]=KalturaYahooSyndicationFeed" \
-d "syndicationFeed[name]=MRSS Feed" \
-d "syndicationFeed[type]=2"

iTunes Podcast:

curl -X POST "$KALTURA_SERVICE_URL/service/syndicationFeed/action/add" \
-d "ks=$KALTURA_KS" \
-d "format=1" \
-d "syndicationFeed[objectType]=KalturaITunesSyndicationFeed" \
-d "syndicationFeed[name]=My Podcast" \
-d "syndicationFeed[type]=3" \
-d "syndicationFeed[feedDescription]=A podcast feed for video content" \
-d "syndicationFeed[language]=EN" \
-d "syndicationFeed[ownerName]=Channel Owner" \
-d "syndicationFeed[ownerEmail]=owner@example.com"

Roku Direct Publisher:

curl -X POST "$KALTURA_SERVICE_URL/service/syndicationFeed/action/add" \
-d "ks=$KALTURA_KS" \
-d "format=1" \
-d "syndicationFeed[objectType]=KalturaRokuSyndicationFeed" \
-d "syndicationFeed[name]=Roku Channel Feed" \
-d "syndicationFeed[type]=7"

Flexible Format (Generic XSLT):

curl -X POST "$KALTURA_SERVICE_URL/service/syndicationFeed/action/add" \
-d "ks=$KALTURA_KS" \
-d "format=1" \
-d "syndicationFeed[objectType]=KalturaGenericXsltSyndicationFeed" \
-d "syndicationFeed[name]=Custom Feed" \
-d "syndicationFeed[type]=6" \
--data-urlencode 'syndicationFeed[xslt]=<?xml version="1.0"?><xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"><xsl:output method="xml"/><xsl:template match="/"><feed><xsl:copy-of select="."/></feed></xsl:template></xsl:stylesheet>'

The Generic XSLT feed type requires an xslt parameter containing the XSLT stylesheet that transforms Kaltura's internal MRSS into the desired output format.

Common parameters (all feed types):

ParameterTypeRequiredDescription
syndicationFeed[objectType]stringYesMust match the feed type: KalturaGoogleVideoSyndicationFeed, KalturaYahooSyndicationFeed, KalturaITunesSyndicationFeed, KalturaGenericXsltSyndicationFeed, KalturaRokuSyndicationFeed, KalturaOperaSyndicationFeed
syndicationFeed[name]stringYesFeed display name
syndicationFeed[type]integerYesFeed type enum: 1=Google Video Sitemap, 2=Yahoo MRSS, 3=iTunes, 6=Generic XSLT, 7=Roku, 8=Opera TV
syndicationFeed[landingPage]stringNoTemplate URL for video links — use {entry_id} placeholder (required for Google Video Sitemap to generate <loc> elements)
syndicationFeed[playlistId]stringNoRestrict feed to entries in this playlist
syndicationFeed[allowEmbed]booleanNoInclude embed URLs in feed entries
syndicationFeed[enforceEntitlement]booleanNoApply access control to feed entries
syndicationFeed[entryFilter][objectType]stringNoKalturaMediaEntryFilter — required if using entry filter fields
syndicationFeed[entryFilter][tagsLike]stringNoFilter entries by tags
syndicationFeed[feedContentTypeHeader]stringNoResponse Content-Type header (default: text/xml; charset=utf-8)

iTunes-specific parameters (type=3, KalturaITunesSyndicationFeed):

ParameterTypeRequiredDescription
syndicationFeed[feedDescription]stringNoPodcast channel description
syndicationFeed[language]stringNoFeed language code (e.g., EN)
syndicationFeed[ownerName]stringNoPodcast owner name
syndicationFeed[ownerEmail]stringNoPodcast owner email
syndicationFeed[feedImageUrl]stringNoAlbum art / channel logo URL
syndicationFeed[feedAuthor]stringNoPodcast author
syndicationFeed[adultContent]stringNoExplicit content flag

Generic XSLT-specific parameters (type=6, KalturaGenericXsltSyndicationFeed):

ParameterTypeRequiredDescription
syndicationFeed[xslt]stringYesXSLT stylesheet that transforms Kaltura's internal MRSS into the desired output format

Response includes the feedUrl for accessing the generated XML:

{
"id": "1_abc12345",
"feedUrl": "https://www.kaltura.com/api_v3/getFeed.php?partnerId=\{PARTNER_ID\}&feedId=1_abc12345",
"name": "Video Sitemap",
"type": 1,
"objectType": "KalturaGoogleVideoSyndicationFeed"
}

5. syndicationFeed.get​

Retrieve a syndication feed by ID:

curl -X POST "$KALTURA_SERVICE_URL/service/syndicationFeed/action/get" \
-d "ks=$KALTURA_KS" \
-d "format=1" \
-d "id=$FEED_ID"
ParameterTypeRequiredDescription
idstringYesSyndication feed ID (e.g., 1_abc12345)

6. syndicationFeed.list​

List syndication feeds:

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

All filter and pager parameters are optional. Omitting them returns all feeds on the account.

ParameterTypeRequiredDescription
filter[objectType]stringNoKalturaBaseSyndicationFeedFilter or KalturaSyndicationFeedFilter
filter[typeEqual]integerNoFilter by feed type: 1=Google, 2=Yahoo, 3=iTunes, 6=Generic XSLT, 7=Roku, 8=Opera TV
filter[orderBy]stringNoSort field: +createdAt, -createdAt, +name, -name
pager[pageSize]integerNoResults per page (default 30, max 500)
pager[pageIndex]integerNoPage number, 1-based (default 1)

7. syndicationFeed.update​

Update a syndication feed:

curl -X POST "$KALTURA_SERVICE_URL/service/syndicationFeed/action/update" \
-d "ks=$KALTURA_KS" \
-d "format=1" \
-d "id=$FEED_ID" \
-d "syndicationFeed[objectType]=KalturaRokuSyndicationFeed" \
-d "syndicationFeed[name]=Updated Feed Name"
ParameterTypeRequiredDescription
idstringYesSyndication feed ID to update
syndicationFeed[objectType]stringYesMust match the feed's original type (e.g., KalturaRokuSyndicationFeed)
syndicationFeed[name]stringNoUpdated feed name
syndicationFeed[landingPage]stringNoUpdated landing page URL template
syndicationFeed[playlistId]stringNoUpdated playlist scope
syndicationFeed[allowEmbed]booleanNoUpdated embed URL inclusion
syndicationFeed[enforceEntitlement]booleanNoUpdated entitlement enforcement
syndicationFeed[entryFilter][objectType]stringNoKalturaMediaEntryFilter — required if updating entry filter
syndicationFeed[entryFilter][tagsLike]stringNoUpdated tag filter

Pass only the fields to change. Fields not included remain unchanged. The type field is immutable and cannot be updated.

8. syndicationFeed.delete​

Delete a syndication feed:

curl -X POST "$KALTURA_SERVICE_URL/service/syndicationFeed/action/delete" \
-d "ks=$KALTURA_KS" \
-d "format=1" \
-d "id=$FEED_ID"
ParameterTypeRequiredDescription
idstringYesSyndication feed ID to delete

9. syndicationFeed.getEntryCount​

Get the number of entries in a syndication feed:

curl -X POST "$KALTURA_SERVICE_URL/service/syndicationFeed/action/getEntryCount" \
-d "ks=$KALTURA_KS" \
-d "format=1" \
-d "feedId=$FEED_ID"
ParameterTypeRequiredDescription
feedIdstringYesSyndication feed ID to count entries for

Response:

{
"totalEntryCount": 27118,
"actualEntryCount": 27118,
"requireTranscodingCount": 0,
"objectType": "KalturaSyndicationFeedEntryCount"
}
  • totalEntryCount — entries matching the feed filter
  • actualEntryCount — entries with required flavors available
  • requireTranscodingCount — entries needing transcoding before inclusion

10. Feed URL & XML Output​

All feeds are served at: https://{service_url}/api_v3/getFeed.php?partnerId=\{PARTNER_ID\}&feedId=\{FEED_ID\}

Append &limit=N to cap the number of entries returned (also reduces cache TTL from 24 hours to 30 minutes).

10.1 Roku MRSS Output​

<rss xmlns:media="http://search.yahoo.com/mrss/" xmlns:atom="http://www.w3.org/2005/Atom"
xmlns:dcterms="http://purl.org/dc/terms/" version="2.0">
<channel>
<title><![CDATA[Feed Name]]></title>
<description><![CDATA[Description]]></description>
<item>
<guid isPermaLink="false">ENTRY_ID</guid>
<title><![CDATA[Entry Title]]></title>
<pubDate>Mon, 21 Jul 2014 07:20:18 -0400</pubDate>
<media:content url="http://cdnapi.kaltura.com/.../playManifest/.../a.m3u8" duration="2969"/>
<media:thumbnail url="https://cfvod.kaltura.com/.../thumbnail/.../width/800/height/450"/>
<media:keywords><![CDATA[tag1, tag2]]></media:keywords>
</item>
</channel>
</rss>

10.2 iTunes Podcast RSS Output​

<rss xmlns:itunes="http://www.itunes.com/dtds/podcast-1.0.dtd" version="2.0">
<channel>
<title>Feed Name</title>
<language>EN</language>
<itunes:owner>
<itunes:name>Owner Name</itunes:name>
<itunes:email>owner@example.com</itunes:email>
</itunes:owner>
<item>
<title>Entry Title</title>
<enclosure url="https://cfvod.kaltura.com/.../serveFlavor/.../name/a.mp4" type="video/mp4"/>
<itunes:duration>1:58:18</itunes:duration>
<itunes:image href="https://cfvod.kaltura.com/.../thumbnail/.../ext.jpg"/>
</item>
</channel>
</rss>

10.3 Google Video Sitemap Output​

<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9"
xmlns:video="http://www.google.com/schemas/sitemap-video/1.1">
<url>
<loc>https://example.com/video/ENTRY_ID</loc>
<video:video>
<video:title>Entry Title</video:title>
<video:thumbnail_loc>https://cfvod.kaltura.com/.../thumbnail/...</video:thumbnail_loc>
<video:content_loc>https://cfvod.kaltura.com/.../serveFlavor/...</video:content_loc>
</video:video>
</url>
</urlset>

11. Entry Filtering​

Scope a syndication feed to specific content using entryFilter or playlistId.

Filter by tags:

curl -X POST "$KALTURA_SERVICE_URL/service/syndicationFeed/action/add" \
-d "ks=$KALTURA_KS" \
-d "format=1" \
-d "syndicationFeed[objectType]=KalturaGoogleVideoSyndicationFeed" \
-d "syndicationFeed[name]=Tagged Content Feed" \
-d "syndicationFeed[type]=1" \
-d "syndicationFeed[landingPage]=https://example.com/video/{entry_id}" \
-d "syndicationFeed[entryFilter][objectType]=KalturaMediaEntryFilter" \
-d "syndicationFeed[entryFilter][tagsLike]=webinar"

Filter by playlist:

curl -X POST "$KALTURA_SERVICE_URL/service/syndicationFeed/action/add" \
-d "ks=$KALTURA_KS" \
-d "format=1" \
-d "syndicationFeed[objectType]=KalturaYahooSyndicationFeed" \
-d "syndicationFeed[name]=Playlist Feed" \
-d "syndicationFeed[type]=2" \
-d "syndicationFeed[playlistId]=$PLAYLIST_ID"

Feeds without a playlistId or entryFilter include all account entries.

12. Feed Caching & Performance​

  • Default feed cache TTL: 24 hours
  • Adding &limit=N to the feed URL reduces cache to 30 minutes and caps at N items
  • Special characters in entry metadata are XML-escaped automatically
  • Feeds without content filters on large accounts can include tens of thousands of entries — use playlistId or entryFilter to scope appropriately
  • Google Video Sitemap feeds require a valid landingPage URL to generate <loc> elements

13. API Actions Reference​

ServiceActionDescription
syndicationFeedaddCreate syndication feed
syndicationFeedgetGet feed by ID
syndicationFeedlistList feeds
syndicationFeedupdateUpdate feed config
syndicationFeeddeleteDelete feed
syndicationFeedgetEntryCountCount entries in feed

14. Error Handling​

Error CodeMeaningResolution
INVALID_FEED_IDFeed ID does not existVerify the feed ID
PROPERTY_VALIDATION_CANNOT_BE_NULLA required field is missing (e.g., objectType)Add the required parameter
PROPERTY_VALIDATION_NOT_UPDATABLEAttempted to update an immutable fieldCheck which fields are read-only for the feed type
SERVICE_FORBIDDENKS lacks required permissionsUse an admin KS with disableentitlement
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 (INVALID_FEED_ID, PROPERTY_VALIDATION_*), fix the request before retrying.

15. Best Practices​

  • Scope feeds with filters. Use playlistId or entryFilter to limit feed content — unscoped feeds on large accounts return all entries.
  • Add &limit=N to feed URLs for testing. This reduces the cache TTL to 30 minutes and caps entries, making iteration faster during development.
  • Use HTTPS for feed URLs. The feedUrl returned by the API uses http:// — convert to https:// in production.
  • Match objectType to feed type. The objectType in syndicationFeed.add must correspond to the type value — mismatches cause validation errors.
  • Use iTunes-specific fields for podcasts. Set feedDescription, language, ownerName, and ownerEmail for Apple Podcasts compliance.
  • Set a landingPage for Google Video Sitemaps. The {entry_id} placeholder in landingPage generates the <loc> URLs that Google indexes.

Common Integration Patterns​

Google Video Sitemap for SEO​

Generate a Google-compatible video sitemap for search engine indexing:

# Create a Google Video Sitemap feed scoped to published content
curl -X POST "$KALTURA_SERVICE_URL/service/syndicationFeed/action/add" \
-d "ks=$KALTURA_KS" \
-d "format=1" \
-d "syndicationFeed[objectType]=KalturaGoogleVideoSyndicationFeed" \
-d "syndicationFeed[name]=Video Sitemap - Published" \
-d "syndicationFeed[type]=1" \
-d "syndicationFeed[landingPage]=https://mysite.com/watch/{entry_id}" \
-d "syndicationFeed[entryFilter][objectType]=KalturaMediaEntryFilter" \
-d "syndicationFeed[entryFilter][tagsLike]=published"

Submit the feed URL to Google Search Console as a video sitemap.

Podcast Feed Generation​

Create an iTunes-compatible podcast feed:

curl -X POST "$KALTURA_SERVICE_URL/service/syndicationFeed/action/add" \
-d "ks=$KALTURA_KS" \
-d "format=1" \
-d "syndicationFeed[objectType]=KalturaITunesSyndicationFeed" \
-d "syndicationFeed[name]=Company Podcast" \
-d "syndicationFeed[type]=3" \
-d "syndicationFeed[feedDescription]=Weekly insights from our team" \
-d "syndicationFeed[language]=EN" \
-d "syndicationFeed[ownerName]=My Company" \
-d "syndicationFeed[ownerEmail]=podcast@example.com" \
-d "syndicationFeed[playlistId]=$PODCAST_PLAYLIST_ID"

Use playlistId to restrict the podcast to a curated playlist of episodes.

Content Syndication for News and Media​

Create multiple feed formats for different distribution channels:

# MRSS for news aggregators
curl -X POST "$KALTURA_SERVICE_URL/service/syndicationFeed/action/add" \
-d "ks=$KALTURA_KS" \
-d "format=1" \
-d "syndicationFeed[objectType]=KalturaYahooSyndicationFeed" \
-d "syndicationFeed[name]=News Video Feed" \
-d "syndicationFeed[type]=2" \
-d "syndicationFeed[entryFilter][objectType]=KalturaMediaEntryFilter" \
-d "syndicationFeed[entryFilter][tagsLike]=news"

# Roku feed for OTT
curl -X POST "$KALTURA_SERVICE_URL/service/syndicationFeed/action/add" \
-d "ks=$KALTURA_KS" \
-d "format=1" \
-d "syndicationFeed[objectType]=KalturaRokuSyndicationFeed" \
-d "syndicationFeed[name]=Roku Channel" \
-d "syndicationFeed[type]=7" \
-d "syndicationFeed[entryFilter][objectType]=KalturaMediaEntryFilter" \
-d "syndicationFeed[entryFilter][tagsLike]=featured"

Webhook-Triggered Feed Refresh​

Combine syndication with webhooks for proactive cache management. Set up a webhook that fires when new content is published, then programmatically add &limit=N to your feed URL to trigger a 30-minute cache window — ensuring external platforms see new content sooner than the default 24-hour cache.