Zenix Embed API
Embed the Zenix player on partner sites via a simple iframe. Auto-selects the best streaming source (VF/VO) with zero backend exposure.
Interactive Builder
Préparez votre code sans attendre. Lancez l’aperçu lorsque vous souhaitez tester le lecteur.
Votre lecteur, prêt à tester.
Choisissez votre contenu, puis lancez la démonstration. Le code d’intégration est déjà disponible ci-dessous.
Sécurité & intégration
- Ne pas utiliser l'attribut
sandboxsur l'iframe, ou inclure au minimumallow-scripts allow-same-origin allow-popups. - Utilise uniquement l’iframe générée par Zenix : les lecteurs
<video>, HLS ou MP4 maison ne sont pas pris en charge. - Le lecteur démarre automatiquement. La cadence Smartlink reste gérée à l’intérieur de l’iframe, sur les interactions réelles du lecteur.
- Mode strict : définir
EMBED_FRAME_ANCESTORS_MODE=whitelistetEMBED_ALLOWED_ORIGINSsur le serveur. - Les URLs de flux sont signées et liées à la session (expiration ~15 min).
Introduction
The Zenix Embed API lets you integrate a fully-hosted video player into any website using a single <iframe> tag. The player handles source selection, Smartlink cadence and playback — no server-side code required on your end. Raw stream extraction and native-player relays are not supported.
Quick Start
Copy this snippet to embed a movie:
<iframe src="https://fluxora.sbs/embed/zenix?tmdb=550&type=movie&lang=vf" width="100%" height="500" frameborder="0" allowfullscreen allow="autoplay; fullscreen; encrypted-media"> </iframe>
For TV series, add season and episode:
<iframe src="https://fluxora.sbs/embed/zenix?tmdb=71712&type=tv&season=1&episode=1&lang=vf" width="100%" height="500" frameborder="0" allowfullscreen allow="autoplay; fullscreen; encrypted-media"> </iframe>
N'utilisez pas defer_play ni parent_gate dans l'URL embed — réservés au site Zenix. Sur votre site, utilisez uniquement l'URL ci-dessus : le lecteur démarre automatiquement et affiche son propre contrôle si un navigateur mobile exige un geste. L'iframe doit avoir allow="autoplay; fullscreen; encrypted-media" sans attribut sandbox.
Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
tmdb | integer | Yes | TMDB content ID |
type | string | Yes | movie or tv |
season | integer | TV only | Season number (default: 1) |
episode | integer | TV only | Episode number (default: 1) |
lang | string | No | vf (French) or vo (original). Auto-selects best source. |
Availability API
Check whether content is available before embedding:
https://fluxora.sbs/api/embed-player/availability?tmdb=&type=&season=&episode=
Response
{
"ok": true,
"vf": true,
"vo": false,
"available": true,
"meta": { "title": "Fight Club", "type": "movie" }
}
| Field | Type | Description |
|---|---|---|
ok | boolean | Request succeeded |
vf | boolean | null | French dub: true if confirmed on a source, false if absent, null if not verified. Includes confirmed S3 results. |
vo | boolean | null | Original version availability; null means not verified. |
available | boolean | null | At least one source confirmed. Never treat null as false. |
pending | boolean | Verification is incomplete. Do not hide the player solely because a source is unverified. |
should_embed | boolean | Presentation recommendation: true unless absence is confirmed. This does not claim that unknown content is available. |
availability_status | string | confirmed_available, confirmed_unavailable, unknown, or last_known_available (temporary cached evidence). |
availability_cache | object | Shared metadata cache, with checked_at, age_seconds and stale. Positive evidence is fresh for 5 minutes; confirmed negatives for 2 minutes. Refresh runs asynchronously. Last-known positive evidence expires after 15 minutes; expired negatives become unknown. Episodes and languages remain separate; embedding permissions are evaluated on every request. A first-ever check returns HTTP 202 with null, never an invented false. On unknown, keep the reader visible (should_embed) and retry after 5 seconds. |
sources.s3 | boolean | null | S3 evidence for the requested language and episode. Provider errors or cooldowns are unknown, not confirmed absence. |
meta | object | Content metadata (title, type, etc.) |
HTTP 202 ou null signifie « non vérifié », jamais « absent ». Ne testez pas if (data.available). Pour la langue demandée, masquez uniquement lorsque son champ vaut strictement false ; sur erreur réseau, conservez le lecteur.
let showReader = true;
try {
const response = await fetch(availabilityUrl);
if (response.ok) {
const data = await response.json();
// requestedLanguage vaut "vf" ou "vo".
showReader = data.available !== false && data[requestedLanguage] !== false;
}
} catch (_) { /* On garde le lecteur : pas de fausse absence. */ }
reader.hidden = !showReader;
Les sites déjà intégrés doivent adopter cette condition : le serveur Fluxora ne peut pas corriger à distance leur propre JavaScript. Les permissions d’accès au lecteur restent inchangées.
Sorties & calendrier
JSON public, sans clé, avec cache partagé et accès navigateur (CORS). Aucun appel à une source n’est effectué pendant votre requête. Dates ISO, fuseau UTC ; pagination avec page et limit (100 au maximum).
Dernières sorties référencées
GET https://fluxora.sbs/api/releases?from=2026-10-01&to=2026-10-31&type=movie&source=s3&limit=30
Par défaut : les 30 derniers jours, triés par release_date décroissante. Filtres : type=movie|tv|anime, source=s1|s2|s3. Sans filtre, toutes les sources. Intervalle maximal : 366 jours. Les dates inconnues sont exclues, jamais inventées. Pour une série, cette date est celle du titre, pas de chaque épisode.
Derniers ajouts S3 (films et épisodes)
GET https://fluxora.sbs/api/releases?date_field=added&source=s3&limit=50
added_at est la date d’ajout communiquée par S3, distincte de la sortie du film. Ce flux conserve les nouveautés reçues depuis son activation pendant 30 jours, sans reconstituer l’historique manquant. Il ne contient pas les ajouts S1/S2.
Calendrier des épisodes annoncés
GET https://fluxora.sbs/api/calendar
Diffusions annoncées par S3 pour les 7 prochains jours, avec season, episode, episode_title et date. meta.coverage précise l’intervalle en cache ; un intervalle extérieur renvoie 422. Une annonce ne confirme jamais la disponibilité de lecture.
Format commun
{ "ok": true, "items": [], "total": 0, "page": 1, "pages": 1, "per_page": 30,
"meta": { "date_field": "release", "timezone": "UTC", "catalogue_partial": true } }
Chaque entrée fournit son identifiant tmdb, son type, son titre, ses sources, sa date et date_type. available: null signifie que cette route ne teste pas la lecture : utilisez Availability API pour cela. La présence d’un épisode n’atteste pas toute la série. meta.stale indique un flux S3 âgé de plus d’une heure. S3 est synchronisé toutes les 30 minutes par pages limitées ; les plafonds du catalogue officiel restent applicables, l’index n’est pas exhaustif.
Annonces Discord → votre site
Récupérez les nouveautés qui alimentent déjà nos annonces Discord S1, S2 et S3 : film, série, saison ou épisode. Cette API publique, sans clé, lit un index local. Elle ne redétecte pas les contenus et n’appelle ni Discord ni les sources pendant votre requête.
Première lecture : dernières annonces
GET https://fluxora.sbs/api/announcements?limit=20
Sans after, vous recevez les 20 dernières annonces, dans l’ordre de leur identifiant. Enregistrez next_cursor, puis passez-le dans les appels suivants pour ne recevoir que les nouveaux événements.
GET https://fluxora.sbs/api/announcements?after=123&limit=100
GET https://fluxora.sbs/api/announcements?after=123&source=s3&type=tv&lang=vf
| Paramètre | Valeurs | Utilisation |
|---|---|---|
after | Identifiant entier ≥ 0 | Exclusif : événements après ce curseur. 0 relit tout l’historique conservé. |
limit | 1 à 100 ; défaut 20 | Nombre maximal d’événements par réponse. |
source | all, s1, s2, s3 | Source annoncée ; défaut all. |
type | all, movie, tv | tv regroupe séries et épisodes. |
lang | all, vf, vo | Langue explicitement annoncée. Les langues inconnues ne correspondent pas à VF ou VO. |
Réponse JSON
Exemple de structure ; les valeurs ci-dessous sont illustratives.
{
"ok": true,
"items": [{
"id": 124,
"content_key": "identifiant-stable-du-contenu",
"event_type": "episode_added",
"source": "s3", "type": "tv", "tmdb": 1399,
"title": "Titre de la série", "season": 1, "episode": 2,
"episode_end": null, "languages": ["vf"], "poster": null,
"announced_at": "2026-10-25T17:00:00Z",
"embed_url": "https://fluxora.sbs/embed/zenix?tmdb=1399&type=tv&lang=vf&season=1&episode=2",
"availability": { "playback_confirmed": null },
"message": {
"title": "Nouvel épisode", "description": "Texte de l’annonce Discord",
"fields": [], "url": "https://fluxora.sbs/embed/zenix?tmdb=1399&type=tv&season=1&episode=2",
"thumbnail": null, "image": null, "timestamp": "2026-10-25T17:00:00Z"
}
}],
"next_cursor": 124, "has_more": false,
"meta": { "initial_snapshot": false, "latest_id": 124, "poll_after_seconds": 60, "timezone": "UTC", "coverage": "existing_webhook_announcements" }
}
message reprend les textes, champs et images publics de l’annonce ; aucun webhook, jeton ni identifiant de salon privé n’est exposé. Le lien embed_url ouvre le lecteur Fluxora. Les textes peuvent contenir du Markdown : utilisez textContent, jamais une injection HTML directe.
Pour ouvrir votre propre fiche film ou série, construisez votre URL avec tmdb, type, season et episode. embed_url est un lien public sans PK : gardez votre PK habituelle lorsque vous intégrez le lecteur sur votre site.
event_type vaut movie_added, series_added, season_added ou episode_added. episode_end est renseigné pour une plage annoncée. languages: [] signifie « non précisé ». announced_at est la date de l’annonce en UTC, pas la date de sortie du film. Un événement peut être indexé après son annonce ; le curseur suit toujours l’ordre des identifiants.
Notifications sur votre site : exemple JavaScript
<ul id="fluxora-news"></ul>
<script>
const cursorKey = 'fluxora-announcements-all-v1';
let cursor = localStorage.getItem(cursorKey);
const seen = new Set();
async function pollFluxora() {
try {
let more;
do {
const url = new URL('https://fluxora.sbs/api/announcements');
url.searchParams.set('limit', '100');
if (cursor !== null) url.searchParams.set('after', cursor);
const response = await fetch(url, { signal: AbortSignal.timeout(10000) });
if (!response.ok) throw new Error('Flux temporairement indisponible');
const data = await response.json();
for (const event of data.items) {
if (seen.has(event.id)) continue;
const li = document.createElement('li');
const a = document.createElement('a');
a.href = event.embed_url;
a.textContent = event.message.title || event.title;
li.append(a);
document.getElementById('fluxora-news').prepend(li);
seen.add(event.id);
}
// Enregistrer seulement après avoir traité les événements.
cursor = String(data.next_cursor);
localStorage.setItem(cursorKey, cursor);
more = data.has_more;
} while (more);
} catch (error) {
console.warn(error.message); // Curseur conservé : reprise au prochain passage.
} finally {
setTimeout(pollFluxora, 60000);
}
}
pollFluxora();
</script>
Pagination, fiabilité et disponibilité
Interrogez le flux toutes les 60 secondes. Si has_more vaut true, poursuivez avec next_cursor jusqu’à avoir tout traité. Le curseur peut avancer même si le filtre ne renvoie aucun événement. Gardez un curseur distinct par combinaison de filtres, et dédupliquez avec id. Pour ne prévenir qu’une seule fois du même contenu malgré plusieurs annonces de sources, utilisez aussi content_key.
Le flux provient des circuits d’annonces existants : il ne couvre pas tout le catalogue ni toutes les modifications. L’historique commence à son activation, avec une reprise limitée d’annonces antérieures. Une panne Discord n’interrompt pas l’API ; les événements du circuit existant sont indexés séparément, normalement sous une minute, sans garantie de délai absolu.
playback_confirmed décrit uniquement la vérification effectuée au moment de l’annonce : true confirmé, false non confirmé, null non vérifié. Ce n’est pas l’état de lecture actuel. Pour celui-ci, utilisez Availability API. Une annonce de série ou de saison ne prouve pas tous ses épisodes.
HTTP 200 : réponse valide, y compris une liste vide ; 204 : précontrôle OPTIONS ; 405 : méthode interdite ; 422 : paramètre invalide ; 429 : ralentir selon Retry-After ; 503 : index temporairement indisponible, conserver le curseur et réessayer. GET, HEAD et OPTIONS sont autorisés. CORS public, cache de 15 secondes ; aucun cookie ni clé à envoyer.
Embed URL
Base pattern:
https://fluxora.sbs/embed/zenix?tmdb=ID&type=movie|tv&season=1&episode=1&lang=vf|vo
Integration Examples
HTML
<!-- Movie --> <iframe src="https://fluxora.sbs/embed/zenix?tmdb=550&type=movie&lang=vf" width="100%" height="500" frameborder="0" allowfullscreen allow="autoplay; fullscreen; encrypted-media"> </iframe> <!-- TV Series --> <iframe src="https://fluxora.sbs/embed/zenix?tmdb=71712&type=tv&season=1&episode=1&lang=vf" width="100%" height="500" frameborder="0" allowfullscreen allow="autoplay; fullscreen; encrypted-media"> </iframe>
React
function ZenixPlayer({ tmdb, type = 'movie', season = 1, episode = 1, lang = 'vf' }) {
const params = new URLSearchParams({ tmdb, type, lang });
if (type === 'tv') { params.set('season', season); params.set('episode', episode); }
const src = `https://fluxora.sbs/embed/zenix?${params}`;
return (
<iframe
src={src}
width="100%" height="500"
frameBorder="0"
allowFullScreen
allow="autoplay; fullscreen; encrypted-media"
title="Zenix Player"
/>
);
}
WordPress
// functions.php — shortcode [zenix tmdb="550" type="movie" lang="vf"]
function zenix_embed_shortcode($atts) {
$a = shortcode_atts([
'tmdb' => '', 'type' => 'movie',
'season' => '1', 'episode' => '1', 'lang' => 'vf'
], $atts);
if (!$a['tmdb']) return '';
$url = 'https://fluxora.sbs/embed/zenix?' . http_build_query(array_filter([
'tmdb' => $a['tmdb'], 'type' => $a['type'],
'season' => $a['type'] === 'tv' ? $a['season'] : null,
'episode' => $a['type'] === 'tv' ? $a['episode'] : null,
'lang' => $a['lang']
]));
return '<iframe src="' . esc_url($url) . '" width="100%" height="500" '
. 'frameborder="0" allowfullscreen '
. 'allow="autoplay; fullscreen; encrypted-media"></iframe>';
}
add_shortcode('zenix', 'zenix_embed_shortcode');
Usage: [zenix tmdb="550" type="movie" lang="vf"]