Skip to main content
To make integration as smooth as possible, TitanOS has introduced the Titan Schema Feed Format: a single, clearly defined structure for delivering your catalogue. Every feed can be checked automatically before it reaches us — we’re happy to share a validation script so you can self-validate on your side and catch any issues early.
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.
Three documents guide your technical team through building the catalogue feed and the recommendations feed:
  1. Feed envelope (feed.schema.json) — the envelope that wraps your catalogue: how to structure and submit it.
  2. Content records (content.schema.json) — how to describe each individual asset: movie, series, season, episode, or sport program.
  3. Recommendations (recommendations.schema.json) — how to structure your ranked lists per market.
Both the feed and the recommendations are full snapshots: anything absent from the document is treated as deleted (absence = delete).

Feed envelope

Defined in feed.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 in content.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)
The Mandalorian (Series)
Breaking Bad (Series)
The Crown (Series)
Chef’s Table (Series)

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 for sport_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

The availabilities 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
  • price required for rental/purchase/ppv; rejected for free/account.
  • license_duration only valid on rental and ppv; omit → bounded by end_time.
  • ppv = live-only; rental = VOD-only.
  • video_qualities required, VOD-only — omit on live offers.
  • price.amount is major units (4.99, not 499).

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.
UI safe zones. When preparing artwork, keep primary visual elements (such as faces or titles) centered. TitanOS may overlay text or other UI elements on the edges of the image.
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.
Minimum resolution by type Examples artwork_portrait
Artwork portrait example

Artwork portrait example

screenshot_portrait
Screenshot portrait example

Screenshot portrait example

artwork_landscape
Artwork landscape example

Artwork landscape example

screenshot_landscape
Screenshot landscape example

Screenshot landscape example

transparent_logo
Transparent logo example

Transparent logo example

PromoVideo

Same as Image but type is trailer / clip / preview, and it adds optional duration_in_seconds (integer ≥ 0). Required: type, url, locales. 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.
URL construction & structure. For HTML5 applications, the final landing URL is created by appending the content-specific path provided in your metadata to the application’s registered Base URL. The formula: {AppBaseURL} + / + {path} — e.g. base https://titanos.partner-app.com + path player/550e8400-e29bhttps://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 for tv_show and season, as they are containers rather than playable video files.
  • watch (Direct Player Launch): bypasses all menus and launches video playback immediately. Strongly preferred for movie and individual episode records 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 in recommendations.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

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).Genres
New documentsAvailabilities / offersContent fields (general)Series / season / episode structureSport fields