{
  "aboutHtml": "<p>Vidu Q2 crée une vidéo à partir d’une scène écrite au moyen du profil texte-vers-vidéo sélectionné par viduq2. Ses entrées obligatoires sont l’identifiant exact du modèle et un prompt décrivant la scène. Utilisez-le pour un court concept de produit, un plan d’ensemble ou une action de personnage dont l’apparence et le mouvement peuvent être précisés par des mots. Cette méthode configurée est texte-vers-vidéo ; sa description n’attribue pas au sélecteur un mode distinct de référence image ou de modification vidéo.</p><p>Construisez le brief autour d’une séquence visible. Identifiez le sujet, le lieu, l’action, l’échelle de plan, le mouvement de caméra et la composition finale. Pour un concept de produit, décrivez un objet sur une table, la lumière se déplaçant sur sa matière et une lente approche de caméra qui se termine sur un détail reconnaissable. Pour une scène de lieu, présentez l’environnement avant de vous rapprocher du point d’intérêt. Adaptez l’action à la durée de clip choisie afin que la scène ait le temps d’atteindre la fin voulue.</p><p>La limite du prompt est de 2 000 caractères. Placez d’abord le sujet et l’action essentiels, puis ajoutez les détails d’éclairage, de matière, d’environnement et de caméra qui modifient le résultat voulu. Précisez le style visuel dans le prompt. Le guide propre à Q2 indique que les paramètres distincts style et movement_amplitude sont sans effet pour ce modèle : le préréglage general ou anime et les options d’amplitude de mouvement ne remplacent donc pas une description claire de la scène.</p><p>Le réglage de durée propre au modèle accepte des secondes entières de un à dix. Les choix de résolution propres à Q2 sont 540p, 720p et 1080p, avec 720p comme valeur par défaut documentée. Choisissez ensemble la durée et la résolution selon l’action et la destination. Une brève mise en valeur et un mouvement plus long demandent des rythmes différents ; augmenter la durée demandée doit servir la séquence visible plutôt que simplement étirer un brief inchangé. Vérifiez les dimensions et la longueur réelles du clip renvoyé lors de la préparation de son intégration finale.</p><p>Les choix documentés du paramètre aspect_ratio sont 16:9, 9:16, 3:4, 4:3 et 1:1, avec 16:9 par défaut. Le guide inclut explicitement 3:4 et 4:3 pour la famille Q2. Choisissez le cadrage avant la génération et décrivez une composition adaptée : gardez un sujet principal lisible dans une vue en portrait, ou utilisez la largeur d’un cadre paysage pour le décor environnant. Gardez la vue finale assez claire pour la page, la présentation ou l’ajout ultérieur de légendes prévu.</p><p>Le champ seed contrôle la variation. L’omettre ou fournir 0 sélectionne une valeur aléatoire ; une valeur non nulle sélectionne l’option documentée de graine fixe pour une génération reproductible. Conservez la graine renvoyée avec le prompt et les réglages pour comparer les versions. L’opération commune documente aussi les réglages audio et off_peak spécifiquement pour les modèles Q3. Ces options Q3 ne sont pas des capacités attribuées à ce profil Q2 ; préparez cette requête autour de son entrée textuelle et de sa sortie vidéo documentées.</p><p>La génération est asynchrone. La soumission renvoie task_id et un état initial, avec created pour une tâche nouvellement créée. Conservez cette identité de tâche pendant le suivi du traitement. La consultation de résultat documentée utilise state=success pour un résultat réussi et renvoie un tableau creations. Chaque élément contient l’URL de sa vidéo dans creations[].url ; enregistrez chaque vidéo renvoyée plutôt que de supposer que la tâche contient toujours exactement une création.</p><p>La documentation de résultat rapporte aussi la durée et les fps de la vidéo réelle ainsi que la largeur et la hauteur de sa résolution. Gardez ces valeurs rapportées avec le clip achevé au lieu de considérer la cadence ou les dimensions d’un exemple comme une spécification fixe de Q2. La réponse de création de tâche comprend une valeur credits avec la configuration de requête. Conservez ces métadonnées de tâche rapportées et l’identité de la tâche achevée avec le résultat, afin que chaque vidéo reste liée à ses réglages de génération.</p><p>Vérifiez toute la séquence par rapport au brief d’origine : l’apparence du sujet, la forme des objets, la direction du mouvement, la continuité de caméra et la vue finale voulue. Pour une révision, identifiez le détail concret qui ne correspond pas au brief et préservez les parties réussies de la scène. Gardez ensemble le prompt, le sélecteur exact, les réglages, l’identité de tâche et les vidéos achevées afin qu’une comparaison ultérieure repose sur les résultats réels.</p>",
  "aboutText": "Vidu Q2 crée une vidéo à partir d’une scène écrite au moyen du profil texte-vers-vidéo sélectionné par viduq2. Ses entrées obligatoires sont l’identifiant exact du modèle et un prompt décrivant la scène. Utilisez-le pour un court concept de produit, un plan d’ensemble ou une action de personnage dont l’apparence et le mouvement peuvent être précisés par des mots. Cette méthode configurée est texte-vers-vidéo ; sa description n’attribue pas au sélecteur un mode distinct de référence image ou de modification vidéo.\n\nConstruisez le brief autour d’une séquence visible. Identifiez le sujet, le lieu, l’action, l’échelle de plan, le mouvement de caméra et la composition finale. Pour un concept de produit, décrivez un objet sur une table, la lumière se déplaçant sur sa matière et une lente approche de caméra qui se termine sur un détail reconnaissable. Pour une scène de lieu, présentez l’environnement avant de vous rapprocher du point d’intérêt. Adaptez l’action à la durée de clip choisie afin que la scène ait le temps d’atteindre la fin voulue.\n\nLa limite du prompt est de 2 000 caractères. Placez d’abord le sujet et l’action essentiels, puis ajoutez les détails d’éclairage, de matière, d’environnement et de caméra qui modifient le résultat voulu. Précisez le style visuel dans le prompt. Le guide propre à Q2 indique que les paramètres distincts style et movement_amplitude sont sans effet pour ce modèle : le préréglage general ou anime et les options d’amplitude de mouvement ne remplacent donc pas une description claire de la scène.\n\nLe réglage de durée propre au modèle accepte des secondes entières de un à dix. Les choix de résolution propres à Q2 sont 540p, 720p et 1080p, avec 720p comme valeur par défaut documentée. Choisissez ensemble la durée et la résolution selon l’action et la destination. Une brève mise en valeur et un mouvement plus long demandent des rythmes différents ; augmenter la durée demandée doit servir la séquence visible plutôt que simplement étirer un brief inchangé. Vérifiez les dimensions et la longueur réelles du clip renvoyé lors de la préparation de son intégration finale.\n\nLes choix documentés du paramètre aspect_ratio sont 16:9, 9:16, 3:4, 4:3 et 1:1, avec 16:9 par défaut. Le guide inclut explicitement 3:4 et 4:3 pour la famille Q2. Choisissez le cadrage avant la génération et décrivez une composition adaptée : gardez un sujet principal lisible dans une vue en portrait, ou utilisez la largeur d’un cadre paysage pour le décor environnant. Gardez la vue finale assez claire pour la page, la présentation ou l’ajout ultérieur de légendes prévu.\n\nLe champ seed contrôle la variation. L’omettre ou fournir 0 sélectionne une valeur aléatoire ; une valeur non nulle sélectionne l’option documentée de graine fixe pour une génération reproductible. Conservez la graine renvoyée avec le prompt et les réglages pour comparer les versions. L’opération commune documente aussi les réglages audio et off_peak spécifiquement pour les modèles Q3. Ces options Q3 ne sont pas des capacités attribuées à ce profil Q2 ; préparez cette requête autour de son entrée textuelle et de sa sortie vidéo documentées.\n\nLa génération est asynchrone. La soumission renvoie task_id et un état initial, avec created pour une tâche nouvellement créée. Conservez cette identité de tâche pendant le suivi du traitement. La consultation de résultat documentée utilise state=success pour un résultat réussi et renvoie un tableau creations. Chaque élément contient l’URL de sa vidéo dans creations[].url ; enregistrez chaque vidéo renvoyée plutôt que de supposer que la tâche contient toujours exactement une création.\n\nLa documentation de résultat rapporte aussi la durée et les fps de la vidéo réelle ainsi que la largeur et la hauteur de sa résolution. Gardez ces valeurs rapportées avec le clip achevé au lieu de considérer la cadence ou les dimensions d’un exemple comme une spécification fixe de Q2. La réponse de création de tâche comprend une valeur credits avec la configuration de requête. Conservez ces métadonnées de tâche rapportées et l’identité de la tâche achevée avec le résultat, afin que chaque vidéo reste liée à ses réglages de génération.\n\nVérifiez toute la séquence par rapport au brief d’origine : l’apparence du sujet, la forme des objets, la direction du mouvement, la continuité de caméra et la vue finale voulue. Pour une révision, identifiez le détail concret qui ne correspond pas au brief et préservez les parties réussies de la scène. Gardez ensemble le prompt, le sélecteur exact, les réglages, l’identité de tâche et les vidéos achevées afin qu’une comparaison ultérieure repose sur les résultats réels.",
  "editorialOverlay": {
    "copy_fields": null,
    "copy_sha256": null,
    "copy_source": null,
    "html_sha256": "0b5e6178b30de88141d585a1295c419eda9c0936a755ab03b00e0f1334cdaa2e",
    "module_sha256": "ee9dc1c50b1e6a8fb7fa062030fcb4646b9aaaeb08be513b723a5a92a7290f06",
    "raw_model_unchanged": true,
    "schema": "ailoot-native-model-editorial-v1"
  },
  "locale": "fr-be",
  "methods": [
    {
      "html": "<div class=\"sheet-head\"><span class=\"mav\" aria-hidden=\"true\">•</span><h2 id=\"sheet-title\">Vidu: Q2 Text-to-Video</h2><button class=\"icon-btn\" type=\"button\" data-close-sheet aria-label=\"Fermer\">×</button></div><div class=\"idline\"><span>Vidu /</span><code>viduq2</code><button type=\"button\" id=\"copy-id\">Copier l’ID</button></div><nav class=\"card-jump-nav\" aria-label=\"Rubriques de la fiche modèle\"><button type=\"button\" data-card-jump=\"overview\">Premiers pas</button><button type=\"button\" data-card-jump=\"methods\">Entrées et méthodes</button><button type=\"button\" data-card-jump=\"pricing\">Tarifs</button><button type=\"button\" data-card-jump=\"examples\">Exemples</button><button type=\"button\" data-card-jump=\"results\">Résultats</button><button type=\"button\" data-card-jump=\"aliases\">Alias</button></nav><div class=\"card-method-tabs\" role=\"tablist\" aria-label=\"Méthodes API\"><button type=\"button\" role=\"tab\" tabindex=\"0\" aria-controls=\"card-method-content\" aria-selected=\"true\" id=\"card-method-tab-0\" data-card-method=\"Ultra|videos|/v1/videos|viduq2\">Vidéo</button></div><div id=\"card-method-content\" role=\"tabpanel\" aria-labelledby=\"card-method-tab-0\"><section class=\"card-section\" data-card-section=\"overview\"><h3 tabindex=\"-1\">Premiers pas</h3><p class=\"mdesc-full\">Vidu Q2 crée une vidéo à partir d’un brief de scène textuel, avec une durée de 1 à 10 secondes, une sortie 540p, 720p ou 1080p et cinq rapports d’aspect. Ce profil viduq2 précis utilise le prompt pour le style et le mouvement et renvoie son résultat par une tâche asynchrone.</p><dl class=\"card-io\" data-card-io><div><dt>Entrées acceptées</dt><dd>Texte</dd></div><div><dt>Résultats</dt><dd>Vidéo</dd></div></dl><details class=\"card-about\"><summary>À propos du modèle</summary><p class=\"note-s\" data-model-method-boundary>Cette description présente les capacités du modèle. Les entrées, sorties et options disponibles dans Ailoot pour la méthode sélectionnée figurent ci-dessous.</p><div class=\"mabout\" id=\"m-about\"><p>Vidu Q2 crée une vidéo à partir d’une scène écrite au moyen du profil texte-vers-vidéo sélectionné par viduq2. Ses entrées obligatoires sont l’identifiant exact du modèle et un prompt décrivant la scène. Utilisez-le pour un court concept de produit, un plan d’ensemble ou une action de personnage dont l’apparence et le mouvement peuvent être précisés par des mots. Cette méthode configurée est texte-vers-vidéo ; sa description n’attribue pas au sélecteur un mode distinct de référence image ou de modification vidéo.</p><p>Construisez le brief autour d’une séquence visible. Identifiez le sujet, le lieu, l’action, l’échelle de plan, le mouvement de caméra et la composition finale. Pour un concept de produit, décrivez un objet sur une table, la lumière se déplaçant sur sa matière et une lente approche de caméra qui se termine sur un détail reconnaissable. Pour une scène de lieu, présentez l’environnement avant de vous rapprocher du point d’intérêt. Adaptez l’action à la durée de clip choisie afin que la scène ait le temps d’atteindre la fin voulue.</p><p>La limite du prompt est de 2 000 caractères. Placez d’abord le sujet et l’action essentiels, puis ajoutez les détails d’éclairage, de matière, d’environnement et de caméra qui modifient le résultat voulu. Précisez le style visuel dans le prompt. Le guide propre à Q2 indique que les paramètres distincts style et movement_amplitude sont sans effet pour ce modèle : le préréglage general ou anime et les options d’amplitude de mouvement ne remplacent donc pas une description claire de la scène.</p><p>Le réglage de durée propre au modèle accepte des secondes entières de un à dix. Les choix de résolution propres à Q2 sont 540p, 720p et 1080p, avec 720p comme valeur par défaut documentée. Choisissez ensemble la durée et la résolution selon l’action et la destination. Une brève mise en valeur et un mouvement plus long demandent des rythmes différents ; augmenter la durée demandée doit servir la séquence visible plutôt que simplement étirer un brief inchangé. Vérifiez les dimensions et la longueur réelles du clip renvoyé lors de la préparation de son intégration finale.</p><p>Les choix documentés du paramètre aspect_ratio sont 16:9, 9:16, 3:4, 4:3 et 1:1, avec 16:9 par défaut. Le guide inclut explicitement 3:4 et 4:3 pour la famille Q2. Choisissez le cadrage avant la génération et décrivez une composition adaptée : gardez un sujet principal lisible dans une vue en portrait, ou utilisez la largeur d’un cadre paysage pour le décor environnant. Gardez la vue finale assez claire pour la page, la présentation ou l’ajout ultérieur de légendes prévu.</p><p>Le champ seed contrôle la variation. L’omettre ou fournir 0 sélectionne une valeur aléatoire ; une valeur non nulle sélectionne l’option documentée de graine fixe pour une génération reproductible. Conservez la graine renvoyée avec le prompt et les réglages pour comparer les versions. L’opération commune documente aussi les réglages audio et off_peak spécifiquement pour les modèles Q3. Ces options Q3 ne sont pas des capacités attribuées à ce profil Q2 ; préparez cette requête autour de son entrée textuelle et de sa sortie vidéo documentées.</p><p>La génération est asynchrone. La soumission renvoie task_id et un état initial, avec created pour une tâche nouvellement créée. Conservez cette identité de tâche pendant le suivi du traitement. La consultation de résultat documentée utilise state=success pour un résultat réussi et renvoie un tableau creations. Chaque élément contient l’URL de sa vidéo dans creations[].url ; enregistrez chaque vidéo renvoyée plutôt que de supposer que la tâche contient toujours exactement une création.</p><p>La documentation de résultat rapporte aussi la durée et les fps de la vidéo réelle ainsi que la largeur et la hauteur de sa résolution. Gardez ces valeurs rapportées avec le clip achevé au lieu de considérer la cadence ou les dimensions d’un exemple comme une spécification fixe de Q2. La réponse de création de tâche comprend une valeur credits avec la configuration de requête. Conservez ces métadonnées de tâche rapportées et l’identité de la tâche achevée avec le résultat, afin que chaque vidéo reste liée à ses réglages de génération.</p><p>Vérifiez toute la séquence par rapport au brief d’origine : l’apparence du sujet, la forme des objets, la direction du mouvement, la continuité de caméra et la vue finale voulue. Pour une révision, identifiez le détail concret qui ne correspond pas au brief et préservez les parties réussies de la scène. Gardez ensemble le prompt, le sélecteur exact, les réglages, l’identité de tâche et les vidéos achevées afin qu’une comparaison ultérieure repose sur les résultats réels.</p></div></details></section><section class=\"card-section\" data-card-section=\"methods\"><h3 tabindex=\"-1\">Disponible dans Ailoot · entrées et méthodes</h3><details class=\"card-method\" open><summary><b>Ailoot Ultra · Vidéo</b> <code>POST /v1/videos</code></summary><dl class=\"method-capabilities\"><div><dt>Entrée</dt><dd><code>text</code></dd></div><div><dt>Sortie</dt><dd><code>video</code></dd></div></dl><div class=\"tw\" data-card-parameters data-typed-parameters><table><thead><tr><th>Champ</th><th>Type</th><th>Exigence</th><th>Valeurs et limites</th><th>Par défaut</th></tr></thead><tbody><tr data-parameter-availability=\"source_interface\"><th data-cell-label=\"Champ\" scope=\"row\"><span class=\"card-cell-label\">Champ</span><code class=\"card-field-name\">model</code></th><td data-cell-label=\"Type\" data-field-type><span class=\"card-cell-label\">Type</span><code>string</code></td><td data-cell-label=\"Exigence\"><span class=\"card-cell-label\">Exigence</span>Obligatoire</td><td data-cell-label=\"Valeurs et limites\"><span class=\"card-cell-label\">Valeurs et limites</span><div>viduq2</div></td><td data-cell-label=\"Par défaut\" data-default=\"unspecified\"><span class=\"card-cell-label\">Par défaut</span>—</td></tr><tr data-parameter-availability=\"source_interface\"><th data-cell-label=\"Champ\" scope=\"row\"><span class=\"card-cell-label\">Champ</span><code class=\"card-field-name\">prompt</code></th><td data-cell-label=\"Type\" data-field-type><span class=\"card-cell-label\">Type</span><code>string</code></td><td data-cell-label=\"Exigence\"><span class=\"card-cell-label\">Exigence</span>Obligatoire</td><td data-cell-label=\"Valeurs et limites\"><span class=\"card-cell-label\">Valeurs et limites</span><div>Conditions: Décrivez la scène à générer. La limite documentée est de 2000 caractères ; Ailoot vérifie que la chaîne n’est pas vide et conserve le texte.</div></td><td data-cell-label=\"Par défaut\" data-default=\"unspecified\"><span class=\"card-cell-label\">Par défaut</span>—</td></tr><tr data-parameter-availability=\"source_interface\"><th data-cell-label=\"Champ\" scope=\"row\"><span class=\"card-cell-label\">Champ</span><code class=\"card-field-name\">duration</code></th><td data-cell-label=\"Type\" data-field-type><span class=\"card-cell-label\">Type</span><code>integer</code></td><td data-cell-label=\"Exigence\"><span class=\"card-cell-label\">Exigence</span>Facultatif</td><td data-cell-label=\"Valeurs et limites\"><span class=\"card-cell-label\">Valeurs et limites</span><div>Minimum: 1</div><div>Maximum: 10</div><div>Conditions: La description propre au modèle viduq2 précise une durée de 1–10 secondes entières. Aucune durée par défaut propre au modèle n’est documentée.</div><div>Unité: secondes</div></td><td data-cell-label=\"Par défaut\" data-default=\"unspecified\"><span class=\"card-cell-label\">Par défaut</span>—</td></tr><tr data-parameter-availability=\"source_interface\"><th data-cell-label=\"Champ\" scope=\"row\"><span class=\"card-cell-label\">Champ</span><code class=\"card-field-name\">seed</code></th><td data-cell-label=\"Type\" data-field-type><span class=\"card-cell-label\">Type</span><code>string</code></td><td data-cell-label=\"Exigence\"><span class=\"card-cell-label\">Exigence</span>Facultatif</td><td data-cell-label=\"Valeurs et limites\"><span class=\"card-cell-label\">Valeurs et limites</span><div>Conditions: Omettez le champ ou envoyez la chaîne &quot;0&quot; pour un résultat aléatoire. Une valeur seed fournie non nulle sélectionne le comportement documenté avec seed fixe ; aucune plage numérique n’est précisée.</div></td><td data-cell-label=\"Par défaut\" data-default=\"unspecified\"><span class=\"card-cell-label\">Par défaut</span>—</td></tr><tr data-parameter-availability=\"source_interface\"><th data-cell-label=\"Champ\" scope=\"row\"><span class=\"card-cell-label\">Champ</span><code class=\"card-field-name\">aspect_ratio</code></th><td data-cell-label=\"Type\" data-field-type><span class=\"card-cell-label\">Type</span><code>string</code></td><td data-cell-label=\"Exigence\"><span class=\"card-cell-label\">Exigence</span>Facultatif</td><td data-cell-label=\"Valeurs et limites\"><span class=\"card-cell-label\">Valeurs et limites</span><div>16:9, 9:16, 3:4, 4:3, 1:1</div></td><td data-cell-label=\"Par défaut\" data-default=\"known\"><span class=\"card-cell-label\">Par défaut</span>16:9</td></tr><tr data-parameter-availability=\"source_interface\"><th data-cell-label=\"Champ\" scope=\"row\"><span class=\"card-cell-label\">Champ</span><code class=\"card-field-name\">resolution</code></th><td data-cell-label=\"Type\" data-field-type><span class=\"card-cell-label\">Type</span><code>string</code></td><td data-cell-label=\"Exigence\"><span class=\"card-cell-label\">Exigence</span>Facultatif</td><td data-cell-label=\"Valeurs et limites\"><span class=\"card-cell-label\">Valeurs et limites</span><div>540p, 720p, 1080p</div><div>Conditions: La liste propre au modèle viduq2 documente ces paliers pour 1–10 secondes. Une énumération et un tableau communs mentionnent également 360p ; son applicabilité contredit cette liste et n’est pas affirmée ici.</div></td><td data-cell-label=\"Par défaut\" data-default=\"known\"><span class=\"card-cell-label\">Par défaut</span>720p</td></tr><tr data-parameter-availability=\"source_interface\"><th data-cell-label=\"Champ\" scope=\"row\"><span class=\"card-cell-label\">Champ</span><code class=\"card-field-name\">style</code></th><td data-cell-label=\"Type\" data-field-type><span class=\"card-cell-label\">Type</span><code>string</code></td><td data-cell-label=\"Exigence\"><span class=\"card-cell-label\">Exigence</span>Facultatif</td><td data-cell-label=\"Valeurs et limites\"><span class=\"card-cell-label\">Valeurs et limites</span><div>general, anime</div><div>Conditions: La requête commune accepte ce champ, mais la documentation indique explicitement qu’il n’a aucun effet pour viduq2.</div></td><td data-cell-label=\"Par défaut\" data-default=\"known\"><span class=\"card-cell-label\">Par défaut</span>general</td></tr><tr data-parameter-availability=\"source_interface\"><th data-cell-label=\"Champ\" scope=\"row\"><span class=\"card-cell-label\">Champ</span><code class=\"card-field-name\">movement_amplitude</code></th><td data-cell-label=\"Type\" data-field-type><span class=\"card-cell-label\">Type</span><code>string</code></td><td data-cell-label=\"Exigence\"><span class=\"card-cell-label\">Exigence</span>Facultatif</td><td data-cell-label=\"Valeurs et limites\"><span class=\"card-cell-label\">Valeurs et limites</span><div>auto, small, medium, large</div><div>Conditions: La requête commune accepte ce champ, mais la documentation indique explicitement qu’il n’a aucun effet pour les modèles q2.</div></td><td data-cell-label=\"Par défaut\" data-default=\"known\"><span class=\"card-cell-label\">Par défaut</span>auto</td></tr></tbody></table></div><details class=\"card-about\" data-material-combinations><summary>Combinaisons d’éléments d’entrée</summary><p class=\"note-s\"><b></b></p></details><details class=\"note-s\" data-method-contract><summary>Paramètres et cycle de vie de la méthode</summary><div class=\"tw\" data-card-table=\"contract\"><table><thead><tr><th>Paramètre</th><th>Contrat</th></tr></thead><tbody><tr><th data-cell-label=\"Paramètre\" scope=\"row\"><span class=\"card-cell-label\">Paramètre</span><code>content_type</code></th><td data-cell-label=\"Contrat\"><span class=\"card-cell-label\">Contrat</span>application/json</td></tr><tr><th data-cell-label=\"Paramètre\" scope=\"row\"><span class=\"card-cell-label\">Paramètre</span><code>required</code></th><td data-cell-label=\"Contrat\"><span class=\"card-cell-label\">Contrat</span>model, prompt</td></tr><tr><th data-cell-label=\"Paramètre\" scope=\"row\"><span class=\"card-cell-label\">Paramètre</span><code>optional</code></th><td data-cell-label=\"Contrat\"><span class=\"card-cell-label\">Contrat</span>duration, seed, aspect_ratio, resolution, style, movement_amplitude</td></tr><tr><th data-cell-label=\"Paramètre\" scope=\"row\"><span class=\"card-cell-label\">Paramètre</span><code>material_types</code></th><td data-cell-label=\"Contrat\"><span class=\"card-cell-label\">Contrat</span>text</td></tr><tr><th data-cell-label=\"Paramètre\" scope=\"row\"><span class=\"card-cell-label\">Paramètre</span><code>additional_properties</code></th><td data-cell-label=\"Contrat\"><span class=\"card-cell-label\">Contrat</span>true</td></tr><tr><th data-cell-label=\"Paramètre\" scope=\"row\"><span class=\"card-cell-label\">Paramètre</span><code>validation_scope</code></th><td data-cell-label=\"Contrat\"><span class=\"card-cell-label\">Contrat</span>Ailoot valide les chaînes model/prompt non vides. Les types facultatifs et les limites ci-dessous constituent le contrat documenté de la requête ; les autres champs de la requête sont conservés pour le modèle sélectionné.</td></tr></tbody></table></div><p>Alias de méthode : <code>/v1/videos/generations</code></p><p>Cycle de vie : <code>submit_once_poll_original</code></p><p class=\"note-s\"><code>GET /v1/videos/{request_id}</code></p><p class=\"note-s\"><code>GET /v1/videos/generations/{request_id}</code></p><p class=\"note-s\"><code>GET /v1/videos/{request_id}/content</code></p><p class=\"note-s\"><code>GET /v1/videos/generations/{request_id}/content</code></p><p class=\"note-s\">Créez une seule fois et conservez l’id public et polling_url renvoyés.</p><p class=\"note-s\">Interrogez périodiquement l’opération d’origine et consultez state ; success et un résultat creations[].url dont vous êtes propriétaire constituent la condition d’achèvement.</p><p class=\"note-s\">Téléchargez chaque URL de vidéo renvoyée dont vous êtes propriétaire ; l’exemple ne permet pas de déduire un nombre fixe de résultats, une durée ou une fréquence d’images.</p></details></details></section><section class=\"card-section\" data-card-section=\"pricing\"><h3 tabindex=\"-1\">Tarifs</h3><div class=\"card-result-process\" data-billing-basis><h5>Calcul du coût final</h5><p class=\"note-s\">Les tarifs affichés servent à estimer le coût avant la génération. Le montant final est calculé à partir du coût enregistré pour la génération d’origine. La durée mesurée du résultat et les quantités prévisionnelles ne constituent pas la quantité finale facturable.</p></div><div data-native-semantic-method=\"v1\" data-tariff-reference-only><p class=\"note-s\" data-rate-support-note>Les tarifs n’ajoutent pas d’options de requête. Les paramètres pris en charge figurent dans la méthode sélectionnée.</p><dl data-price-conditions><dt>Mode rapide</dt><dd>Non précisé <span class=\"note-s\">Lorsque le mode rapide est sélectionné</span></dd><dt>Mode Flex</dt><dd>Non précisé <span class=\"note-s\">Lorsque le mode flex est sélectionné</span></dd><dt>Effort de raisonnement maximal</dt><dd>Non précisé <span class=\"note-s\">Lorsque l’effort de raisonnement maximal utilise l’ajustement par défaut (default)</span></dd></dl></div><div data-declared-tariff-pricing><h4>Tarifs estimés à des fins de comparaison</h4><h4>Prix par configuration</h4><p class=\"note-s\">Associez chaque coût aux conditions indiquées. Utilisez un seul tarif pour chaque ensemble de configurations alternatives.</p><div class=\"tw\" data-pricing-profiles><table><thead><tr><th>Configuration</th><th>Barème tarifaire</th><th>Quantité prévisionnelle</th><th>Coût</th></tr></thead><tbody><tr><th data-cell-label=\"Configuration\" scope=\"row\"><span class=\"card-cell-label\">Configuration</span>Tarifs de base des jetons</th><td data-cell-label=\"Barème tarifaire\"><span class=\"card-cell-label\">Barème tarifaire</span>Tarif de base</td><td data-cell-label=\"Quantité prévisionnelle\"><span class=\"card-cell-label\">Quantité prévisionnelle</span>—</td><td data-cell-label=\"Coût\"><span class=\"card-cell-label\">Coût</span><div><span>Entrée · Tokens en entrée · Estimation à des fins de comparaison uniquement</span> <b>—</b> <span class=\"price-unit\">/ 1K tokens</span></div><div><span>Sortie · Tokens en sortie · Estimation à des fins de comparaison uniquement</span> <b>—</b> <span class=\"price-unit\">/ 1K tokens</span></div><div><span>Entrée · Lecture du cache · Estimation à des fins de comparaison uniquement</span> <b>—</b> <span class=\"price-unit\">/ 1K tokens</span></div><div><span>Entrée · Écriture dans le cache · Estimation à des fins de comparaison uniquement</span> <b>—</b> <span class=\"price-unit\">/ 1K tokens</span></div><div><span>Entrée · Écriture dans le cache, 1 h · Estimation à des fins de comparaison uniquement</span> <b>—</b> <span class=\"price-unit\">/ 1K tokens</span></div></td></tr><tr><th data-cell-label=\"Configuration\" scope=\"row\"><span class=\"card-cell-label\">Configuration</span>Coût estimé de la génération</th><td data-cell-label=\"Barème tarifaire\"><span class=\"card-cell-label\">Barème tarifaire</span>—</td><td data-cell-label=\"Quantité prévisionnelle\"><span class=\"card-cell-label\">Quantité prévisionnelle</span>Estimation pour une génération</td><td data-cell-label=\"Coût\"><span class=\"card-cell-label\">Coût</span><div><span>Sortie · Coût estimé de génération · Estimation à des fins de comparaison uniquement</span> <b>$5.12</b> <span class=\"price-unit\">estimation avant génération</span></div><p class=\"note-s\">Cette estimation ne constitue ni des frais supplémentaires ni un tarif fixe pour la génération terminée.</p></td></tr></tbody></table></div></div><p class=\"note-s\">Ailoot réserve un montant estimé avant une requête. Après le résultat, le montant final est débité selon l’utilisation mesurée. Pour le streaming, le montant final à débiter est calculé à partir du relevé final d’utilisation. <a href=\"/docs/fr-be/billing/reserve/\">Fonctionnement de la réservation et du débit →</a></p></section><section class=\"card-section\" data-card-section=\"examples\"><h3 tabindex=\"-1\">Exemples de requêtes</h3><h4>Ailoot Ultra · Vidéo</h4><div class=\"code-group\"><div class=\"cg-bar\"><div class=\"cg-tabs\" role=\"tablist\" aria-label=\"Variantes du code\"><button class=\"cg-tab\" id=\"model-code-2782-tab-0\" role=\"tab\" type=\"button\" aria-controls=\"model-code-2782-panel-0\" aria-selected=\"true\" tabindex=\"0\">curl · créer une vidéo</button><button class=\"cg-tab\" id=\"model-code-2782-tab-1\" role=\"tab\" type=\"button\" aria-controls=\"model-code-2782-panel-1\" aria-selected=\"false\" tabindex=\"-1\">curl · lire la tâche d’origine</button><button class=\"cg-tab\" id=\"model-code-2782-tab-2\" role=\"tab\" type=\"button\" aria-controls=\"model-code-2782-panel-2\" aria-selected=\"false\" tabindex=\"-1\">curl · télécharger toutes vos vidéos</button></div><div class=\"cg-tools\"><button class=\"cg-btn cg-copy\" type=\"button\" aria-label=\"Copier le code\"><svg class=\"cp\" viewBox=\"0 0 16 16\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.4\"><rect x=\"5.25\" y=\"5.25\" width=\"8.5\" height=\"8.5\" rx=\"1.75\"/><path d=\"M10.75 5.25V3.5a1.25 1.25 0 0 0-1.25-1.25H3.5A1.25 1.25 0 0 0 2.25 3.5v6a1.25 1.25 0 0 0 1.25 1.25h1.75\"/></svg><svg class=\"ok\" viewBox=\"0 0 16 16\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.4\"><path d=\"m3 8.5 3.25 3.25L13 5\"/></svg></button></div></div><div class=\"cg-body\"><div class=\"cg-pane\" id=\"model-code-2782-panel-0\" role=\"tabpanel\" aria-labelledby=\"model-code-2782-tab-0\"><pre data-lang=\"bash\"><code>set -eu\n: &quot;${AILOOT_API_KEY:?Set your Ailoot API key}&quot;\ncat &gt; request.json &lt;&lt;&#39;JSON_REQUEST&#39;\n{&quot;model&quot;:&quot;viduq2&quot;,&quot;prompt&quot;:&quot;In an ultra-realistic fashion photography style featuring light blue and pale amber tones, an astronaut in a spacesuit walks through the fog. The background consists of enchanting white and golden lights, creating a minimalist still life and an impressive panoramic scene.&quot;}\nJSON_REQUEST\ncurl --fail-with-body --silent --show-error https://api.ailoot.ai/v1/videos \\\n  -H &quot;Authorization: Bearer $AILOOT_API_KEY&quot; -H &#39;Content-Type: application/json&#39; \\\n  --data-binary @request.json -D response-headers.txt -o result.json\n</code></pre></div><div class=\"cg-pane\" id=\"model-code-2782-panel-1\" role=\"tabpanel\" aria-labelledby=\"model-code-2782-tab-1\" hidden><pre data-lang=\"bash\"><code>set -eu\n: &quot;${AILOOT_API_KEY:?Set your Ailoot API key}&quot;\npython3 - &lt;&lt;&#39;PY_POLL&#39;\nimport json\nfrom pathlib import Path\nfrom urllib.parse import quote,urljoin,urlsplit\nr=json.loads(Path(&quot;result.json&quot;).read_text())\ni=r.get(&quot;id&quot;)\nif not isinstance(i,str) or not i:raise SystemExit(&quot;Keep original response/headers/id; do not resubmit creation.&quot;)\nu=urljoin(&quot;https://api.ailoot.ai&quot;,r.get(&quot;polling_url&quot;) or &quot;/v1/videos/&quot;+quote(i,safe=&quot;&quot;))\np=urlsplit(u)\nif p.scheme!=&quot;https&quot; or p.netloc!=&quot;api.ailoot.ai&quot; or not p.path.startswith(&quot;/v1/videos/&quot;):raise SystemExit(&quot;Use the actual Ailoot lookup path.&quot;)\nPath(&quot;poll-url.txt&quot;).write_text(u)\nPY_POLL\ncurl --fail-with-body --silent --show-error &quot;$(cat poll-url.txt)&quot; -H &quot;Authorization: Bearer $AILOOT_API_KEY&quot; -D status-headers.txt -o status.json\n</code></pre></div><div class=\"cg-pane\" id=\"model-code-2782-panel-2\" role=\"tabpanel\" aria-labelledby=\"model-code-2782-tab-2\" hidden><pre data-lang=\"bash\"><code>set -eu\npython3 - &lt;&lt;&#39;PY_ASSETS&#39;\nimport json\nfrom pathlib import Path\nfrom urllib.parse import urlsplit\nr=json.loads(Path(&quot;status.json&quot;).read_text())\nif r.get(&quot;state&quot;)!=&quot;success&quot;:raise SystemExit(&quot;Poll the same original job until its owned result is returned.&quot;)\ncreations=r.get(&quot;creations&quot;)\nif not isinstance(creations,list) or not creations:raise SystemExit(&quot;No completed video creations.&quot;)\nurls=[]\nfor item in creations:\n    value=item.get(&quot;url&quot;) if isinstance(item,dict) else None\n    values=[value] if isinstance(value,str) else value\n    if not isinstance(values,list) or not values:raise SystemExit(&quot;No completed video URL.&quot;)\n    for u in values:\n        if not isinstance(u,str):raise SystemExit(&quot;Invalid returned URL.&quot;)\n        p=urlsplit(u)\n        if p.scheme!=&quot;https&quot; or p.netloc!=&quot;api.ailoot.ai&quot; or not p.path.startswith(&quot;/v1/media/assets/&quot;) or not p.path.endswith(&quot;/content&quot;) or not p.query:raise SystemExit(&quot;Wait for the actual Ailoot-owned signed result.&quot;)\n        urls.append(u)\nPath(&quot;asset-urls.txt&quot;).write_text(&quot;\\n&quot;.join(urls)+&quot;\\n&quot;)\nPY_ASSETS\nindex=0\nwhile IFS= read -r asset_url; do\n  curl --fail-with-body --silent --show-error &quot;$asset_url&quot; -o &quot;video-${index}.bin&quot;\n  index=$((index + 1))\ndone &lt; asset-urls.txt\n</code></pre></div></div></div></section><section class=\"card-section\" data-card-section=\"results\"><h3 tabindex=\"-1\">Recevoir et enregistrer les résultats</h3><h4>Ailoot Ultra · Vidéo</h4><p class=\"note-s\">Le JSON conserve l’état natif et le tableau creations, auxquels s’ajoutent les valeurs publiques id/provider_task_id/polling_url. Les URL vidéo sélectionnées sont vides avant publication et deviennent des URL signées appartenant à Ailoot après achèvement.</p><ul class=\"card-result-paths\"><li><code>GET /v1/videos/{request_id}</code></li><li><code>GET /v1/videos/generations/{request_id}</code></li><li><code>GET /v1/videos/{request_id}/content</code></li><li><code>GET /v1/videos/generations/{request_id}/content</code></li></ul><div class=\"card-result-process\" data-all-results><h5>Conserver tous les résultats terminés</h5><p class=\"note-s\">Enregistrez chaque vidéo terminée ou fichier renvoyé ; récupérez chaque URL de ressource effectivement renvoyée.</p><p class=\"note-s\">Téléchargez chaque URL réelle renvoyée dans creations[].url ; un index de contenu identifie un résultat réellement renvoyé.</p></div><div class=\"card-result-process\" data-unknown-recovery><h5>Si la réponse d’origine doit être vérifiée</h5><p class=\"note-s\">La déclaration figée n’énumère aucun état d’échec terminal. Conservez la réponse, les en-têtes et l’id d’origine, puis vérifiez cette même opération en cas d’état non reconnu ou d’erreur result_pending_check ; ne soumettez jamais de nouveau une création dont l’issue est inconnue.</p></div><details class=\"card-about\" data-output-fields><summary>Champs de la réponse</summary><div class=\"tw\" data-card-table=\"output\"><table><thead><tr><th>Champ</th><th>Type</th><th>Signification</th></tr></thead><tbody><tr><th data-cell-label=\"Champ\" scope=\"row\"><span class=\"card-cell-label\">Champ</span><code class=\"card-field-name\">id</code></th><td data-cell-label=\"Type\" data-field-type><span class=\"card-cell-label\">Type</span>string</td><td data-cell-label=\"Signification\"><span class=\"card-cell-label\">Signification</span>Identifiant public de tâche ou d’opération Ailoot renvoyé.</td></tr><tr><th data-cell-label=\"Champ\" scope=\"row\"><span class=\"card-cell-label\">Champ</span><code class=\"card-field-name\">provider_task_id</code></th><td data-cell-label=\"Type\" data-field-type><span class=\"card-cell-label\">Type</span>string</td><td data-cell-label=\"Signification\"><span class=\"card-cell-label\">Signification</span>Identifiant de la tâche d’origine, distinct de l’id public.</td></tr><tr><th data-cell-label=\"Champ\" scope=\"row\"><span class=\"card-cell-label\">Champ</span><code class=\"card-field-name\">polling_url</code></th><td data-cell-label=\"Type\" data-field-type><span class=\"card-cell-label\">Type</span>string</td><td data-cell-label=\"Signification\"><span class=\"card-cell-label\">Signification</span>Chemin de consultation Ailoot renvoyé pour la tâche d’origine.</td></tr><tr><th data-cell-label=\"Champ\" scope=\"row\"><span class=\"card-cell-label\">Champ</span><code class=\"card-field-name\">task_id</code></th><td data-cell-label=\"Type\" data-field-type><span class=\"card-cell-label\">Type</span>string when supplied</td><td data-cell-label=\"Signification\"><span class=\"card-cell-label\">Signification</span>Identifiant d’origine présent dans la réponse de création.</td></tr><tr><th data-cell-label=\"Champ\" scope=\"row\"><span class=\"card-cell-label\">Champ</span><code class=\"card-field-name\">state</code></th><td data-cell-label=\"Type\" data-field-type><span class=\"card-cell-label\">Type</span>string when supplied</td><td data-cell-label=\"Signification\"><span class=\"card-cell-label\">Signification</span>État natif de la tâche : created pour l’état d’attente figé et success pour l’achèvement.</td></tr><tr><th data-cell-label=\"Champ\" scope=\"row\"><span class=\"card-cell-label\">Champ</span><code class=\"card-field-name\">err_code</code></th><td data-cell-label=\"Type\" data-field-type><span class=\"card-cell-label\">Type</span>string when supplied</td><td data-cell-label=\"Signification\"><span class=\"card-cell-label\">Signification</span>Diagnostic de la tâche ; la spécification enregistrée ne déclare aucune liste énumérée de codes d’erreur.</td></tr><tr><th data-cell-label=\"Champ\" scope=\"row\"><span class=\"card-cell-label\">Champ</span><code class=\"card-field-name\">creations[].url</code></th><td data-cell-label=\"Type\" data-field-type><span class=\"card-cell-label\">Type</span>string|string[]</td><td data-cell-label=\"Signification\"><span class=\"card-cell-label\">Signification</span>Chaque URL de vidéo terminée sélectionnée est remplacée par une URL signée appartenant à Ailoot.</td></tr><tr><th data-cell-label=\"Champ\" scope=\"row\"><span class=\"card-cell-label\">Champ</span><code class=\"card-field-name\">creations[].video.duration</code></th><td data-cell-label=\"Type\" data-field-type><span class=\"card-cell-label\">Type</span>number when supplied</td><td data-cell-label=\"Signification\"><span class=\"card-cell-label\">Signification</span>Durée vidéo renvoyée ; vérifiez le résultat réellement terminé.</td></tr><tr><th data-cell-label=\"Champ\" scope=\"row\"><span class=\"card-cell-label\">Champ</span><code class=\"card-field-name\">creations[].video.fps</code></th><td data-cell-label=\"Type\" data-field-type><span class=\"card-cell-label\">Type</span>integer when supplied</td><td data-cell-label=\"Signification\"><span class=\"card-cell-label\">Signification</span>Fréquence d’images renvoyée ; aucune fréquence fixe n’est promise.</td></tr><tr><th data-cell-label=\"Champ\" scope=\"row\"><span class=\"card-cell-label\">Champ</span><code class=\"card-field-name\">creations[].video.resolution.width</code></th><td data-cell-label=\"Type\" data-field-type><span class=\"card-cell-label\">Type</span>integer when supplied</td><td data-cell-label=\"Signification\"><span class=\"card-cell-label\">Signification</span>Largeur de sortie renvoyée en pixels.</td></tr><tr><th data-cell-label=\"Champ\" scope=\"row\"><span class=\"card-cell-label\">Champ</span><code class=\"card-field-name\">creations[].video.resolution.height</code></th><td data-cell-label=\"Type\" data-field-type><span class=\"card-cell-label\">Type</span>integer when supplied</td><td data-cell-label=\"Signification\"><span class=\"card-cell-label\">Signification</span>Hauteur de sortie renvoyée en pixels.</td></tr></tbody></table></div></details><details class=\"card-about\" data-method-errors><summary>Erreurs et étapes suivantes</summary><div class=\"tw\" data-card-table=\"errors\"><table><thead><tr><th>Réponse</th><th>Condition</th><th>Étape suivante</th></tr></thead><tbody><tr><th data-cell-label=\"Réponse\" scope=\"row\"><span class=\"card-cell-label\">Réponse</span>400 · <code>invalid_request_error</code></th><td data-cell-label=\"Condition\"><span class=\"card-cell-label\">Condition</span>JSON/modèle invalide, chaînes obligatoires manquantes ou vides, ou index de contenu invalide.</td><td data-cell-label=\"Étape suivante\"><span class=\"card-cell-label\">Étape suivante</span></td></tr><tr><th data-cell-label=\"Réponse\" scope=\"row\"><span class=\"card-cell-label\">Réponse</span>401 · <code>authentication_error</code></th><td data-cell-label=\"Condition\"><span class=\"card-cell-label\">Condition</span>Clé API Ailoot invalide.</td><td data-cell-label=\"Étape suivante\"><span class=\"card-cell-label\">Étape suivante</span></td></tr><tr><th data-cell-label=\"Réponse\" scope=\"row\"><span class=\"card-cell-label\">Réponse</span>403 · <code>permission_error</code></th><td data-cell-label=\"Condition\"><span class=\"card-cell-label\">Condition</span>Le groupe de la clé API n’est pas autorisé à utiliser cette route média.</td><td data-cell-label=\"Étape suivante\"><span class=\"card-cell-label\">Étape suivante</span></td></tr><tr><th data-cell-label=\"Réponse\" scope=\"row\"><span class=\"card-cell-label\">Réponse</span>404 · <code>not_found_error</code></th><td data-cell-label=\"Condition\"><span class=\"card-cell-label\">Condition</span>La tâche d’origine ou le résultat demandé est absent ou n’appartient pas au même utilisateur, à la même clé API et au même groupe.</td><td data-cell-label=\"Étape suivante\"><span class=\"card-cell-label\">Étape suivante</span></td></tr><tr><th data-cell-label=\"Réponse\" scope=\"row\"><span class=\"card-cell-label\">Réponse</span>502 · <code>result_pending_check</code></th><td data-cell-label=\"Condition\"><span class=\"card-cell-label\">Condition</span>La soumission initiale ou son état est incomplet ou ne peut pas être rapproché des données disponibles ; conservez l’ID d’origine et ne soumettez pas de nouveau la requête.</td><td data-cell-label=\"Étape suivante\"><span class=\"card-cell-label\">Étape suivante</span></td></tr><tr><th data-cell-label=\"Réponse\" scope=\"row\"><span class=\"card-cell-label\">Réponse</span>503 · <code>result_pending_check</code></th><td data-cell-label=\"Condition\"><span class=\"card-cell-label\">Condition</span>L’association d’origine, la route ou le média dont vous êtes propriétaire fait encore l’objet de vérifications ; poursuivez la vérification de cette opération d’origine.</td><td data-cell-label=\"Étape suivante\"><span class=\"card-cell-label\">Étape suivante</span></td></tr><tr><th data-cell-label=\"Réponse\" scope=\"row\"><span class=\"card-cell-label\">Réponse</span>503 · <code>server_error</code></th><td data-cell-label=\"Condition\"><span class=\"card-cell-label\">Condition</span>Le service de médias ou le stockage des tâches d’origine est indisponible.</td><td data-cell-label=\"Étape suivante\"><span class=\"card-cell-label\">Étape suivante</span></td></tr></tbody></table></div></details></section><section class=\"card-section\" data-card-section=\"aliases\"><h3 tabindex=\"-1\">Alias</h3><h4>Alias du modèle</h4><p class=\"note-s\"><span data-model-alias-route=\"Ultra\"><b>Ailoot Ultra</b> <a href=\"#m=viduq2&amp;route=Ultra&amp;caller=viduq2&amp;fmt=videos\"><code>viduq2</code></a></span></p><h4>Alias des chemins de méthode</h4><p class=\"note-s\"><code>/v1/videos/generations</code></p><h4>ID d’appel associés</h4><p class=\"note-s\"><a href=\"#m=viduq2&amp;route=Ultra&amp;caller=viduq2&amp;fmt=videos\"><code>viduq2</code></a></p></section></div>",
      "method_identity": {
        "effective_request_model_id": "viduq2",
        "fmt": "videos",
        "http": "POST",
        "path": "/v1/videos",
        "request_model_id": "viduq2",
        "route_label": "Ultra"
      },
      "method_key": "Ultra|videos|/v1/videos|viduq2",
      "ordinal": 0,
      "rawMethod": {
        "available": null,
        "billing_basis": {
          "basis": "original_invoice_usd",
          "description": "Les tarifs affichés servent à estimer le coût avant la génération. Le montant final est calculé à partir du coût enregistré pour la génération d’origine. La durée mesurée du résultat et les quantités prévisionnelles ne constituent pas la quantité finale facturable.",
          "forecast_quantity_is_estimate": true,
          "physical_output_is_billable_quantity": false,
          "version": "original_invoice_usd_v1"
        },
        "cache_read": null,
        "cache_write": null,
        "cache_write_1h": null,
        "contract": {
          "data": {
            "errors": [
              {
                "condition": "JSON/modèle invalide, chaînes obligatoires manquantes ou vides, ou index de contenu invalide.",
                "http_status": 400,
                "type": "invalid_request_error"
              },
              {
                "condition": "Clé API Ailoot invalide.",
                "http_status": 401,
                "type": "authentication_error"
              },
              {
                "condition": "Le groupe de la clé API n’est pas autorisé à utiliser cette route média.",
                "http_status": 403,
                "type": "permission_error"
              },
              {
                "condition": "La tâche d’origine ou le résultat demandé est absent ou n’appartient pas au même utilisateur, à la même clé API et au même groupe.",
                "http_status": 404,
                "type": "not_found_error"
              },
              {
                "condition": "La soumission initiale ou son état est incomplet ou ne peut pas être rapproché des données disponibles ; conservez l’ID d’origine et ne soumettez pas de nouveau la requête.",
                "http_status": 502,
                "type": "result_pending_check"
              },
              {
                "condition": "L’association d’origine, la route ou le média dont vous êtes propriétaire fait encore l’objet de vérifications ; poursuivez la vérification de cette opération d’origine.",
                "http_status": 503,
                "type": "result_pending_check"
              },
              {
                "condition": "Le service de médias ou le stockage des tâches d’origine est indisponible.",
                "http_status": 503,
                "type": "server_error"
              }
            ],
            "ignored_fields": [
              "style",
              "movement_amplitude"
            ],
            "lifecycle": {
              "cancel_endpoint": null,
              "completed_states": [
                "success"
              ],
              "content": [
                {
                  "http": "GET",
                  "path": "/v1/videos/{request_id}/content",
                  "query": {
                    "index": "actual output index; default 0"
                  }
                },
                {
                  "http": "GET",
                  "path": "/v1/videos/generations/{request_id}/content",
                  "query": {
                    "index": "actual output index; default 0"
                  }
                }
              ],
              "content_pending": "Original status JSON until publication.",
              "content_ready": {
                "http_status": 303,
                "location": "actual signed Ailoot-owned asset URL"
              },
              "create": {
                "http": "POST",
                "path": "/v1/videos"
              },
              "failed_states": [],
              "id_source": "Use the actual returned public id or X-Ailoot-Task-Id and polling_url. Keep task_id/provider_task_id separate; status lookup can retain the original task identity when the native fetch omits it.",
              "mode": "submit_once_poll_original",
              "owned_result": {
                "http": "GET",
                "path": "/v1/media/assets/{asset_id}"
              },
              "pending_states": [
                "created"
              ],
              "signed_asset_lifetime_seconds": 86400,
              "state_field": "state",
              "status": [
                {
                  "http": "GET",
                  "path": "/v1/videos/{request_id}"
                },
                {
                  "http": "GET",
                  "path": "/v1/videos/generations/{request_id}"
                }
              ],
              "submit_status": 200,
              "unknown": "La déclaration figée n’énumère aucun état d’échec terminal. Conservez la réponse, les en-têtes et l’id d’origine, puis vérifiez cette même opération en cas d’état non reconnu ou d’erreur result_pending_check ; ne soumettez jamais de nouveau une création dont l’issue est inconnue.",
              "unknown_no_replay": true
            },
            "material_combinations": [
              [
                "text"
              ]
            ],
            "operation_modes": [
              "text_to_video"
            ],
            "outputs": {
              "additional_media_boundary": "Only creations[].url is selected for owned video delivery. No owned cover-image or callback result flow is established.",
              "all_results": "Téléchargez chaque URL réelle renvoyée dans creations[].url ; un index de contenu identifie un résultat réellement renvoyé.",
              "every_actual_output": true,
              "family": "video",
              "fields": [
                {
                  "description": "Identifiant public de tâche ou d’opération Ailoot renvoyé.",
                  "name": "id",
                  "type": "string"
                },
                {
                  "description": "Identifiant de la tâche d’origine, distinct de l’id public.",
                  "name": "provider_task_id",
                  "type": "string"
                },
                {
                  "description": "Chemin de consultation Ailoot renvoyé pour la tâche d’origine.",
                  "name": "polling_url",
                  "type": "string"
                },
                {
                  "description": "Identifiant d’origine présent dans la réponse de création.",
                  "name": "task_id",
                  "type": "string when supplied"
                },
                {
                  "description": "État natif de la tâche : created pour l’état d’attente figé et success pour l’achèvement.",
                  "name": "state",
                  "type": "string when supplied"
                },
                {
                  "description": "Diagnostic de la tâche ; la spécification enregistrée ne déclare aucune liste énumérée de codes d’erreur.",
                  "name": "err_code",
                  "type": "string when supplied"
                },
                {
                  "description": "Chaque URL de vidéo terminée sélectionnée est remplacée par une URL signée appartenant à Ailoot.",
                  "name": "creations[].url",
                  "type": "string|string[]"
                },
                {
                  "description": "Durée vidéo renvoyée ; vérifiez le résultat réellement terminé.",
                  "name": "creations[].video.duration",
                  "type": "number when supplied"
                },
                {
                  "description": "Fréquence d’images renvoyée ; aucune fréquence fixe n’est promise.",
                  "name": "creations[].video.fps",
                  "type": "integer when supplied"
                },
                {
                  "description": "Largeur de sortie renvoyée en pixels.",
                  "name": "creations[].video.resolution.width",
                  "type": "integer when supplied"
                },
                {
                  "description": "Hauteur de sortie renvoyée en pixels.",
                  "name": "creations[].video.resolution.height",
                  "type": "integer when supplied"
                }
              ],
              "format": null,
              "maximum_outputs": null,
              "ownership": "Selected video outputs are copied, reopened and SHA256/length/positive-duration checked before publication.",
              "result": "Le JSON conserve l’état natif et le tableau creations, auxquels s’ajoutent les valeurs publiques id/provider_task_id/polling_url. Les URL vidéo sélectionnées sont vides avant publication et deviennent des URL signées appartenant à Ailoot après achèvement."
            },
            "parameters": [
              {
                "availability": "source_interface",
                "default": null,
                "default_known": false,
                "enum": [
                  "viduq2"
                ],
                "enum_known": true,
                "name": "model",
                "required": true,
                "type": "string"
              },
              {
                "availability": "source_interface",
                "conditions": "Décrivez la scène à générer. La limite documentée est de 2000 caractères ; Ailoot vérifie que la chaîne n’est pas vide et conserve le texte.",
                "default": null,
                "default_known": false,
                "enum": null,
                "enum_known": false,
                "maxLength": 2000,
                "minLength": 1,
                "name": "prompt",
                "required": true,
                "type": "string"
              },
              {
                "availability": "source_interface",
                "conditions": "La description propre au modèle viduq2 précise une durée de 1–10 secondes entières. Aucune durée par défaut propre au modèle n’est documentée.",
                "default": null,
                "default_known": false,
                "enum": null,
                "enum_known": false,
                "maximum": 10,
                "minimum": 1,
                "name": "duration",
                "required": false,
                "type": "integer",
                "unit": "secondes"
              },
              {
                "availability": "source_interface",
                "conditions": "Omettez le champ ou envoyez la chaîne \"0\" pour un résultat aléatoire. Une valeur seed fournie non nulle sélectionne le comportement documenté avec seed fixe ; aucune plage numérique n’est précisée.",
                "default": null,
                "default_known": false,
                "enum": null,
                "enum_known": false,
                "name": "seed",
                "required": false,
                "type": "string"
              },
              {
                "availability": "source_interface",
                "default": "16:9",
                "default_known": true,
                "enum": [
                  "16:9",
                  "9:16",
                  "3:4",
                  "4:3",
                  "1:1"
                ],
                "enum_known": true,
                "name": "aspect_ratio",
                "required": false,
                "type": "string"
              },
              {
                "availability": "source_interface",
                "conditions": "La liste propre au modèle viduq2 documente ces paliers pour 1–10 secondes. Une énumération et un tableau communs mentionnent également 360p ; son applicabilité contredit cette liste et n’est pas affirmée ici.",
                "default": "720p",
                "default_known": true,
                "enum": [
                  "540p",
                  "720p",
                  "1080p"
                ],
                "enum_known": true,
                "name": "resolution",
                "required": false,
                "type": "string"
              },
              {
                "availability": "source_interface",
                "conditions": "La requête commune accepte ce champ, mais la documentation indique explicitement qu’il n’a aucun effet pour viduq2.",
                "default": "general",
                "default_known": true,
                "enum": [
                  "general",
                  "anime"
                ],
                "enum_known": true,
                "name": "style",
                "required": false,
                "type": "string"
              },
              {
                "availability": "source_interface",
                "conditions": "La requête commune accepte ce champ, mais la documentation indique explicitement qu’il n’a aucun effet pour les modèles q2.",
                "default": "auto",
                "default_known": true,
                "enum": [
                  "auto",
                  "small",
                  "medium",
                  "large"
                ],
                "enum_known": true,
                "name": "movement_amplitude",
                "required": false,
                "type": "string"
              }
            ],
            "profile_binding": "Literal viduq2 model with the documented Ailoot videos interface.",
            "request_schema": {
              "additionalProperties": true,
              "properties": {
                "aspect_ratio": {
                  "default": "16:9",
                  "enum": [
                    "16:9",
                    "9:16",
                    "3:4",
                    "4:3",
                    "1:1"
                  ],
                  "type": "string"
                },
                "duration": {
                  "maximum": 10,
                  "minimum": 1,
                  "type": "integer"
                },
                "model": {
                  "const": "viduq2",
                  "minLength": 1,
                  "type": "string"
                },
                "movement_amplitude": {
                  "default": "auto",
                  "enum": [
                    "auto",
                    "small",
                    "medium",
                    "large"
                  ],
                  "type": "string"
                },
                "prompt": {
                  "maxLength": 2000,
                  "minLength": 1,
                  "type": "string"
                },
                "resolution": {
                  "default": "720p",
                  "enum": [
                    "540p",
                    "720p",
                    "1080p"
                  ],
                  "type": "string"
                },
                "seed": {
                  "type": "string"
                },
                "style": {
                  "default": "general",
                  "enum": [
                    "general",
                    "anime"
                  ],
                  "type": "string"
                }
              },
              "required": [
                "model",
                "prompt"
              ],
              "type": "object"
            },
            "source_ambiguities": [
              "The shared enum and table mention 360p, while the model-specific viduq2 resolution description lists 540p/720p/1080p. The method asserts only the explicit model-specific list.",
              "The shared duration example uses a quoted string despite an integer schema. The copyable viduq2 example omits that optional field; an explicit duration follows the documented integer type.",
              "No model-specific default duration, maximum output count, generated-file retention period, cancellation endpoint or terminal failure-state list is established by these saved documents.",
              "The documented fetch uses an id path parameter; the pinned declaration names that same substituted value task_id. The fetch example has no task_id field, which the current client accepts only by retaining the original task identity."
            ],
            "unsupported": [
              "Image-guided input, video editing and extension are not part of this text-to-video method.",
              "The audio and off_peak parameters are documented only for other model selectors, not viduq2.",
              "No live streaming, callback completion or owned cover-image result contract is established here."
            ]
          },
          "hints": [
            "Créez une seule fois et conservez l’id public et polling_url renvoyés.",
            "Interrogez périodiquement l’opération d’origine et consultez state ; success et un résultat creations[].url dont vous êtes propriétaire constituent la condition d’achèvement.",
            "Téléchargez chaque URL de vidéo renvoyée dont vous êtes propriétaire ; l’exemple ne permet pas de déduire un nombre fixe de résultats, une durée ou une fréquence d’images."
          ],
          "input": {
            "additional_properties": true,
            "content_type": "application/json",
            "material_types": [
              "text"
            ],
            "optional": [
              "duration",
              "seed",
              "aspect_ratio",
              "resolution",
              "style",
              "movement_amplitude"
            ],
            "required": [
              "model",
              "prompt"
            ],
            "validation_scope": "Ailoot valide les chaînes model/prompt non vides. Les types facultatifs et les limites ci-dessous constituent le contrat documenté de la requête ; les autres champs de la requête sont conservés pour le modèle sélectionné."
          },
          "lifecycle": {
            "cancel_endpoint": null,
            "completed_states": [
              "success"
            ],
            "content": [
              {
                "http": "GET",
                "path": "/v1/videos/{request_id}/content",
                "query": {
                  "index": "actual output index; default 0"
                }
              },
              {
                "http": "GET",
                "path": "/v1/videos/generations/{request_id}/content",
                "query": {
                  "index": "actual output index; default 0"
                }
              }
            ],
            "content_pending": "Original status JSON until publication.",
            "content_ready": {
              "http_status": 303,
              "location": "actual signed Ailoot-owned asset URL"
            },
            "create": {
              "http": "POST",
              "path": "/v1/videos"
            },
            "failed_states": [],
            "id_source": "Use the actual returned public id or X-Ailoot-Task-Id and polling_url. Keep task_id/provider_task_id separate; status lookup can retain the original task identity when the native fetch omits it.",
            "mode": "submit_once_poll_original",
            "owned_result": {
              "http": "GET",
              "path": "/v1/media/assets/{asset_id}"
            },
            "pending_states": [
              "created"
            ],
            "signed_asset_lifetime_seconds": 86400,
            "state_field": "state",
            "status": [
              {
                "http": "GET",
                "path": "/v1/videos/{request_id}"
              },
              {
                "http": "GET",
                "path": "/v1/videos/generations/{request_id}"
              }
            ],
            "submit_status": 200,
            "unknown": "The pinned declaration enumerates no terminal failure state. Preserve original response/headers/id and check that same operation for any unrecognized state or result_pending_check error; never resubmit an unknown creation.",
            "unknown_no_replay": true
          },
          "manufacturer_capability": {
            "documented_material_types": [
              "text"
            ]
          },
          "method": {
            "http": "POST",
            "path": "/v1/videos"
          },
          "method_aliases": [
            "/v1/videos/generations"
          ],
          "operation_modes": [
            "text_to_video"
          ],
          "output": {
            "additional_media_boundary": "Only creations[].url is selected for owned video delivery. No owned cover-image or callback result flow is established.",
            "all_results": "Download every actual returned URL in creations[].url; a content index identifies one real returned output.",
            "every_actual_output": true,
            "family": "video",
            "fields": [
              {
                "description": "Returned public Ailoot task or operation identifier.",
                "name": "id",
                "type": "string"
              },
              {
                "description": "Original task identifier, separate from the public id.",
                "name": "provider_task_id",
                "type": "string"
              },
              {
                "description": "Returned Ailoot lookup path for the original task.",
                "name": "polling_url",
                "type": "string"
              },
              {
                "description": "Original identifier present in the creation response.",
                "name": "task_id",
                "type": "string when supplied"
              },
              {
                "description": "Native task state: created for the pinned pending state and success for completion.",
                "name": "state",
                "type": "string when supplied"
              },
              {
                "description": "Task diagnostic; the saved specification declares no enumerated error-code list.",
                "name": "err_code",
                "type": "string when supplied"
              },
              {
                "description": "Every selected completed video URL is replaced with an Ailoot-owned signed URL.",
                "name": "creations[].url",
                "type": "string|string[]"
              },
              {
                "description": "Returned video duration; inspect the actual completed result.",
                "name": "creations[].video.duration",
                "type": "number when supplied"
              },
              {
                "description": "Returned frame rate; no fixed frame rate is promised.",
                "name": "creations[].video.fps",
                "type": "integer when supplied"
              },
              {
                "description": "Returned output width in pixels.",
                "name": "creations[].video.resolution.width",
                "type": "integer when supplied"
              },
              {
                "description": "Returned output height in pixels.",
                "name": "creations[].video.resolution.height",
                "type": "integer when supplied"
              }
            ],
            "format": null,
            "maximum_outputs": null,
            "ownership": "Selected video outputs are copied, reopened and SHA256/length/positive-duration checked before publication.",
            "result": "JSON retains the native state and creations array, with public id/provider_task_id/polling_url added. Selected video URLs are blank before publication and become Ailoot-owned signed URLs after completion."
          }
        },
        "ctx": null,
        "declared_pricing_profiles": [
          {
            "dimensions": {
              "regime": "base"
            },
            "label": "Base token rates",
            "units": [
              {
                "amount": null,
                "amount_unit": "usd_per_thousand_tokens",
                "billing_input": false,
                "estimate_only": true,
                "key": "input_price",
                "label": "Input tokens",
                "native_amount_usd_per_unit": null,
                "native_quantity": 1,
                "native_unit": "input_token",
                "public_unit_label": "/ 1K tokens",
                "quantity": 1000,
                "quantity_is_estimate": true,
                "rate_role": "typed_native_retail_rate",
                "side": "in",
                "unit": "input_token"
              },
              {
                "amount": null,
                "amount_unit": "usd_per_thousand_tokens",
                "billing_input": false,
                "estimate_only": true,
                "key": "output_price",
                "label": "Output tokens",
                "native_amount_usd_per_unit": null,
                "native_quantity": 1,
                "native_unit": "output_token",
                "public_unit_label": "/ 1K tokens",
                "quantity": 1000,
                "quantity_is_estimate": true,
                "rate_role": "typed_native_retail_rate",
                "side": "out",
                "unit": "output_token"
              },
              {
                "amount": null,
                "amount_unit": "usd_per_thousand_tokens",
                "billing_input": false,
                "estimate_only": true,
                "key": "cache_read_price",
                "label": "Cache read",
                "native_amount_usd_per_unit": null,
                "native_quantity": 1,
                "native_unit": "cached_input_token",
                "public_unit_label": "/ 1K tokens",
                "quantity": 1000,
                "quantity_is_estimate": true,
                "rate_role": "typed_native_retail_rate",
                "side": "in",
                "unit": "cached_input_token"
              },
              {
                "amount": null,
                "amount_unit": "usd_per_thousand_tokens",
                "billing_input": false,
                "estimate_only": true,
                "key": "cache_write_price",
                "label": "Cache write",
                "native_amount_usd_per_unit": null,
                "native_quantity": 1,
                "native_unit": "generic_cache_creation_token",
                "public_unit_label": "/ 1K tokens",
                "quantity": 1000,
                "quantity_is_estimate": true,
                "rate_role": "typed_native_retail_rate",
                "side": "in",
                "unit": "generic_cache_creation_token"
              },
              {
                "amount": null,
                "amount_unit": "usd_per_thousand_tokens",
                "billing_input": false,
                "estimate_only": true,
                "key": "cache_write_1h_price",
                "label": "Cache write, 1 hour",
                "native_amount_usd_per_unit": null,
                "native_quantity": 1,
                "native_unit": "one_hour_cache_creation_token",
                "public_unit_label": "/ 1K tokens",
                "quantity": 1000,
                "quantity_is_estimate": true,
                "rate_role": "typed_native_retail_rate",
                "side": "in",
                "unit": "one_hour_cache_creation_token"
              }
            ]
          },
          {
            "basis": "Cette estimation ne constitue ni des frais supplémentaires ni un tarif fixe pour la génération terminée.",
            "dimensions": {
              "forecast_quantity": "one generation estimate"
            },
            "label": "Coût estimé de la génération",
            "units": [
              {
                "amount": "5.12",
                "amount_unit": "usd_per_exact_native_unit",
                "billing_input": false,
                "estimate_only": true,
                "key": "forecast_usd",
                "label": "Estimated generation cost",
                "native_amount_usd_per_unit": "5.12",
                "native_quantity": 1,
                "public_unit_label": "estimate before generation",
                "quantity": 1,
                "quantity_is_estimate": true,
                "rate_role": "typed_native_retail_rate",
                "side": "out",
                "unit": "request_estimate"
              }
            ]
          }
        ],
        "examples": [
          {
            "code": "set -eu\n: \"${AILOOT_API_KEY:?Set your Ailoot API key}\"\ncat > request.json <<'JSON_REQUEST'\n{\"model\":\"viduq2\",\"prompt\":\"In an ultra-realistic fashion photography style featuring light blue and pale amber tones, an astronaut in a spacesuit walks through the fog. The background consists of enchanting white and golden lights, creating a minimalist still life and an impressive panoramic scene.\"}\nJSON_REQUEST\ncurl --fail-with-body --silent --show-error https://api.ailoot.ai/v1/videos \\\n  -H \"Authorization: Bearer $AILOOT_API_KEY\" -H 'Content-Type: application/json' \\\n  --data-binary @request.json -D response-headers.txt -o result.json\n",
            "label": "curl · create video",
            "language": "bash"
          },
          {
            "code": "set -eu\n: \"${AILOOT_API_KEY:?Set your Ailoot API key}\"\npython3 - <<'PY_POLL'\nimport json\nfrom pathlib import Path\nfrom urllib.parse import quote,urljoin,urlsplit\nr=json.loads(Path(\"result.json\").read_text())\ni=r.get(\"id\")\nif not isinstance(i,str) or not i:raise SystemExit(\"Keep original response/headers/id; do not resubmit creation.\")\nu=urljoin(\"https://api.ailoot.ai\",r.get(\"polling_url\") or \"/v1/videos/\"+quote(i,safe=\"\"))\np=urlsplit(u)\nif p.scheme!=\"https\" or p.netloc!=\"api.ailoot.ai\" or not p.path.startswith(\"/v1/videos/\"):raise SystemExit(\"Use the actual Ailoot lookup path.\")\nPath(\"poll-url.txt\").write_text(u)\nPY_POLL\ncurl --fail-with-body --silent --show-error \"$(cat poll-url.txt)\" -H \"Authorization: Bearer $AILOOT_API_KEY\" -D status-headers.txt -o status.json\n",
            "label": "curl · read original task",
            "language": "bash"
          },
          {
            "code": "set -eu\npython3 - <<'PY_ASSETS'\nimport json\nfrom pathlib import Path\nfrom urllib.parse import urlsplit\nr=json.loads(Path(\"status.json\").read_text())\nif r.get(\"state\")!=\"success\":raise SystemExit(\"Poll the same original job until its owned result is returned.\")\ncreations=r.get(\"creations\")\nif not isinstance(creations,list) or not creations:raise SystemExit(\"No completed video creations.\")\nurls=[]\nfor item in creations:\n    value=item.get(\"url\") if isinstance(item,dict) else None\n    values=[value] if isinstance(value,str) else value\n    if not isinstance(values,list) or not values:raise SystemExit(\"No completed video URL.\")\n    for u in values:\n        if not isinstance(u,str):raise SystemExit(\"Invalid returned URL.\")\n        p=urlsplit(u)\n        if p.scheme!=\"https\" or p.netloc!=\"api.ailoot.ai\" or not p.path.startswith(\"/v1/media/assets/\") or not p.path.endswith(\"/content\") or not p.query:raise SystemExit(\"Wait for the actual Ailoot-owned signed result.\")\n        urls.append(u)\nPath(\"asset-urls.txt\").write_text(\"\\n\".join(urls)+\"\\n\")\nPY_ASSETS\nindex=0\nwhile IFS= read -r asset_url; do\n  curl --fail-with-body --silent --show-error \"$asset_url\" -o \"video-${index}.bin\"\n  index=$((index + 1))\ndone < asset-urls.txt\n",
            "label": "curl · download every owned video",
            "language": "bash"
          }
        ],
        "family": "openai",
        "fast_multiplier": null,
        "flex_multiplier": null,
        "fmt": "videos",
        "hints": [
          "Create once and retain the returned public id and polling_url.",
          "Poll the original operation and read state; success and an owned creations[].url result are the completion boundary.",
          "Download every returned owned video URL; do not infer a fixed output count, duration or frame rate from the example."
        ],
        "http": "POST",
        "in": null,
        "input": [
          "text"
        ],
        "label": "Vidéo",
        "max_out": null,
        "max_reasoning_effort_multiplier": null,
        "method_aliases": [
          "/v1/videos/generations"
        ],
        "out": null,
        "output": [
          "video"
        ],
        "path": "/v1/videos",
        "price_conditions": [
          {
            "label": "Fast mode",
            "value": "Not specified",
            "when": "When fast mode is selected"
          },
          {
            "label": "Flex mode",
            "value": "Not specified",
            "when": "When flex mode is selected"
          },
          {
            "label": "Maximum reasoning effort",
            "value": "Not specified",
            "when": "When maximum reasoning effort uses the default adjustment"
          }
        ],
        "pricing": {
          "billing_mode": "original_invoice_usd",
          "image_input_price": null,
          "image_output_price": null
        },
        "pricing_profiles": [
          {
            "dimensions": {
              "regime": "base"
            },
            "label": "Base token rates",
            "units": [
              {
                "amount": null,
                "amount_unit": "usd_per_thousand_tokens",
                "billing_input": false,
                "estimate_only": true,
                "key": "input_price",
                "label": "Input tokens",
                "native_amount_usd_per_unit": null,
                "native_quantity": 1,
                "native_unit": "input_token",
                "public_unit_label": "/ 1K tokens",
                "quantity": 1000,
                "quantity_is_estimate": true,
                "rate_role": "typed_native_retail_rate",
                "side": "in",
                "unit": "input_token"
              },
              {
                "amount": null,
                "amount_unit": "usd_per_thousand_tokens",
                "billing_input": false,
                "estimate_only": true,
                "key": "output_price",
                "label": "Output tokens",
                "native_amount_usd_per_unit": null,
                "native_quantity": 1,
                "native_unit": "output_token",
                "public_unit_label": "/ 1K tokens",
                "quantity": 1000,
                "quantity_is_estimate": true,
                "rate_role": "typed_native_retail_rate",
                "side": "out",
                "unit": "output_token"
              },
              {
                "amount": null,
                "amount_unit": "usd_per_thousand_tokens",
                "billing_input": false,
                "estimate_only": true,
                "key": "cache_read_price",
                "label": "Cache read",
                "native_amount_usd_per_unit": null,
                "native_quantity": 1,
                "native_unit": "cached_input_token",
                "public_unit_label": "/ 1K tokens",
                "quantity": 1000,
                "quantity_is_estimate": true,
                "rate_role": "typed_native_retail_rate",
                "side": "in",
                "unit": "cached_input_token"
              },
              {
                "amount": null,
                "amount_unit": "usd_per_thousand_tokens",
                "billing_input": false,
                "estimate_only": true,
                "key": "cache_write_price",
                "label": "Cache write",
                "native_amount_usd_per_unit": null,
                "native_quantity": 1,
                "native_unit": "generic_cache_creation_token",
                "public_unit_label": "/ 1K tokens",
                "quantity": 1000,
                "quantity_is_estimate": true,
                "rate_role": "typed_native_retail_rate",
                "side": "in",
                "unit": "generic_cache_creation_token"
              },
              {
                "amount": null,
                "amount_unit": "usd_per_thousand_tokens",
                "billing_input": false,
                "estimate_only": true,
                "key": "cache_write_1h_price",
                "label": "Cache write, 1 hour",
                "native_amount_usd_per_unit": null,
                "native_quantity": 1,
                "native_unit": "one_hour_cache_creation_token",
                "public_unit_label": "/ 1K tokens",
                "quantity": 1000,
                "quantity_is_estimate": true,
                "rate_role": "typed_native_retail_rate",
                "side": "in",
                "unit": "one_hour_cache_creation_token"
              }
            ]
          },
          {
            "basis": "This estimate is not an additional charge or a fixed rate for the completed generation.",
            "dimensions": {
              "forecast_quantity": "one generation estimate"
            },
            "label": "Estimated generation cost",
            "units": [
              {
                "amount": "5.12",
                "amount_unit": "usd_per_exact_native_unit",
                "billing_input": false,
                "estimate_only": true,
                "key": "forecast_usd",
                "label": "Estimated generation cost",
                "native_amount_usd_per_unit": "5.12",
                "native_quantity": 1,
                "public_unit_label": "estimate before generation",
                "quantity": 1,
                "quantity_is_estimate": true,
                "rate_role": "typed_native_retail_rate",
                "side": "out",
                "unit": "request_estimate"
              }
            ]
          }
        ],
        "request_model_id": "viduq2",
        "route_label": "Ultra",
        "status_reads": [
          "GET /v1/videos/{request_id}",
          "GET /v1/videos/generations/{request_id}",
          "GET /v1/videos/{request_id}/content",
          "GET /v1/videos/generations/{request_id}/content"
        ],
        "tiers": [],
        "units": [
          {
            "amount": null,
            "amount_unit": "usd_per_thousand_tokens",
            "billing_input": false,
            "estimate_only": true,
            "key": "input_price",
            "label": "Input tokens",
            "native_amount_usd_per_unit": null,
            "native_quantity": 1,
            "native_unit": "input_token",
            "public_unit_label": "/ 1K tokens",
            "quantity": 1000,
            "quantity_is_estimate": true,
            "rate_role": "typed_native_retail_rate",
            "side": "in",
            "unit": "input_token"
          },
          {
            "amount": null,
            "amount_unit": "usd_per_thousand_tokens",
            "billing_input": false,
            "estimate_only": true,
            "key": "output_price",
            "label": "Output tokens",
            "native_amount_usd_per_unit": null,
            "native_quantity": 1,
            "native_unit": "output_token",
            "public_unit_label": "/ 1K tokens",
            "quantity": 1000,
            "quantity_is_estimate": true,
            "rate_role": "typed_native_retail_rate",
            "side": "out",
            "unit": "output_token"
          },
          {
            "amount": null,
            "amount_unit": "usd_per_thousand_tokens",
            "billing_input": false,
            "estimate_only": true,
            "key": "cache_read_price",
            "label": "Cache read",
            "native_amount_usd_per_unit": null,
            "native_quantity": 1,
            "native_unit": "cached_input_token",
            "public_unit_label": "/ 1K tokens",
            "quantity": 1000,
            "quantity_is_estimate": true,
            "rate_role": "typed_native_retail_rate",
            "side": "in",
            "unit": "cached_input_token"
          },
          {
            "amount": null,
            "amount_unit": "usd_per_thousand_tokens",
            "billing_input": false,
            "estimate_only": true,
            "key": "cache_write_price",
            "label": "Cache write",
            "native_amount_usd_per_unit": null,
            "native_quantity": 1,
            "native_unit": "generic_cache_creation_token",
            "public_unit_label": "/ 1K tokens",
            "quantity": 1000,
            "quantity_is_estimate": true,
            "rate_role": "typed_native_retail_rate",
            "side": "in",
            "unit": "generic_cache_creation_token"
          },
          {
            "amount": null,
            "amount_unit": "usd_per_thousand_tokens",
            "billing_input": false,
            "estimate_only": true,
            "key": "cache_write_1h_price",
            "label": "Cache write, 1 hour",
            "native_amount_usd_per_unit": null,
            "native_quantity": 1,
            "native_unit": "one_hour_cache_creation_token",
            "public_unit_label": "/ 1K tokens",
            "quantity": 1000,
            "quantity_is_estimate": true,
            "rate_role": "typed_native_retail_rate",
            "side": "in",
            "unit": "one_hour_cache_creation_token"
          },
          {
            "amount": "5.12",
            "amount_unit": "usd_per_exact_native_unit",
            "billing_input": false,
            "estimate_only": true,
            "key": "forecast_usd",
            "label": "Estimated generation cost",
            "native_amount_usd_per_unit": "5.12",
            "native_quantity": 1,
            "public_unit_label": "estimate before generation",
            "quantity": 1,
            "quantity_is_estimate": true,
            "rate_role": "typed_native_retail_rate",
            "side": "out",
            "unit": "request_estimate"
          }
        ]
      }
    }
  ],
  "model_id": "viduq2",
  "nativeProvenance": {
    "input_facts_canonical_sha256": "26fc6000ae665fb4ed90543917ccfc4a2fb0067c1d44622ec85839bd8d06328f",
    "input_html_sha256": "665df6c72c529709d6fd01c83027597e1eb2e25b20b4b4766c16b867a325f125",
    "private_audit_sha256": "c39a2c1aa07a76560761e81284af37bf97a52bab1b9b6cb0b191742873dec27a",
    "role": "historical-normalized-input-audit-hashes",
    "schema": "ailoot-native-model-provenance-v2"
  },
  "page": {
    "canonical": "https://ailoot.ai/models/fr-be/viduq2/",
    "description": "Vidu Q2 crée une vidéo à partir d’un brief de scène textuel, avec une durée de 1 à 10 secondes, une sortie 540p, 720p ou 1080p et cinq rapports d’aspect. Ce profil viduq2 précis utilise le prompt pour le style et le mouvement et renvoie son résultat par une tâche asynchrone.",
    "locale": "fr-be",
    "md_url": "https://ailoot.ai/models/fr-be/viduq2/index.md",
    "title": "Vidu: Q2 Text-to-Video — Ailoot",
    "url": "https://ailoot.ai/models/fr-be/viduq2/"
  },
  "rawModel": {
    "about": "Vidu Q2 crée une vidéo à partir d’une scène écrite au moyen du profil texte-vers-vidéo sélectionné par viduq2. Ses entrées obligatoires sont l’identifiant exact du modèle et un prompt décrivant la scène. Utilisez-le pour un court concept de produit, un plan d’ensemble ou une action de personnage dont l’apparence et le mouvement peuvent être précisés par des mots. Cette méthode configurée est texte-vers-vidéo ; sa description n’attribue pas au sélecteur un mode distinct de référence image ou de modification vidéo.\n\nConstruisez le brief autour d’une séquence visible. Identifiez le sujet, le lieu, l’action, l’échelle de plan, le mouvement de caméra et la composition finale. Pour un concept de produit, décrivez un objet sur une table, la lumière se déplaçant sur sa matière et une lente approche de caméra qui se termine sur un détail reconnaissable. Pour une scène de lieu, présentez l’environnement avant de vous rapprocher du point d’intérêt. Adaptez l’action à la durée de clip choisie afin que la scène ait le temps d’atteindre la fin voulue.\n\nLa limite du prompt est de 2 000 caractères. Placez d’abord le sujet et l’action essentiels, puis ajoutez les détails d’éclairage, de matière, d’environnement et de caméra qui modifient le résultat voulu. Précisez le style visuel dans le prompt. Le guide propre à Q2 indique que les paramètres distincts style et movement_amplitude sont sans effet pour ce modèle : le préréglage general ou anime et les options d’amplitude de mouvement ne remplacent donc pas une description claire de la scène.\n\nLe réglage de durée propre au modèle accepte des secondes entières de un à dix. Les choix de résolution propres à Q2 sont 540p, 720p et 1080p, avec 720p comme valeur par défaut documentée. Choisissez ensemble la durée et la résolution selon l’action et la destination. Une brève mise en valeur et un mouvement plus long demandent des rythmes différents ; augmenter la durée demandée doit servir la séquence visible plutôt que simplement étirer un brief inchangé. Vérifiez les dimensions et la longueur réelles du clip renvoyé lors de la préparation de son intégration finale.\n\nLes choix documentés du paramètre aspect_ratio sont 16:9, 9:16, 3:4, 4:3 et 1:1, avec 16:9 par défaut. Le guide inclut explicitement 3:4 et 4:3 pour la famille Q2. Choisissez le cadrage avant la génération et décrivez une composition adaptée : gardez un sujet principal lisible dans une vue en portrait, ou utilisez la largeur d’un cadre paysage pour le décor environnant. Gardez la vue finale assez claire pour la page, la présentation ou l’ajout ultérieur de légendes prévu.\n\nLe champ seed contrôle la variation. L’omettre ou fournir 0 sélectionne une valeur aléatoire ; une valeur non nulle sélectionne l’option documentée de graine fixe pour une génération reproductible. Conservez la graine renvoyée avec le prompt et les réglages pour comparer les versions. L’opération commune documente aussi les réglages audio et off_peak spécifiquement pour les modèles Q3. Ces options Q3 ne sont pas des capacités attribuées à ce profil Q2 ; préparez cette requête autour de son entrée textuelle et de sa sortie vidéo documentées.\n\nLa génération est asynchrone. La soumission renvoie task_id et un état initial, avec created pour une tâche nouvellement créée. Conservez cette identité de tâche pendant le suivi du traitement. La consultation de résultat documentée utilise state=success pour un résultat réussi et renvoie un tableau creations. Chaque élément contient l’URL de sa vidéo dans creations[].url ; enregistrez chaque vidéo renvoyée plutôt que de supposer que la tâche contient toujours exactement une création.\n\nLa documentation de résultat rapporte aussi la durée et les fps de la vidéo réelle ainsi que la largeur et la hauteur de sa résolution. Gardez ces valeurs rapportées avec le clip achevé au lieu de considérer la cadence ou les dimensions d’un exemple comme une spécification fixe de Q2. La réponse de création de tâche comprend une valeur credits avec la configuration de requête. Conservez ces métadonnées de tâche rapportées et l’identité de la tâche achevée avec le résultat, afin que chaque vidéo reste liée à ses réglages de génération.\n\nVérifiez toute la séquence par rapport au brief d’origine : l’apparence du sujet, la forme des objets, la direction du mouvement, la continuité de caméra et la vue finale voulue. Pour une révision, identifiez le détail concret qui ne correspond pas au brief et préservez les parties réussies de la scène. Gardez ensemble le prompt, le sélecteur exact, les réglages, l’identité de tâche et les vidéos achevées afin qu’une comparaison ultérieure repose sur les résultats réels.",
    "alias_of": null,
    "aliases": [],
    "author": "Vidu",
    "capabilities": {
      "context_length": 0,
      "manufacturer_input": [
        "text"
      ],
      "manufacturer_output": [
        "video"
      ]
    },
    "card_routes": [
      {
        "label": "Ultra",
        "rates": [
          {
            "amount": "5.12",
            "amount_unit": "usd_per_exact_native_unit",
            "billing_input": false,
            "estimate_only": true,
            "key": "forecast_usd",
            "label": "Estimated generation cost",
            "native_amount_usd_per_unit": "5.12",
            "native_quantity": 1,
            "public_unit_label": "estimate before generation",
            "quantity": 1,
            "quantity_is_estimate": true,
            "rate_role": "typed_native_retail_rate",
            "side": "out",
            "unit": "request_estimate"
          }
        ],
        "summary": "La tarification complète de la configuration figure dans les détails."
      }
    ],
    "ctx": null,
    "display_name": "Vidu: Q2 Text-to-Video",
    "formats": [
      "videos"
    ],
    "id": "viduq2",
    "input": [
      "text"
    ],
    "kind": "video",
    "locale": "en",
    "max_out": null,
    "methods": [
      {
        "available": null,
        "billing_basis": {
          "basis": "original_invoice_usd",
          "description": "Les tarifs affichés servent à estimer le coût avant la génération. Le montant final est calculé à partir du coût enregistré pour la génération d’origine. La durée mesurée du résultat et les quantités prévisionnelles ne constituent pas la quantité finale facturable.",
          "forecast_quantity_is_estimate": true,
          "physical_output_is_billable_quantity": false,
          "version": "original_invoice_usd_v1"
        },
        "cache_read": null,
        "cache_write": null,
        "cache_write_1h": null,
        "contract": {
          "data": {
            "errors": [
              {
                "condition": "JSON/modèle invalide, chaînes obligatoires manquantes ou vides, ou index de contenu invalide.",
                "http_status": 400,
                "type": "invalid_request_error"
              },
              {
                "condition": "Clé API Ailoot invalide.",
                "http_status": 401,
                "type": "authentication_error"
              },
              {
                "condition": "Le groupe de la clé API n’est pas autorisé à utiliser cette route média.",
                "http_status": 403,
                "type": "permission_error"
              },
              {
                "condition": "La tâche d’origine ou le résultat demandé est absent ou n’appartient pas au même utilisateur, à la même clé API et au même groupe.",
                "http_status": 404,
                "type": "not_found_error"
              },
              {
                "condition": "La soumission initiale ou son état est incomplet ou ne peut pas être rapproché des données disponibles ; conservez l’ID d’origine et ne soumettez pas de nouveau la requête.",
                "http_status": 502,
                "type": "result_pending_check"
              },
              {
                "condition": "L’association d’origine, la route ou le média dont vous êtes propriétaire fait encore l’objet de vérifications ; poursuivez la vérification de cette opération d’origine.",
                "http_status": 503,
                "type": "result_pending_check"
              },
              {
                "condition": "Le service de médias ou le stockage des tâches d’origine est indisponible.",
                "http_status": 503,
                "type": "server_error"
              }
            ],
            "ignored_fields": [
              "style",
              "movement_amplitude"
            ],
            "lifecycle": {
              "cancel_endpoint": null,
              "completed_states": [
                "success"
              ],
              "content": [
                {
                  "http": "GET",
                  "path": "/v1/videos/{request_id}/content",
                  "query": {
                    "index": "actual output index; default 0"
                  }
                },
                {
                  "http": "GET",
                  "path": "/v1/videos/generations/{request_id}/content",
                  "query": {
                    "index": "actual output index; default 0"
                  }
                }
              ],
              "content_pending": "Original status JSON until publication.",
              "content_ready": {
                "http_status": 303,
                "location": "actual signed Ailoot-owned asset URL"
              },
              "create": {
                "http": "POST",
                "path": "/v1/videos"
              },
              "failed_states": [],
              "id_source": "Use the actual returned public id or X-Ailoot-Task-Id and polling_url. Keep task_id/provider_task_id separate; status lookup can retain the original task identity when the native fetch omits it.",
              "mode": "submit_once_poll_original",
              "owned_result": {
                "http": "GET",
                "path": "/v1/media/assets/{asset_id}"
              },
              "pending_states": [
                "created"
              ],
              "signed_asset_lifetime_seconds": 86400,
              "state_field": "state",
              "status": [
                {
                  "http": "GET",
                  "path": "/v1/videos/{request_id}"
                },
                {
                  "http": "GET",
                  "path": "/v1/videos/generations/{request_id}"
                }
              ],
              "submit_status": 200,
              "unknown": "La déclaration figée n’énumère aucun état d’échec terminal. Conservez la réponse, les en-têtes et l’id d’origine, puis vérifiez cette même opération en cas d’état non reconnu ou d’erreur result_pending_check ; ne soumettez jamais de nouveau une création dont l’issue est inconnue.",
              "unknown_no_replay": true
            },
            "material_combinations": [
              [
                "text"
              ]
            ],
            "operation_modes": [
              "text_to_video"
            ],
            "outputs": {
              "additional_media_boundary": "Only creations[].url is selected for owned video delivery. No owned cover-image or callback result flow is established.",
              "all_results": "Téléchargez chaque URL réelle renvoyée dans creations[].url ; un index de contenu identifie un résultat réellement renvoyé.",
              "every_actual_output": true,
              "family": "video",
              "fields": [
                {
                  "description": "Identifiant public de tâche ou d’opération Ailoot renvoyé.",
                  "name": "id",
                  "type": "string"
                },
                {
                  "description": "Identifiant de la tâche d’origine, distinct de l’id public.",
                  "name": "provider_task_id",
                  "type": "string"
                },
                {
                  "description": "Chemin de consultation Ailoot renvoyé pour la tâche d’origine.",
                  "name": "polling_url",
                  "type": "string"
                },
                {
                  "description": "Identifiant d’origine présent dans la réponse de création.",
                  "name": "task_id",
                  "type": "string when supplied"
                },
                {
                  "description": "État natif de la tâche : created pour l’état d’attente figé et success pour l’achèvement.",
                  "name": "state",
                  "type": "string when supplied"
                },
                {
                  "description": "Diagnostic de la tâche ; la spécification enregistrée ne déclare aucune liste énumérée de codes d’erreur.",
                  "name": "err_code",
                  "type": "string when supplied"
                },
                {
                  "description": "Chaque URL de vidéo terminée sélectionnée est remplacée par une URL signée appartenant à Ailoot.",
                  "name": "creations[].url",
                  "type": "string|string[]"
                },
                {
                  "description": "Durée vidéo renvoyée ; vérifiez le résultat réellement terminé.",
                  "name": "creations[].video.duration",
                  "type": "number when supplied"
                },
                {
                  "description": "Fréquence d’images renvoyée ; aucune fréquence fixe n’est promise.",
                  "name": "creations[].video.fps",
                  "type": "integer when supplied"
                },
                {
                  "description": "Largeur de sortie renvoyée en pixels.",
                  "name": "creations[].video.resolution.width",
                  "type": "integer when supplied"
                },
                {
                  "description": "Hauteur de sortie renvoyée en pixels.",
                  "name": "creations[].video.resolution.height",
                  "type": "integer when supplied"
                }
              ],
              "format": null,
              "maximum_outputs": null,
              "ownership": "Selected video outputs are copied, reopened and SHA256/length/positive-duration checked before publication.",
              "result": "Le JSON conserve l’état natif et le tableau creations, auxquels s’ajoutent les valeurs publiques id/provider_task_id/polling_url. Les URL vidéo sélectionnées sont vides avant publication et deviennent des URL signées appartenant à Ailoot après achèvement."
            },
            "parameters": [
              {
                "availability": "source_interface",
                "default": null,
                "default_known": false,
                "enum": [
                  "viduq2"
                ],
                "enum_known": true,
                "name": "model",
                "required": true,
                "type": "string"
              },
              {
                "availability": "source_interface",
                "conditions": "Décrivez la scène à générer. La limite documentée est de 2000 caractères ; Ailoot vérifie que la chaîne n’est pas vide et conserve le texte.",
                "default": null,
                "default_known": false,
                "enum": null,
                "enum_known": false,
                "maxLength": 2000,
                "minLength": 1,
                "name": "prompt",
                "required": true,
                "type": "string"
              },
              {
                "availability": "source_interface",
                "conditions": "La description propre au modèle viduq2 précise une durée de 1–10 secondes entières. Aucune durée par défaut propre au modèle n’est documentée.",
                "default": null,
                "default_known": false,
                "enum": null,
                "enum_known": false,
                "maximum": 10,
                "minimum": 1,
                "name": "duration",
                "required": false,
                "type": "integer",
                "unit": "secondes"
              },
              {
                "availability": "source_interface",
                "conditions": "Omettez le champ ou envoyez la chaîne \"0\" pour un résultat aléatoire. Une valeur seed fournie non nulle sélectionne le comportement documenté avec seed fixe ; aucune plage numérique n’est précisée.",
                "default": null,
                "default_known": false,
                "enum": null,
                "enum_known": false,
                "name": "seed",
                "required": false,
                "type": "string"
              },
              {
                "availability": "source_interface",
                "default": "16:9",
                "default_known": true,
                "enum": [
                  "16:9",
                  "9:16",
                  "3:4",
                  "4:3",
                  "1:1"
                ],
                "enum_known": true,
                "name": "aspect_ratio",
                "required": false,
                "type": "string"
              },
              {
                "availability": "source_interface",
                "conditions": "La liste propre au modèle viduq2 documente ces paliers pour 1–10 secondes. Une énumération et un tableau communs mentionnent également 360p ; son applicabilité contredit cette liste et n’est pas affirmée ici.",
                "default": "720p",
                "default_known": true,
                "enum": [
                  "540p",
                  "720p",
                  "1080p"
                ],
                "enum_known": true,
                "name": "resolution",
                "required": false,
                "type": "string"
              },
              {
                "availability": "source_interface",
                "conditions": "La requête commune accepte ce champ, mais la documentation indique explicitement qu’il n’a aucun effet pour viduq2.",
                "default": "general",
                "default_known": true,
                "enum": [
                  "general",
                  "anime"
                ],
                "enum_known": true,
                "name": "style",
                "required": false,
                "type": "string"
              },
              {
                "availability": "source_interface",
                "conditions": "La requête commune accepte ce champ, mais la documentation indique explicitement qu’il n’a aucun effet pour les modèles q2.",
                "default": "auto",
                "default_known": true,
                "enum": [
                  "auto",
                  "small",
                  "medium",
                  "large"
                ],
                "enum_known": true,
                "name": "movement_amplitude",
                "required": false,
                "type": "string"
              }
            ],
            "profile_binding": "Literal viduq2 model with the documented Ailoot videos interface.",
            "request_schema": {
              "additionalProperties": true,
              "properties": {
                "aspect_ratio": {
                  "default": "16:9",
                  "enum": [
                    "16:9",
                    "9:16",
                    "3:4",
                    "4:3",
                    "1:1"
                  ],
                  "type": "string"
                },
                "duration": {
                  "maximum": 10,
                  "minimum": 1,
                  "type": "integer"
                },
                "model": {
                  "const": "viduq2",
                  "minLength": 1,
                  "type": "string"
                },
                "movement_amplitude": {
                  "default": "auto",
                  "enum": [
                    "auto",
                    "small",
                    "medium",
                    "large"
                  ],
                  "type": "string"
                },
                "prompt": {
                  "maxLength": 2000,
                  "minLength": 1,
                  "type": "string"
                },
                "resolution": {
                  "default": "720p",
                  "enum": [
                    "540p",
                    "720p",
                    "1080p"
                  ],
                  "type": "string"
                },
                "seed": {
                  "type": "string"
                },
                "style": {
                  "default": "general",
                  "enum": [
                    "general",
                    "anime"
                  ],
                  "type": "string"
                }
              },
              "required": [
                "model",
                "prompt"
              ],
              "type": "object"
            },
            "source_ambiguities": [
              "The shared enum and table mention 360p, while the model-specific viduq2 resolution description lists 540p/720p/1080p. The method asserts only the explicit model-specific list.",
              "The shared duration example uses a quoted string despite an integer schema. The copyable viduq2 example omits that optional field; an explicit duration follows the documented integer type.",
              "No model-specific default duration, maximum output count, generated-file retention period, cancellation endpoint or terminal failure-state list is established by these saved documents.",
              "The documented fetch uses an id path parameter; the pinned declaration names that same substituted value task_id. The fetch example has no task_id field, which the current client accepts only by retaining the original task identity."
            ],
            "unsupported": [
              "Image-guided input, video editing and extension are not part of this text-to-video method.",
              "The audio and off_peak parameters are documented only for other model selectors, not viduq2.",
              "No live streaming, callback completion or owned cover-image result contract is established here."
            ]
          },
          "hints": [
            "Créez une seule fois et conservez l’id public et polling_url renvoyés.",
            "Interrogez périodiquement l’opération d’origine et consultez state ; success et un résultat creations[].url dont vous êtes propriétaire constituent la condition d’achèvement.",
            "Téléchargez chaque URL de vidéo renvoyée dont vous êtes propriétaire ; l’exemple ne permet pas de déduire un nombre fixe de résultats, une durée ou une fréquence d’images."
          ],
          "input": {
            "additional_properties": true,
            "content_type": "application/json",
            "material_types": [
              "text"
            ],
            "optional": [
              "duration",
              "seed",
              "aspect_ratio",
              "resolution",
              "style",
              "movement_amplitude"
            ],
            "required": [
              "model",
              "prompt"
            ],
            "validation_scope": "Ailoot valide les chaînes model/prompt non vides. Les types facultatifs et les limites ci-dessous constituent le contrat documenté de la requête ; les autres champs de la requête sont conservés pour le modèle sélectionné."
          },
          "lifecycle": {
            "cancel_endpoint": null,
            "completed_states": [
              "success"
            ],
            "content": [
              {
                "http": "GET",
                "path": "/v1/videos/{request_id}/content",
                "query": {
                  "index": "actual output index; default 0"
                }
              },
              {
                "http": "GET",
                "path": "/v1/videos/generations/{request_id}/content",
                "query": {
                  "index": "actual output index; default 0"
                }
              }
            ],
            "content_pending": "Original status JSON until publication.",
            "content_ready": {
              "http_status": 303,
              "location": "actual signed Ailoot-owned asset URL"
            },
            "create": {
              "http": "POST",
              "path": "/v1/videos"
            },
            "failed_states": [],
            "id_source": "Use the actual returned public id or X-Ailoot-Task-Id and polling_url. Keep task_id/provider_task_id separate; status lookup can retain the original task identity when the native fetch omits it.",
            "mode": "submit_once_poll_original",
            "owned_result": {
              "http": "GET",
              "path": "/v1/media/assets/{asset_id}"
            },
            "pending_states": [
              "created"
            ],
            "signed_asset_lifetime_seconds": 86400,
            "state_field": "state",
            "status": [
              {
                "http": "GET",
                "path": "/v1/videos/{request_id}"
              },
              {
                "http": "GET",
                "path": "/v1/videos/generations/{request_id}"
              }
            ],
            "submit_status": 200,
            "unknown": "The pinned declaration enumerates no terminal failure state. Preserve original response/headers/id and check that same operation for any unrecognized state or result_pending_check error; never resubmit an unknown creation.",
            "unknown_no_replay": true
          },
          "manufacturer_capability": {
            "documented_material_types": [
              "text"
            ]
          },
          "method": {
            "http": "POST",
            "path": "/v1/videos"
          },
          "method_aliases": [
            "/v1/videos/generations"
          ],
          "operation_modes": [
            "text_to_video"
          ],
          "output": {
            "additional_media_boundary": "Only creations[].url is selected for owned video delivery. No owned cover-image or callback result flow is established.",
            "all_results": "Download every actual returned URL in creations[].url; a content index identifies one real returned output.",
            "every_actual_output": true,
            "family": "video",
            "fields": [
              {
                "description": "Returned public Ailoot task or operation identifier.",
                "name": "id",
                "type": "string"
              },
              {
                "description": "Original task identifier, separate from the public id.",
                "name": "provider_task_id",
                "type": "string"
              },
              {
                "description": "Returned Ailoot lookup path for the original task.",
                "name": "polling_url",
                "type": "string"
              },
              {
                "description": "Original identifier present in the creation response.",
                "name": "task_id",
                "type": "string when supplied"
              },
              {
                "description": "Native task state: created for the pinned pending state and success for completion.",
                "name": "state",
                "type": "string when supplied"
              },
              {
                "description": "Task diagnostic; the saved specification declares no enumerated error-code list.",
                "name": "err_code",
                "type": "string when supplied"
              },
              {
                "description": "Every selected completed video URL is replaced with an Ailoot-owned signed URL.",
                "name": "creations[].url",
                "type": "string|string[]"
              },
              {
                "description": "Returned video duration; inspect the actual completed result.",
                "name": "creations[].video.duration",
                "type": "number when supplied"
              },
              {
                "description": "Returned frame rate; no fixed frame rate is promised.",
                "name": "creations[].video.fps",
                "type": "integer when supplied"
              },
              {
                "description": "Returned output width in pixels.",
                "name": "creations[].video.resolution.width",
                "type": "integer when supplied"
              },
              {
                "description": "Returned output height in pixels.",
                "name": "creations[].video.resolution.height",
                "type": "integer when supplied"
              }
            ],
            "format": null,
            "maximum_outputs": null,
            "ownership": "Selected video outputs are copied, reopened and SHA256/length/positive-duration checked before publication.",
            "result": "JSON retains the native state and creations array, with public id/provider_task_id/polling_url added. Selected video URLs are blank before publication and become Ailoot-owned signed URLs after completion."
          }
        },
        "ctx": null,
        "declared_pricing_profiles": [
          {
            "dimensions": {
              "regime": "base"
            },
            "label": "Base token rates",
            "units": [
              {
                "amount": null,
                "amount_unit": "usd_per_thousand_tokens",
                "billing_input": false,
                "estimate_only": true,
                "key": "input_price",
                "label": "Input tokens",
                "native_amount_usd_per_unit": null,
                "native_quantity": 1,
                "native_unit": "input_token",
                "public_unit_label": "/ 1K tokens",
                "quantity": 1000,
                "quantity_is_estimate": true,
                "rate_role": "typed_native_retail_rate",
                "side": "in",
                "unit": "input_token"
              },
              {
                "amount": null,
                "amount_unit": "usd_per_thousand_tokens",
                "billing_input": false,
                "estimate_only": true,
                "key": "output_price",
                "label": "Output tokens",
                "native_amount_usd_per_unit": null,
                "native_quantity": 1,
                "native_unit": "output_token",
                "public_unit_label": "/ 1K tokens",
                "quantity": 1000,
                "quantity_is_estimate": true,
                "rate_role": "typed_native_retail_rate",
                "side": "out",
                "unit": "output_token"
              },
              {
                "amount": null,
                "amount_unit": "usd_per_thousand_tokens",
                "billing_input": false,
                "estimate_only": true,
                "key": "cache_read_price",
                "label": "Cache read",
                "native_amount_usd_per_unit": null,
                "native_quantity": 1,
                "native_unit": "cached_input_token",
                "public_unit_label": "/ 1K tokens",
                "quantity": 1000,
                "quantity_is_estimate": true,
                "rate_role": "typed_native_retail_rate",
                "side": "in",
                "unit": "cached_input_token"
              },
              {
                "amount": null,
                "amount_unit": "usd_per_thousand_tokens",
                "billing_input": false,
                "estimate_only": true,
                "key": "cache_write_price",
                "label": "Cache write",
                "native_amount_usd_per_unit": null,
                "native_quantity": 1,
                "native_unit": "generic_cache_creation_token",
                "public_unit_label": "/ 1K tokens",
                "quantity": 1000,
                "quantity_is_estimate": true,
                "rate_role": "typed_native_retail_rate",
                "side": "in",
                "unit": "generic_cache_creation_token"
              },
              {
                "amount": null,
                "amount_unit": "usd_per_thousand_tokens",
                "billing_input": false,
                "estimate_only": true,
                "key": "cache_write_1h_price",
                "label": "Cache write, 1 hour",
                "native_amount_usd_per_unit": null,
                "native_quantity": 1,
                "native_unit": "one_hour_cache_creation_token",
                "public_unit_label": "/ 1K tokens",
                "quantity": 1000,
                "quantity_is_estimate": true,
                "rate_role": "typed_native_retail_rate",
                "side": "in",
                "unit": "one_hour_cache_creation_token"
              }
            ]
          },
          {
            "basis": "Cette estimation ne constitue ni des frais supplémentaires ni un tarif fixe pour la génération terminée.",
            "dimensions": {
              "forecast_quantity": "one generation estimate"
            },
            "label": "Coût estimé de la génération",
            "units": [
              {
                "amount": "5.12",
                "amount_unit": "usd_per_exact_native_unit",
                "billing_input": false,
                "estimate_only": true,
                "key": "forecast_usd",
                "label": "Estimated generation cost",
                "native_amount_usd_per_unit": "5.12",
                "native_quantity": 1,
                "public_unit_label": "estimate before generation",
                "quantity": 1,
                "quantity_is_estimate": true,
                "rate_role": "typed_native_retail_rate",
                "side": "out",
                "unit": "request_estimate"
              }
            ]
          }
        ],
        "examples": [
          {
            "code": "set -eu\n: \"${AILOOT_API_KEY:?Set your Ailoot API key}\"\ncat > request.json <<'JSON_REQUEST'\n{\"model\":\"viduq2\",\"prompt\":\"In an ultra-realistic fashion photography style featuring light blue and pale amber tones, an astronaut in a spacesuit walks through the fog. The background consists of enchanting white and golden lights, creating a minimalist still life and an impressive panoramic scene.\"}\nJSON_REQUEST\ncurl --fail-with-body --silent --show-error https://api.ailoot.ai/v1/videos \\\n  -H \"Authorization: Bearer $AILOOT_API_KEY\" -H 'Content-Type: application/json' \\\n  --data-binary @request.json -D response-headers.txt -o result.json\n",
            "label": "curl · create video",
            "language": "bash"
          },
          {
            "code": "set -eu\n: \"${AILOOT_API_KEY:?Set your Ailoot API key}\"\npython3 - <<'PY_POLL'\nimport json\nfrom pathlib import Path\nfrom urllib.parse import quote,urljoin,urlsplit\nr=json.loads(Path(\"result.json\").read_text())\ni=r.get(\"id\")\nif not isinstance(i,str) or not i:raise SystemExit(\"Keep original response/headers/id; do not resubmit creation.\")\nu=urljoin(\"https://api.ailoot.ai\",r.get(\"polling_url\") or \"/v1/videos/\"+quote(i,safe=\"\"))\np=urlsplit(u)\nif p.scheme!=\"https\" or p.netloc!=\"api.ailoot.ai\" or not p.path.startswith(\"/v1/videos/\"):raise SystemExit(\"Use the actual Ailoot lookup path.\")\nPath(\"poll-url.txt\").write_text(u)\nPY_POLL\ncurl --fail-with-body --silent --show-error \"$(cat poll-url.txt)\" -H \"Authorization: Bearer $AILOOT_API_KEY\" -D status-headers.txt -o status.json\n",
            "label": "curl · read original task",
            "language": "bash"
          },
          {
            "code": "set -eu\npython3 - <<'PY_ASSETS'\nimport json\nfrom pathlib import Path\nfrom urllib.parse import urlsplit\nr=json.loads(Path(\"status.json\").read_text())\nif r.get(\"state\")!=\"success\":raise SystemExit(\"Poll the same original job until its owned result is returned.\")\ncreations=r.get(\"creations\")\nif not isinstance(creations,list) or not creations:raise SystemExit(\"No completed video creations.\")\nurls=[]\nfor item in creations:\n    value=item.get(\"url\") if isinstance(item,dict) else None\n    values=[value] if isinstance(value,str) else value\n    if not isinstance(values,list) or not values:raise SystemExit(\"No completed video URL.\")\n    for u in values:\n        if not isinstance(u,str):raise SystemExit(\"Invalid returned URL.\")\n        p=urlsplit(u)\n        if p.scheme!=\"https\" or p.netloc!=\"api.ailoot.ai\" or not p.path.startswith(\"/v1/media/assets/\") or not p.path.endswith(\"/content\") or not p.query:raise SystemExit(\"Wait for the actual Ailoot-owned signed result.\")\n        urls.append(u)\nPath(\"asset-urls.txt\").write_text(\"\\n\".join(urls)+\"\\n\")\nPY_ASSETS\nindex=0\nwhile IFS= read -r asset_url; do\n  curl --fail-with-body --silent --show-error \"$asset_url\" -o \"video-${index}.bin\"\n  index=$((index + 1))\ndone < asset-urls.txt\n",
            "label": "curl · download every owned video",
            "language": "bash"
          }
        ],
        "family": "openai",
        "fast_multiplier": null,
        "flex_multiplier": null,
        "fmt": "videos",
        "hints": [
          "Create once and retain the returned public id and polling_url.",
          "Poll the original operation and read state; success and an owned creations[].url result are the completion boundary.",
          "Download every returned owned video URL; do not infer a fixed output count, duration or frame rate from the example."
        ],
        "http": "POST",
        "in": null,
        "input": [
          "text"
        ],
        "label": "Vidéo",
        "max_out": null,
        "max_reasoning_effort_multiplier": null,
        "method_aliases": [
          "/v1/videos/generations"
        ],
        "out": null,
        "output": [
          "video"
        ],
        "path": "/v1/videos",
        "price_conditions": [
          {
            "label": "Fast mode",
            "value": "Not specified",
            "when": "When fast mode is selected"
          },
          {
            "label": "Flex mode",
            "value": "Not specified",
            "when": "When flex mode is selected"
          },
          {
            "label": "Maximum reasoning effort",
            "value": "Not specified",
            "when": "When maximum reasoning effort uses the default adjustment"
          }
        ],
        "pricing": {
          "billing_mode": "original_invoice_usd",
          "image_input_price": null,
          "image_output_price": null
        },
        "pricing_profiles": [
          {
            "dimensions": {
              "regime": "base"
            },
            "label": "Base token rates",
            "units": [
              {
                "amount": null,
                "amount_unit": "usd_per_thousand_tokens",
                "billing_input": false,
                "estimate_only": true,
                "key": "input_price",
                "label": "Input tokens",
                "native_amount_usd_per_unit": null,
                "native_quantity": 1,
                "native_unit": "input_token",
                "public_unit_label": "/ 1K tokens",
                "quantity": 1000,
                "quantity_is_estimate": true,
                "rate_role": "typed_native_retail_rate",
                "side": "in",
                "unit": "input_token"
              },
              {
                "amount": null,
                "amount_unit": "usd_per_thousand_tokens",
                "billing_input": false,
                "estimate_only": true,
                "key": "output_price",
                "label": "Output tokens",
                "native_amount_usd_per_unit": null,
                "native_quantity": 1,
                "native_unit": "output_token",
                "public_unit_label": "/ 1K tokens",
                "quantity": 1000,
                "quantity_is_estimate": true,
                "rate_role": "typed_native_retail_rate",
                "side": "out",
                "unit": "output_token"
              },
              {
                "amount": null,
                "amount_unit": "usd_per_thousand_tokens",
                "billing_input": false,
                "estimate_only": true,
                "key": "cache_read_price",
                "label": "Cache read",
                "native_amount_usd_per_unit": null,
                "native_quantity": 1,
                "native_unit": "cached_input_token",
                "public_unit_label": "/ 1K tokens",
                "quantity": 1000,
                "quantity_is_estimate": true,
                "rate_role": "typed_native_retail_rate",
                "side": "in",
                "unit": "cached_input_token"
              },
              {
                "amount": null,
                "amount_unit": "usd_per_thousand_tokens",
                "billing_input": false,
                "estimate_only": true,
                "key": "cache_write_price",
                "label": "Cache write",
                "native_amount_usd_per_unit": null,
                "native_quantity": 1,
                "native_unit": "generic_cache_creation_token",
                "public_unit_label": "/ 1K tokens",
                "quantity": 1000,
                "quantity_is_estimate": true,
                "rate_role": "typed_native_retail_rate",
                "side": "in",
                "unit": "generic_cache_creation_token"
              },
              {
                "amount": null,
                "amount_unit": "usd_per_thousand_tokens",
                "billing_input": false,
                "estimate_only": true,
                "key": "cache_write_1h_price",
                "label": "Cache write, 1 hour",
                "native_amount_usd_per_unit": null,
                "native_quantity": 1,
                "native_unit": "one_hour_cache_creation_token",
                "public_unit_label": "/ 1K tokens",
                "quantity": 1000,
                "quantity_is_estimate": true,
                "rate_role": "typed_native_retail_rate",
                "side": "in",
                "unit": "one_hour_cache_creation_token"
              }
            ]
          },
          {
            "basis": "This estimate is not an additional charge or a fixed rate for the completed generation.",
            "dimensions": {
              "forecast_quantity": "one generation estimate"
            },
            "label": "Estimated generation cost",
            "units": [
              {
                "amount": "5.12",
                "amount_unit": "usd_per_exact_native_unit",
                "billing_input": false,
                "estimate_only": true,
                "key": "forecast_usd",
                "label": "Estimated generation cost",
                "native_amount_usd_per_unit": "5.12",
                "native_quantity": 1,
                "public_unit_label": "estimate before generation",
                "quantity": 1,
                "quantity_is_estimate": true,
                "rate_role": "typed_native_retail_rate",
                "side": "out",
                "unit": "request_estimate"
              }
            ]
          }
        ],
        "request_model_id": "viduq2",
        "route_label": "Ultra",
        "status_reads": [
          "GET /v1/videos/{request_id}",
          "GET /v1/videos/generations/{request_id}",
          "GET /v1/videos/{request_id}/content",
          "GET /v1/videos/generations/{request_id}/content"
        ],
        "tiers": [],
        "units": [
          {
            "amount": null,
            "amount_unit": "usd_per_thousand_tokens",
            "billing_input": false,
            "estimate_only": true,
            "key": "input_price",
            "label": "Input tokens",
            "native_amount_usd_per_unit": null,
            "native_quantity": 1,
            "native_unit": "input_token",
            "public_unit_label": "/ 1K tokens",
            "quantity": 1000,
            "quantity_is_estimate": true,
            "rate_role": "typed_native_retail_rate",
            "side": "in",
            "unit": "input_token"
          },
          {
            "amount": null,
            "amount_unit": "usd_per_thousand_tokens",
            "billing_input": false,
            "estimate_only": true,
            "key": "output_price",
            "label": "Output tokens",
            "native_amount_usd_per_unit": null,
            "native_quantity": 1,
            "native_unit": "output_token",
            "public_unit_label": "/ 1K tokens",
            "quantity": 1000,
            "quantity_is_estimate": true,
            "rate_role": "typed_native_retail_rate",
            "side": "out",
            "unit": "output_token"
          },
          {
            "amount": null,
            "amount_unit": "usd_per_thousand_tokens",
            "billing_input": false,
            "estimate_only": true,
            "key": "cache_read_price",
            "label": "Cache read",
            "native_amount_usd_per_unit": null,
            "native_quantity": 1,
            "native_unit": "cached_input_token",
            "public_unit_label": "/ 1K tokens",
            "quantity": 1000,
            "quantity_is_estimate": true,
            "rate_role": "typed_native_retail_rate",
            "side": "in",
            "unit": "cached_input_token"
          },
          {
            "amount": null,
            "amount_unit": "usd_per_thousand_tokens",
            "billing_input": false,
            "estimate_only": true,
            "key": "cache_write_price",
            "label": "Cache write",
            "native_amount_usd_per_unit": null,
            "native_quantity": 1,
            "native_unit": "generic_cache_creation_token",
            "public_unit_label": "/ 1K tokens",
            "quantity": 1000,
            "quantity_is_estimate": true,
            "rate_role": "typed_native_retail_rate",
            "side": "in",
            "unit": "generic_cache_creation_token"
          },
          {
            "amount": null,
            "amount_unit": "usd_per_thousand_tokens",
            "billing_input": false,
            "estimate_only": true,
            "key": "cache_write_1h_price",
            "label": "Cache write, 1 hour",
            "native_amount_usd_per_unit": null,
            "native_quantity": 1,
            "native_unit": "one_hour_cache_creation_token",
            "public_unit_label": "/ 1K tokens",
            "quantity": 1000,
            "quantity_is_estimate": true,
            "rate_role": "typed_native_retail_rate",
            "side": "in",
            "unit": "one_hour_cache_creation_token"
          },
          {
            "amount": "5.12",
            "amount_unit": "usd_per_exact_native_unit",
            "billing_input": false,
            "estimate_only": true,
            "key": "forecast_usd",
            "label": "Estimated generation cost",
            "native_amount_usd_per_unit": "5.12",
            "native_quantity": 1,
            "public_unit_label": "estimate before generation",
            "quantity": 1,
            "quantity_is_estimate": true,
            "rate_role": "typed_native_retail_rate",
            "side": "out",
            "unit": "request_estimate"
          }
        ]
      }
    ],
    "model_aliases": [
      {
        "canonical_model_id": "viduq2",
        "request_model_id": "viduq2",
        "route_label": "Ultra"
      }
    ],
    "name": "Vidu: Q2 Text-to-Video",
    "price": {
      "estimate_only": true,
      "in": null,
      "in_label": null,
      "out": 5.12,
      "out_label": "estimate before generation",
      "scope_label": "Estimated generation cost",
      "sort_in": null,
      "sort_out": 5.12,
      "varies": false
    },
    "short": "Vidu Q2 crée une vidéo à partir d’un brief de scène textuel, avec une durée de 1 à 10 secondes, une sortie 540p, 720p ou 1080p et cinq rapports d’aspect. Ce profil viduq2 précis utilise le prompt pour le style et le mouvement et renvoie son résultat par une tâche asynchrone."
  },
  "renderer_schema": {
    "method_order": "Original DTO methods order; every exact route/format/path/caller survives.",
    "prices": "Original public DTO fields and original native display HTML; no flattened or normalized offers."
  },
  "representation": "exact-public-dto-and-native-renderer-html",
  "representationNotes": {
    "current_reference": {
      "about_json_pointer": "/aboutHtml",
      "methods": [
        {
          "contract_json_pointer": "/methods/0/rawMethod/contract",
          "html_json_pointer": "/methods/0/html",
          "method_ordinal": 0
        }
      ],
      "role": "current-semantic-reference"
    },
    "raw_input": {
      "examples_role": "historical-input-not-current-ready-examples",
      "json_pointers": [
        "/rawModel",
        "/methods/0/rawMethod"
      ],
      "role": "historical-owner-input"
    },
    "schema": "ailoot-native-model-representations-v1"
  },
  "schema": "ailoot-static-model-facts-v1",
  "schema_version": 1,
  "shortText": "Vidu Q2 crée une vidéo à partir d’un brief de scène textuel, avec une durée de 1 à 10 secondes, une sortie 540p, 720p ou 1080p et cinq rapports d’aspect. Ce profil viduq2 précis utilise le prompt pour le style et le mouvement et renvoie son résultat par une tâche asynchrone.",
  "source": {
    "audit_sha256": "2e00086bcbfc28e64d0cebe97aa47c17d8d5618963027f8ffb9dc6123d7d25b1",
    "bridge_map_sha256": "1125275768b9636fc8461bc7da5061239a81ddfe508e2557843ca42c58ab0036",
    "raw_model_json_sha256": "118071d8ffbba98c675c0b8a4d402fc131e14156047ee5ad6054b97957c54d5f",
    "renderer_sha256": "9d578ff8df69ef70403308c9943a1179a11b94114c10b333bf1c012005d4a7f4"
  },
  "sourceRevision": "923e8140821084c892ba6056651415a0fd3c1ab2d8f68f411f8db3a3bef7534f"
}
