Please submit your catalogue data through the Partner Portal — you’ll also find the JSON Schema files and example JSON files referenced throughout this document there.
- Feed envelope (
feed.schema.json) — the envelope that wraps your catalogue: how to structure and submit it. - Content records (
content.schema.json) — how to describe each individual asset: movie, series, season, episode, or sport program. - Recommendations (
recommendations.schema.json) — how to structure your ranked lists per market.
Feed envelope
Defined infeed.schema.json. A single JSON object: envelope metadata followed by the content array. The envelope wraps the catalogue — metadata first, then the content itself.
Every feed is a full snapshot: whatever isn’t present in contents is treated as deleted.
Content record
Defined incontent.schema.json. One record per asset, discriminated on type. All types share the base fields below. Scripted/editorial types (movie, series, season, episode) also carry genre fields; sport_program does not (sports are categorised by sport / league / event_type).
In the type columns: Series = tv_show. required / optional / N/A are per the schema; “req (one of)” means at least one of the synopsis fields is required.
Base fields
Scroll the table horizontally to see more.
Genre fields
Applies to movie, series, season and episode — not to sport.
Examples
John Wick (Movie)
Allowed genres
genres and dominant_genre are restricted to the fixed list below — send only these Genre values (case as shown). Values outside this list are rejected.
dominant_genre fallback. If a record omits dominant_genre, TitanOS may fall back to the first entry in genres for UI placement — this is a fallback, not a substitute for setting the field explicitly, since it makes placement dependent on array order.Type-specific fields
Sport fields
Only forsport_program records.
Availabilities
Instead of business models like AVOD, TVOD, and SVOD, an offer is now defined by three independent axes:offer_type (the payment mechanism), includes_ad (whether playback carries ads), and delivery — determined by where the offer lives rather than a field of its own (item-level availabilities = VOD, live.availabilities = live). Each entry describes exactly one offer: one payment mechanism, one market set, one time window. Never merge multiple markets or terms into a single entry.
Offer fields
Shared by VOD and live/sport offers.price is { "amount": 4.99, "currency": "EUR" } — decimal major units (4.99, not 499; 500 for €500). amount ≥ 0, currency is ISO 4217.
Business model translation
Theavailabilities array describes one offer per entry — one payment mechanism × one market set × one time window. Never merge multiple markets/terms into a single entry; never send industry shorthand (SVOD, AVOD, TVOD, EST) — express it via offer_type + includes_ad.
Key rules
pricerequired forrental/purchase/ppv; rejected forfree/account.license_durationonly valid onrentalandppv; omit → bounded byend_time.ppv= live-only;rental= VOD-only.video_qualitiesrequired, VOD-only — omit on live offers.price.amountis major units (4.99, not499).
Live events and PPV
Live content (e.g.sport_program) keeps two separate offer lists:
The
live object also carries the actual event schedule:
Key rules.
ppv = pay once for the live event (access ends with the broadcast; replay terms go in the VOD availabilities as rental/purchase). purchase on live = keep it permanently. On the VOD side, access that expires is rental (with license_duration), never purchase. For one payment covering live + replay, send an entry in both lists with the same price. Pre-sale needs no extra field — an offer in the feed is on sale now, even if its window is in the future.
Shared sub-objects
Image
Core delivery rules
- Format & Compatibility: All images must be delivered in JPEG or PNG format using the sRGB color space.
- Asset Availability: Artwork must be hosted on a stable, public-facing server (HTTPS) that allows the TitanOS ingestion system to download the files.
- Update Logic: If you change an image, you must update the image URL or the metadata timestamp. Our system caches images, so keeping the same URL for a new image will prevent the UI from updating.
- Resolution & Scaling: Always provide the highest required resolution. Images will be scaled down for lower-end devices, but low-resolution source files may be rejected to avoid pixelation on 4K displays.
Providing assets that do not match the required aspect ratios (e.g., sending a 4:3 image for a 16:9 slot) will result in automatic cropping or padding, which may distort the intended look of your content.
type
Examples
artwork_portrait

Artwork portrait example
screenshot_portrait

Screenshot portrait example
artwork_landscape

Artwork landscape example
screenshot_landscape

Screenshot landscape example
transparent_logo

Transparent logo example
PromoVideo
Same as Image buttype is trailer / clip / preview, and it adds optional duration_in_seconds (integer ≥ 0). Required: type, url, locales.
Deeplink
At least one deeplink per record must have
platform: "tv".
Technical preconditions. To ensure a successful integration, your application and metadata must meet the following standards:
- HTML5 Accessibility: The application must be a web-based app accessible via a stable URL.
- Routing Logic: For Single Page Applications (SPAs), the internal routing must be configured to parse incoming URL paths or parameters and resolve the correct view state immediately.
- Destination Targets: We support and recommend two levels of deep linking — Content Details (leads the user to the movie or series overview page) and Direct Player, recommended (navigates the user directly into the video player to start playback).
- Geoblocking: Since TitanOS is a global platform, ensure the deep link provided for a specific market (e.g., ES) is not geoblocked for users in that region.
{AppBaseURL} + / + {path} — e.g. base https://titanos.partner-app.com + path player/550e8400-e29b → https://titanos.partner-app.com/player/550e8400-e29b. Query-parameter routing (…/launch?content_id=998877&autoplay=true) works the same way — the url field just needs to resolve to the right view.
action semantics
detail(Content Details Page): navigates the user to the informational overview or landing page of the asset. Mandatory fortv_showandseason, as they are containers rather than playable video files.watch(Direct Player Launch): bypasses all menus and launches video playback immediately. Strongly preferred formovieand individualepisoderecords to keep the user journey as short as possible.
The final deeplink structure depends on the architecture of the CTV application. The instructions and examples might not work 1:1 with your CTV application.
Classification
Common
system/code reference
classifications is optional in the current schema — but TitanOS may still withhold publication of content lacking a valid age rating to manage legal risk, so provide it wherever available.Identifier
Credits
credits is an array of { role, locale, name, character_name? }, one entry per (role, locale, name).
Competitor
{ name } where name is an array of { locale, value } localised strings (min 1).
Sport location
{ country?, city?, venue? } — country is an ISO 3166-1 alpha-2 code (not localised); city and venue are each arrays of { locale, value }.
Value types used above
- Locale tag — BCP 47: language + optional script + optional region (e.g.
en,de-DE,es-419). - Market code — ISO 3166-1 alpha-2 (e.g.
US,DE). - Currency code — ISO 4217 alpha-3 (e.g.
EUR,GBP,USD). - Localised text/title —
{ locale, value }or{ locale, title }.
Recommendations
Defined inrecommendations.schema.json. A separate full-snapshot document: one ordered list per market set, referencing content ids from your feed. Absence = delete (an id in no list is no longer recommended). Ids not present in the content feed are ignored. Emit generated_at before recommendations.
Changelog
v1.1.0 — 2026-09-16 — Closed genre taxonomy (additive)
v1.1.0 — 2026-09-16 — Closed genre taxonomy (additive)
schema_version is one shared contract version across feed.schema.json, content.schema.json, and recommendations.schema.json — all three now declare "1.1.0", even though only the genre taxonomy changed. A 1.0.0 feed still validates against the 1.1.0 schema (MINOR = additive).Genresv1.0.0 — 2026-07-24 — Full schema rewrite (breaking)
v1.0.0 — 2026-07-24 — Full schema rewrite (breaking)
New documents
Availabilities / offers
Content fields (general)
Series / season / episode structure
Sport fields