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
disableentitlementprivilege - Syndication feed creation is available to all accounts — no additional plugin activation required
3. Core Concepts
3.1 How Syndication Feeds Work
- Create a feed — choose a feed type (Google Video Sitemap, iTunes Podcast, MRSS, Roku) and optionally scope it to specific content
- Get the feed URL — the API returns a
feedUrlthat serves XML at a public HTTP endpoint - Share the URL — register the feed URL with external platforms (Google Search Console, Apple Podcasts Connect, Roku Developer Dashboard)
- External platforms poll — each platform fetches the feed on its own schedule; Kaltura serves the current content
3.2 Feed Types
| Type | Value | Object Type | Output Format |
|---|---|---|---|
| Google Video Sitemap | 1 | KalturaGoogleVideoSyndicationFeed | XML sitemap with <video:video> elements |
| Yahoo MRSS | 2 | KalturaYahooSyndicationFeed | RSS 2.0 with <media:*> namespace |
| iTunes Podcast | 3 | KalturaITunesSyndicationFeed | RSS with <itunes:*> namespace |
| Flexible Format (XSLT) | 6 | KalturaGenericXsltSyndicationFeed | Custom XSLT-transformed MRSS |
| Roku Direct Publisher | 7 | KalturaRokuSyndicationFeed | Roku-specific MRSS |
| Opera TV | 8 | KalturaOperaSyndicationFeed | Opera TV format |
3.3 Feed Object Fields
Base fields (all feed types):
| Field | Type | Description |
|---|---|---|
id | string | Feed ID (auto-assigned, e.g., 1_abc12345) |
feedUrl | string | Public URL to fetch the feed XML |
name | string | Feed display name |
type | int | Feed type enum |
status | int | Feed status |
playlistId | string | Content filter — restrict to a specific playlist |
landingPage | string | Template URL for video links (use {entry_id} placeholder) |
allowEmbed | bool | Include embed URLs in feed |
enforceEntitlement | bool | Apply access control to feed entries |
entryFilter | object | KalturaMediaEntryFilter — filter by tags, mediaType, categories |
feedContentTypeHeader | string | Response Content-Type (default: text/xml; charset=utf-8) |
iTunes-specific fields:
| Field | Description |
|---|---|
feedDescription | Channel description |
language | Feed language code (e.g., EN) |
ownerName | Podcast owner name |
ownerEmail | Podcast owner email |
feedImageUrl | Album art / channel logo URL |
feedAuthor | Podcast author |
adultContent | Explicit 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):
| Parameter | Type | Required | Description |
|---|---|---|---|
syndicationFeed[objectType] | string | Yes | Must match the feed type: KalturaGoogleVideoSyndicationFeed, KalturaYahooSyndicationFeed, KalturaITunesSyndicationFeed, KalturaGenericXsltSyndicationFeed, KalturaRokuSyndicationFeed, KalturaOperaSyndicationFeed |
syndicationFeed[name] | string | Yes | Feed display name |
syndicationFeed[type] | integer | Yes | Feed type enum: 1=Google Video Sitemap, 2=Yahoo MRSS, 3=iTunes, 6=Generic XSLT, 7=Roku, 8=Opera TV |
syndicationFeed[landingPage] | string | No | Template URL for video links — use {entry_id} placeholder (required for Google Video Sitemap to generate <loc> elements) |
syndicationFeed[playlistId] | string | No | Restrict feed to entries in this playlist |
syndicationFeed[allowEmbed] | boolean | No | Include embed URLs in feed entries |
syndicationFeed[enforceEntitlement] | boolean | No | Apply access control to feed entries |
syndicationFeed[entryFilter][objectType] | string | No | KalturaMediaEntryFilter — required if using entry filter fields |
syndicationFeed[entryFilter][tagsLike] | string | No | Filter entries by tags |
syndicationFeed[feedContentTypeHeader] | string | No | Response Content-Type header (default: text/xml; charset=utf-8) |
iTunes-specific parameters (type=3, KalturaITunesSyndicationFeed):
| Parameter | Type | Required | Description |
|---|---|---|---|
syndicationFeed[feedDescription] | string | No | Podcast channel description |
syndicationFeed[language] | string | No | Feed language code (e.g., EN) |
syndicationFeed[ownerName] | string | No | Podcast owner name |
syndicationFeed[ownerEmail] | string | No | Podcast owner email |
syndicationFeed[feedImageUrl] | string | No | Album art / channel logo URL |
syndicationFeed[feedAuthor] | string | No | Podcast author |
syndicationFeed[adultContent] | string | No | Explicit content flag |
Generic XSLT-specific parameters (type=6, KalturaGenericXsltSyndicationFeed):
| Parameter | Type | Required | Description |
|---|---|---|---|
syndicationFeed[xslt] | string | Yes | XSLT 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"
| Parameter | Type | Required | Description |
|---|---|---|---|
id | string | Yes | Syndication 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.
| Parameter | Type | Required | Description |
|---|---|---|---|
filter[objectType] | string | No | KalturaBaseSyndicationFeedFilter or KalturaSyndicationFeedFilter |
filter[typeEqual] | integer | No | Filter by feed type: 1=Google, 2=Yahoo, 3=iTunes, 6=Generic XSLT, 7=Roku, 8=Opera TV |
filter[orderBy] | string | No | Sort field: +createdAt, -createdAt, +name, -name |
pager[pageSize] | integer | No | Results per page (default 30, max 500) |
pager[pageIndex] | integer | No | Page 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"
| Parameter | Type | Required | Description |
|---|---|---|---|
id | string | Yes | Syndication feed ID to update |
syndicationFeed[objectType] | string | Yes | Must match the feed's original type (e.g., KalturaRokuSyndicationFeed) |
syndicationFeed[name] | string | No | Updated feed name |
syndicationFeed[landingPage] | string | No | Updated landing page URL template |
syndicationFeed[playlistId] | string | No | Updated playlist scope |
syndicationFeed[allowEmbed] | boolean | No | Updated embed URL inclusion |
syndicationFeed[enforceEntitlement] | boolean | No | Updated entitlement enforcement |
syndicationFeed[entryFilter][objectType] | string | No | KalturaMediaEntryFilter — required if updating entry filter |
syndicationFeed[entryFilter][tagsLike] | string | No | Updated 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"
| Parameter | Type | Required | Description |
|---|---|---|---|
id | string | Yes | Syndication 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"
| Parameter | Type | Required | Description |
|---|---|---|---|
feedId | string | Yes | Syndication feed ID to count entries for |
Response:
{
"totalEntryCount": 27118,
"actualEntryCount": 27118,
"requireTranscodingCount": 0,
"objectType": "KalturaSyndicationFeedEntryCount"
}
totalEntryCount— entries matching the feed filteractualEntryCount— entries with required flavors availablerequireTranscodingCount— 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=Nto 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
playlistIdorentryFilterto scope appropriately - Google Video Sitemap feeds require a valid
landingPageURL to generate<loc>elements
13. API Actions Reference
| Service | Action | Description |
|---|---|---|
syndicationFeed | add | Create syndication feed |
syndicationFeed | get | Get feed by ID |
syndicationFeed | list | List feeds |
syndicationFeed | update | Update feed config |
syndicationFeed | delete | Delete feed |
syndicationFeed | getEntryCount | Count entries in feed |
14. Error Handling
| Error Code | Meaning | Resolution |
|---|---|---|
INVALID_FEED_ID | Feed ID does not exist | Verify the feed ID |
PROPERTY_VALIDATION_CANNOT_BE_NULL | A required field is missing (e.g., objectType) | Add the required parameter |
PROPERTY_VALIDATION_NOT_UPDATABLE | Attempted to update an immutable field | Check which fields are read-only for the feed type |
SERVICE_FORBIDDEN | KS lacks required permissions | Use an admin KS with disableentitlement |
INVALID_KS | KS is invalid, expired, or lacks privileges | Generate 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
playlistIdorentryFilterto limit feed content — unscoped feeds on large accounts return all entries. - Add
&limit=Nto 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
feedUrlreturned by the API useshttp://— convert tohttps://in production. - Match objectType to feed type. The
objectTypeinsyndicationFeed.addmust correspond to thetypevalue — mismatches cause validation errors. - Use iTunes-specific fields for podcasts. Set
feedDescription,language,ownerName, andownerEmailfor Apple Podcasts compliance. - Set a landingPage for Google Video Sitemaps. The
{entry_id}placeholder inlandingPagegenerates 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.
16. Related Guides
- Session Guide — KS generation and management
- Content Distribution API — Push content to external platforms via connectors (push model vs syndication's pull model)
- Upload & Ingestion API — Content upload, flavors, and ingestion (entries that appear in feeds)
- Webhooks API — Event-driven automation (trigger feed cache refresh on content events)