OMSS v1.1 Specification
Open Media Streaming Specification Version: 1.1.0 Status: Final Released: June 15th, 2026 License: MITTable of Contents
- Introduction
- Core Principles
- API Conventions
- Endpoints
- Request Specifications
- Response Specifications
- Error Handling
- Caching and Performance
- Security Considerations
- Versioning and Compatibility
- Complete Examples
- License
1. Introduction
1.1 Purpose
OMSS (Open Media Streaming Specification) v1.1 defines a unified REST API standard for streaming media backends. It enables any frontend application to work seamlessly with any OMSS-compliant backend through standardized endpoints for retrieving streaming sources.1.2 Problem Statement
Modern streaming backends scrape data from various providers with inconsistent formats:- No standardized metadata: Files may be MP4, HLS or MKV without clear type information.
- Missing quality information: Bitrate, resolution, and codec data are often unavailable.
- Language ambiguity: Audio/subtitle language tracks may be unlabeled.
- Ephemeral URLs: Signed URLs with expiration times require special handling.
- Cross-origin restrictions: Sources might require proxy handling for CORS and access control.
1.3 Design Philosophy
- Source-focused: OMSS is about standardizing streaming sources, not media metadata.
- Pragmatic: Designed for backends that scrape third-party providers with incomplete data.
- Progressive disclosure: Required fields are minimal; optional fields provide enhanced functionality.
- HTTP-first: Uses HTTP status codes, headers, and semantics correctly.
1.4 Scope
In Scope:- REST API endpoint definitions for source retrieval.
- Standardized source/subtitle schemas.
- Error handling patterns.
- Access control/authentication — implement that yourself. (Personal Note: I would not recommend hosting such a backend publicly anyway, since it brings risk and costs with it. For personal use you do not need these.)
- Media metadata (ratings, descriptions, posters, etc.) — use the TMDB API directly.
- Search functionality — use the TMDB API.
- Provider-specific scraping logic — implement that yourself.
- Video player implementation — whichever player you use.
1.5 TMDB Integration
OMSS uses TMDB (The Movie Database) as the primary identifier for all media content:- Frontend responsibility: Fetch media metadata (title, year, poster, description, ratings) from the TMDB API.
- OMSS responsibility: Provide streaming sources and subtitles for TMDB IDs.
- Clean separation: OMSS focuses exclusively on source standardization.
2. Core Principles
2.1 HTTP-First Design
- Primary signal: HTTP status codes indicate success or failure.
- Secondary signal: The response body provides details.
- Standard headers: Use
Cache-Control,ETag,Retry-After, etc.
2.2 Unknown Data Handling
Backends MUST handle incomplete provider data gracefully:- Missing metadata: Omit optional fields rather than returning null or empty values.
- Quality and language inference: Attempt to infer quality and language from filenames, manifests, resolution, or bitrate.
- Type detection: Analyze file extension, MIME type, or content headers.
2.3 Identifier Strategy
- Primary: TMDB (The Movie Database) IDs.
- Required: All media MUST have a TMDB ID.
2.4 Versioning
- URL-based:
/v1/,/v2/in the path. - Semantic versioning:
MAJOR.MINOR.PATCH. - Breaking changes: Require a new major version.
3. API Conventions
3.1 Base URL
https://api.example.com/omss/), but for simplicity, the specification assumes a root deployment.
3.2 Content Type
- Request:
application/json; charset=utf-8 - Response:
application/json; charset=utf-8
3.3 Character Encoding
UTF-8 MUST be used for all text data.3.4 Date/Time Format
ISO 8601 format MUST be used:3.5 Naming Conventions
- Fields: camelCase (e.g.,
expiresAt,mimeType). - Enums: lowercase (e.g.,
hls,mp4,vtt). - Error codes: SCREAMING_SNAKE_CASE (e.g.,
INVALID_ID,NOT_FOUND).
3.6 Content Negotiation
OMSS v1.1 supports only JSON responses. Supported:Accept: application/json→ 200 OK with JSONAccept: */*→ 200 OK with JSON (default)
Accept: application/xml→ Throws a 406 Not Acceptable error. See 7.3 Standard Error Codes
3.7 Preflight Requests
OMSS backends MUST handle OPTIONS requests for CORS preflight correctly. Example:4. Endpoints
4.1 Home
Purpose: General information about the backend.name(string): Implementation name.version(string): Semantic version of the OMSS implementation (e.g.,1.1.0).status(string): API status —operational,degraded, ordown(e.g. maintenance).endpoints(object): Functions mapped to paths.movie(string): Path to the movie endpoint. MUST contain the{id}placeholder where the frontend will insert the TMDB ID.tv(string): Path to the TV show endpoint. MUST contain the{id},{s}and{e}placeholders where the frontend will insert the TMDB ID, season and episode respectively.
spec(string): When implementing OMSS, this MUST be"omss".media(object): field for backends to provide a list of available media.movies(array of integers OR string: ’_’ as const): List of TMDB movie IDs available in this backend or'_'if the backend supports all movies.tv(array of objects or string: ’_’ as const): List of TMDB TV series IDs with available seasons and episodes, or'_'if the backend supports all TV series. You can use'\*'inside of the tv object to mark a specific series and/or season as available. Each object contains:id(integer): TMDB series ID.seasons(array of objects): List of seasons with available episodes. Each object contains:season(integer): Season number.episodes(array of integers): List of episode numbers available in this season.
providers(array of objects): List of providers this backend provides. Each object contains:id(string): Unique provider identifier (MUST BE URL SAFE).name(string): Human-readable provider name.capabilities(array of strings): List of media types the provider supports any ofmovies,tvand/orsubtitles.
note(string): A custom message by the backend.
4.2 Movie Sources
[!CAUTION] This endpoint is sunset as of OMSS v1.1 and will be removed in the next major version of the specification. Clients SHOULD migrate to the replacement endpoint defined by OMSS v2 once available. Backends implementing OMSS v1.x MUST continue to support this endpoint for the lifetime of the v1 specification.Purpose: Retrieve movie streaming sources by TMDB ID.
id(string, required): TMDB movie ID.
platform(string, optional): Target platform for source optimization. One ofweb,native. Default isweb. This will change the response structure!provider(string, optional): Specific provider to fetch sources from. MUST be a valid provider ID. The result will stay the same, but the backend shall only return sources from the specified provider.filter(string, optional): filter expression(s) to apply on the returned sources. The syntax and semantics of the filter expressions are defined at 5.4 Filter Expression Syntax. The filter parameter is only applicable to the sources array in the response, and does not affect the subtitles array.
4.3 TV Episode Sources
[!CAUTION] This endpoint is sunset as of OMSS v1.1 and will be removed in the next major version of the specification. Clients SHOULD migrate to the replacement endpoint defined by OMSS v2 once available. Backends implementing OMSS v1.x MUST continue to support this endpoint for the lifetime of the v1 specification.Purpose: Retrieve TV episode streaming sources.
id(string, required): TMDB series ID.s(integer, required): Season number (≥ 0).e(integer, required): Episode number (≥ 1).
platform(string, optional): Target platform for source optimization. One ofweb,native. Default isweb. This will change the response structure!provider(string, optional): Specific provider to fetch sources from. MUST be a valid provider ID. The result will stay the same, but the backend shall only return sources from the specified provider.filter(string, optional): filter expression(s) to apply on the returned sources. The syntax and semantics of the filter expressions are defined at 5.4 Filter Expression Syntax. The filter parameter is only applicable to the sources array in the response, and does not affect the subtitles array.
4.4 Proxy Endpoint (sunset)
In previous versions of OMSS, the spec used to dictate the proxy behaviour. Starting v1.1, that isn’t the case anymore. It is up to the backend to decide how to/if it wants to implement the proxy.4.5 Refresh Endpoint
[!CAUTION] This endpoint is sunset as of OMSS v1.1 and will be removed in the next major version of the specification. Clients SHOULD migrate to the replacement endpoint defined by OMSS v2 once available. Backends implementing OMSS v1.x MUST continue to support this endpoint for the lifetime of the v1 specification.Purpose: Unified endpoint to refresh a response by its id.
id(string, required): The ID of the response to refresh.
id is valid the response will always be 200 OK, since the backend should simply remove the cache entry and immediatley invalidate the id and will try to fetch a new source the next time the frontend requests it. If it is invalid, see 7.3 Standard Error Codes.
5. Request Specifications
5.1 Headers
Required:Accept: application/json; charset=utf-8
5.2 Query Parameters
Validation Rules:- Query parameters are lowercase.
- Boolean parameters:
trueorfalse(lowercase).
5.3 Path Parameters
Validation Rules:id: String (numeric characters ONLY, treated as a string).s: Non-negative integer (0–∞ range).e: Positive integer (≥ 1).
5.4 Filter Expression Syntax
The optionalfilter query parameter allows clients to filter the returned sources (not subtitles) based on their properties.
Filtering is applied by the backend after source retrieval and before the response is returned to the client.
5.4.1 Syntax
A filter expression consists of one or more conditions.;) acts as a logical AND operator. All conditions MUST evaluate to true for an item to be included in the response.
Examples:
5.4.2 Operators
The following operators are supported:
The wildcard
* MAY be used with any operator and/or search string to match any value. When used with ==, it matches any non-empty value. When used with !=, it matches no values. When used with =in= or =out=, it behaves as if all possible values were included in the set.
Examples:
5.4.3 Supported Fields
Backends MUST support filtering on the following fields:
Backends MAY support additional fields. Clients MUST support the required fields (see above) and should ignore unsupported fields without throwing an error.
5.4.4 Array Matching
For array fields such asaudioTracks, a condition matches if at least one element in the array satisfies the condition.
Examples:
5.4.5 Examples
Return only 4K sources:5.4.6 Invalid Filter Expressions
If the filter expression contains invalid syntax, unsupported operators, malformed values, or unknown fields, the backend MUST return:400 Bad Request, before any other processing of the request is done.
6. Response Specifications
6.1 Success Response
Both the movie and TV episode endpoints share this response structure, which includes arrays of Source and Subtitle objects, as well as any diagnostics about data quality or scraping issues. The response structure will stay the same regardless of theprovider query parameter, as it only returns sources from the specified provider. If the provider parameter is not specified, sources from all providers will be returned. If the specified provider does not return any sources, the response shall throw a NO_SOURCES_AVAILABLE error (see 7.4.1 Media Exists, No Sources). If the provider parameter is specified but does not match any known provider, the response shall throw a PROVIDER_NOT_FOUND error (see 7.3 Standard Error Codes).
However, the platform query parameter will change the structure of the 6.2 Source Objects and 6.3 Subtitle Objects in the response, as described in their respective sections.
HTTP Status: 200 OK
id(string): Unique response identifier (e.g. UUID v4).sources(array): Array of Source objects (at least one required. if no source found, see 7.4.1).subtitles(array): Array of Subtitle objects (may be empty).diagnostics(array): Non-fatal warnings/errors about data quality/inference and provider issues (may be empty).expiresAt(string, optional): ISO 8601 timestamp when sources expire (for signed/temporary URLs).
6.2 Source Object
Purpose: Represents a streaming source with quality and technical metadata. Usage: If the source object is found in the sources array, it means that the source is streamable and can be used directly in video players. If it is found in the downloads array, it means that the source is NOT streamable and should be treated as a direct download link. Clients should not attempt to use download links as streaming sources, as they may quite literally break your backend, because your backend might try to download the whole file into it’s memory before sending it to the client, which can cause out-of-memory errors and crashes. Platform: The structure of the Source Object can differ based on theplatform query parameter in the request. For web, the url must be a playable streaming link (e.g., HLS, MP4) that can be used directly in HTML5 video players (i.e. without CORS or any other restrictions). For native, the url has to be the upstream URL and a new headers (object) field will be added. This allows native player implementations that can handle CORS and custom headers to access the original streaming URL from the provider, while web clients will receive a proxied/optimized URL that is accessible without additional headers or CORS restrictions in browsers.
Default: web.
?platform=web Example
?platform=native
6.2.1 Required Fields
-
id(string): Unique source identifier (e.g. UUID v4). -
url(string): Forweb: A string representing the URL to the streaming source that can be used directly in HTML5 video players without CORS issues. Fornative: A string representing the original URL to the streaming source from the provider, which may require CORS handling or custom headers (provided in theheadersfield). -
headers(object, only fornativeplatform): Key-value pairs of HTTP (and non-standard HTTP) headers that should be included when accessing theurlfor native player implementations that can handle CORS and custom headers. Forwebplatform, this field is not included, and the providedurlmust be accessible without additional headers or CORS restrictions without additional headers. -
streamable(boolean): Indicates if the source is streamable (true) or a direct download link (false). If false, clients must treat the URL as a download link rather than a streaming source. Download links CANNOT be used as streaming sources. (see Range Header) -
type(string): Source type, one of:hls— HTTP Live Streaming (M3U8).mp4— MP4 file.mkv— MKV file.dash— MPEG-DASH (.mpdfiles).
-
quality(string): Video quality. One of8K,4K,QHD,FHD,HD,SD, orAuto: Quality should be inferred from the best available metadata, prioritizing resolution, then bitrate, filename, or manifest information. If the quality cannot be determined, useAuto. Suggested resolution mapping:- 4320p+ →
8K - 2160p–4319p →
4K - 1440p–2159p →
QHD - 1080p–1439p →
FHD - 720p–1079p →
HD - Below 720p →
SD - Unknown →
Auto
- 4320p+ →
-
audioTracks(array of strings): Human-readable language name. default/unknown —>Original -
provider(object): Information about the upstream provider.id(string): Unique provider identifier.name(string): Human-readable provider name.
6.2.2 Handling Unknown Source Data
Backends must handle missing or incomplete provider data to the best of their ability, while ensuring that the response remains valid and usable for clients.6.2.3 Multi-Audio Handling
It is the client’s responsibility to handle multiple audio tracks. The backend should provide anaudioTracks array with human-readable language names.
For backends: If the language cannot be determined, use "Original".
6.3 Subtitle Object
Purpose: Represents subtitle/caption tracks. Platform: The structure of the Subtitle Object can differ based on theplatform query parameter in the request.
For web, the url must be a direct link to a subtitle file (e.g., VTT, SRT) that can be used directly in HTML5 track elements without CORS issues. For native, the url has to be the upstream URL and a new headers (object) field will be added. This allows native player implementations that can handle CORS and custom headers to access the original subtitle URL from the provider, while web clients will receive a proxied/optimized URL that is accessible without additional headers or CORS restrictions in browsers.
Default: web.
?platform=web Example
6.3.1 Required Fields
-
id(string): Unique subtitle identifier (e.g. UUID v4). -
url(string): Forweb: A string representing the URL to the subtitle file that can be used directly in HTML5 track elements without CORS issues. Fornative: A string representing the original URL to the subtitle file from the provider, which may require CORS handling or custom headers (provided in theheadersfield). -
headers(object, only fornativeplatform): Key-value pairs of HTTP (and non-standard HTTP) headers that should be included when accessing theurlfor native player implementations that can handle CORS and custom headers. Forwebplatform, this field is not included, and the providedurlmust be accessible without additional headers or CORS restrictions without additional headers. -
label(string): Human-readable language name for the subtitle track. default/unknown —>Unknown -
format(string): Subtitle format, one of:vtt— WebVTT (preferred for web; default).srt— SubRip.
-
provider(object): Information about the upstream provider.id(string): Unique provider identifier.name(string): Human-readable provider name.
6.3.3 Handling Unknown Subtitle Data
Backends must handle missing or incomplete subtitle data to the best of their ability, while ensuring that the response remains valid and usable for clients.6.4 Warning/Error Objects in Success Response
Purpose: Report non-response-fatal issues encountered during scraping. Ifsource is an empty string, it means the warning applies to the entire response.
Description: A non-response-fatal warning/error is an issue encountered during scraping that does not prevent the backend from returning a successful response. These warnings/errors provide additional context about potential data quality issues or provider-specific scraping failures (for example: "Provider [name] failed to respond" would be a non-response-fatal error).
[!NOTE] If theproviderparameter is specified in the request, but the backend fails to fetch sources from that specific provider, the response will not include a warning/error object in thediagnosticsarray, but will instead return aNO_SOURCES_AVAILABLEerror response (see 7.4.1 Media Exists, No Sources).
code(string): Machine-readable warning/error code.message(string): Human-readable description.source(string): Identifier of the source of the issue (e.g., provider ID). If empty, applies to the whole response.severity(string): One of:warning— Non-fatal issue.error— Fatal issue.
6.4.1 Standard Warning/Error Codes
7. Error Handling
7.1 Error Response Format
All non-2xx responses MUST include:error.code(string): Machine-readable error code.error.message(string): Human-readable error description.traceId(string): Unique identifier for error tracking/debugging.
error.details(any): Additional context about the error. Frontends should not display this.
7.3 Standard Error Codes
[!NOTE]INVALID_TMDB_IDshould be used, when the TMDB ID is valid in format but does not correspond to any media (e.g.,99999999). For IDs that are not even valid in format (e.g.,abc123),INVALID_PARAMETERshould be used instead.
7.4 Edge Cases
7.4.1 Media Exists, No Sources
HTTP Status: 404 Not Found When the TMDB ID is valid but no streaming sources are available for that media, the backend MUST return a404 Not Found status with a NO_SOURCES_AVAILABLE error code. This indicates that while the media exists, the backend was unable to find any streamable sources for it (applies to a failure when fetching sources from a specific provider).
7.4.2 Invalid TMDB ID
HTTP Status: 400 Bad Request7.4.3 TMDB ID Not Found
HTTP Status: 404 Not Found8. Caching and Performance
8.1 Caching Strategies
OMSS does not mandate specific caching strategies, but recommends best practices for both backends and clients to optimize performance. Backends should implement caching strategies to improve performance and reduce load on upstream providers, and also to help avoid IP bans. Recommended strategies include:- In-memory caching (e.g. Redis, Memcached).
- Cache sources and subtitles separately.
- Cache sources for around 2 hours (7,200 seconds) by default.
- Cache subtitles for longer durations (e.g. 24 hours).
- When the refresh endpoint is called, the cache, aswell as the id, for that specific source should be invalidated immediately.
- For large/public backends, consider caching with a CDN and browser caching headers.
8.5 Performance Recommendations
For Backends:- Implement request coalescing for concurrent identical requests.
- Use connection pooling for upstream providers.
- Implement circuit breakers for failing providers.
- Respect cache headers and ETags.
- Prefetch sources before playback (for example at the end of a episode).
- Use conditional requests (
If-None-Match).
9. Security Considerations
9.1 HTTPS Requirement
- Production: All endpoints MUST use HTTPS.
- Development: HTTP is allowed for
localhostonly.
9.2 Input Validation
Backends MUST validate:-
Path parameters:
id: Alphanumeric, max 20 characters.s: Integer, 0–99.e: Integer, 1–9,999.responseId: Alphanumeric with hyphens/underscores, max 128 characters.
-
Query parameters:
- Reject injection attempts.
-
Headers:
- Enforce size limits (to prevent header overflow attacks).
10. Versioning and Compatibility
10.1 Semantic Versioning
OMSS follows Semantic Versioning 1.0.0:- MAJOR: Breaking changes (incompatible API changes).
- MINOR: Backward-compatible new features.
- PATCH: Backward-compatible bug fixes/clarifications.
10.2 URL Versioning
Version is in the URL path:10.4 Deprecation Policy
This is best effort, but especially in the beginning, this might not be followed strictly, since the spec is still evolving and breaking changes are expected. However, once the spec stabilizes, the following deprecation policy should be followed:- Announce at least 6 months before removal.
-
Headers: Deprecated endpoints return:
- Documentation: Migration guides are provided.
- Support: Deprecated features are supported for ≥ 1 major version.
- Removal: Only in a new major version.
10.5 Client Compatibility Expectations
Clients MUST:- Ignore unknown fields in responses.
- Use HTTP status codes as the primary signal.
- Handle new error codes gracefully.
- Support redirect responses (3xx).
- Version lock to a specific OMSS version (
/v1/). - Upgrade proactively when new versions are released.
- Monitor deprecation headers.
- Implement graceful degradation for missing required fields.
11. Complete Examples
11.1 Movie Request — Web Platform (Default)
Requestplatform query parameter is omitted, the response uses the default web structure. All url fields are accessible without additional headers or CORS restrictions directly in browsers without requiring custom headers or proxy handling by the client.
For examples when requesting a specific provider, see above in the 4.2 Movie Sources section.
Response: 200 OK
11.2 TV Episode Request — Native Platform
Requestnative platform, the backend returns upstream URLs directly and includes the required request headers for native player implementations.
Response: 200 OK