Met de MiniMax H3-API van PoYo genereer je 2K-video's van 5 tot 15 seconden vanuit tekst, een eerste en laatste frame of referentiemedia. Zonder referentiemedia kost een video van 5 seconden naar schatting 105 credits ($0.525).
Deze gids begint met je eerste verzoek en behandelt daarna prijzen, invoermodi, voorbeelden in Python en Node.js en prompts voor verschillende scènes. Alle endpoints en prijzen in deze gids gelden voor PoYo.
Snelstart: dien een taak in en haal de video op
1. Dien een videotaak van 5 seconden in
Haal een API-sleutel op in de PoYo-console, vervang hieronder YOUR_POYO_API_KEY en voer de opdracht uit in een terminal of op je server. Bewaar de sleutel op de server; zet hem niet in browsercode of openbare repositories.
In PoYo-verzoeken is de waarde van model voor MiniMax H3 hailuo-03. Het volgende voorbeeld dient een betaalde generatietaak in.
export POYO_API_KEY="YOUR_POYO_API_KEY"
curl --fail-with-body --max-time 30 \
--request POST 'https://api.poyo.ai/api/generate/submit' \
--header "Authorization: Bearer ${POYO_API_KEY}" \
--header 'Content-Type: application/json' \
--data '{
"model": "hailuo-03",
"input": {
"prompt": "A golden retriever walks through a sunlit autumn park. One slow tracking shot, natural movement, warm afternoon light.",
"duration": 5,
"resolution": "2K",
"aspect_ratio": "16:9"
}
}'
Lees na een geslaagde indiening de taak-ID uit data.task_id. Dit voorbeeld toont de structuur van het antwoord met een tijdelijke taak-ID:
{
"code": 200,
"message": "success",
"data": {
"task_id": "YOUR_TASK_ID"
}
}
2. Vraag het resultaat van de taak op
Zet TASK_ID op de teruggekregen taak-ID en gebruik dezelfde API-sleutel:
TASK_ID="YOUR_TASK_ID"
curl --fail-with-body --max-time 30 \
--request GET "https://api.poyo.ai/api/generate/status/${TASK_ID}" \
--header "Authorization: Bearer ${POYO_API_KEY}"
Een geslaagde indiening betekent dat de taak is geaccepteerd; je moet nog wachten tot de videogeneratie klaar is. Het antwoord op de opvraging kent vier mogelijke waarden voor data.status:
| Status | Betekenis | Volgende stap |
|---|---|---|
not_started | Wacht op verwerking | Vraag later opnieuw op |
running | Generatie bezig | Vraag later opnieuw op |
finished | Generatie voltooid | Lees data.files[].file_url |
failed | Generatie mislukt | Controleer data.error_message en stop met opvragen |
Hier is een voorbeeld van een antwoord voor een voltooide taak. De URL en het tijdstip zijn ter illustratie:
{
"code": 200,
"data": {
"task_id": "YOUR_TASK_ID",
"status": "finished",
"credits_amount": 105,
"files": [
{
"file_url": "https://example.com/generated/video.mp4",
"file_type": "video"
}
],
"created_time": "2026-09-22T08:30:00",
"progress": 100,
"error_message": null
}
}
In de documentatie voor het opvragen van PoYo-taken vind je veldbeschrijvingen en voorbeeldantwoorden voor andere statussen. Mislukt een opvraging tijdelijk, of is je wachttijd verstreken, bewaar dan de taak-ID en vraag later opnieuw op; dien niet automatisch een nieuwe betaalde generatie in.
Hoe de prijzen van MiniMax H3 op PoYo werken
De volgende prijzen zijn gecontroleerd op 21 september 2026. Alle bedragen zijn in USD, met 1 credit = $0.005. Controleer de nieuwste prijzen op de modelpagina voordat je in bulk gaat genereren.
| Factureerbaar onderdeel | Credits | USD |
|---|---|---|
| Duur van de gegenereerde video | 21 credits/seconde | $0.105/seconde |
| Duur van de ingevoerde referentievideo | 21 credits/seconde | $0.105/seconde |
| Eerste 5 referentieafbeeldingen per generatie | 0 | $0 |
| Elke referentieafbeelding vanaf de 6e | 6,4 credits | $0.032 |
Geschatte credits = 21 × (outputseconden + factureerbare seconden referentievideo) + 6,4 × het aantal referentieafbeeldingen boven de 5. Bij 5 of minder referentieafbeeldingen is de extra afbeeldingsheffing 0. Vermenigvuldig de geschatte credits met $0.005 voor de kosten in USD. Bij referentievideo's met een gedeelte van een seconde gebruikt de facturering de duur die de server bepaalt.
| Voorbeeld | Geschatte credits | Geschat in USD |
|---|---|---|
| 5 seconden genereren zonder referentiemedia | 105 | $0.525 |
| 10 seconden genereren zonder referentiemedia | 210 | $1.05 |
| 15 seconden genereren zonder referentiemedia | 315 | $1.575 |
| 10 seconden genereren + 5 seconden referentievideo + 7 referentieafbeeldingen | 327,8 | $1.639 |
Het laatste voorbeeld gebruikt 21 × (10 + 5) + 6.4 × (7 − 5). Dit zijn kosten per generatie; als een shot meerdere pogingen kost, neem je elke generatie mee in je budget.
Kies een invoermodus en referentiemedia
De mediavelden die je indient bepalen de invoermodus. Het voorbeeld in de snelstart hierboven gebruikt tekst naar video. Voeg de juiste velden toe wanneer je begin- en eindframes wilt opgeven of referentiemedia wilt gebruiken.
| Modus | Invoervelden | Gebruik |
|---|---|---|
| Tekst naar video | prompt, zonder media-URL's | Beschrijf de scène, de handeling en de camerabeweging in woorden |
| Generatie met eerste en laatste frame | image_urls | De eerste afbeelding is het beginframe; de tweede, optionele afbeelding is het eindframe. Laat aspect_ratio weg; het eerste frame bepaalt de verhouding |
| Multimodale referentiegeneratie | reference_image_urls, reference_video_urls, reference_audio_urls | Combineer afbeeldingen, video en audio; voor referentie-audio is een referentieafbeelding of -video nodig |
Combineer image_urls niet met een veld reference_*_urls. Alle media-URL's moeten openbaar toegankelijk en rechtstreeks te downloaden zijn.
Limieten voor parameters en media
De volgende limieten komen uit de API-documentatie van PoYo voor MiniMax H3:
promptis verplicht en accepteert maximaal 2000 tekens.durationis een geheel getal van 5 tot 15 seconden, met 5 als standaard;resolutionondersteunt alleen2K.- Tekst naar video ondersteunt
21:9,16:9,4:3,1:1,3:4en9:16, met16:9als standaard. De referentiemodus ondersteunt ookadaptiveen gebruikt dat standaard. - Je kunt maximaal 9 referentieafbeeldingen, 3 referentievideo's en 3 referentie-audioclips opgeven. Elke video of audioclip moet 2 tot 15 seconden duren; de totale videoduur en de totale audioduur mogen elk niet boven 15 seconden uitkomen.
Voorbeeldverzoek met eerste en laatste frame
Gebruik de JSON hieronder als body van POST /api/generate/submit. Media-URL's onder example.com zijn tijdelijke waarden: vervang ze door je eigen downloadbare media voordat je indient. Wil je alleen een beginframe gebruiken, haal dan de tweede URL uit de array.
{
"model": "hailuo-03",
"input": {
"prompt": "The camera slowly moves through the temple doorway, starting at the entrance and ending inside the hall. Dust floats in the sunlight.",
"duration": 6,
"resolution": "2K",
"image_urls": [
"https://example.com/assets/temple-entrance.jpg",
"https://example.com/assets/temple-interior.jpg"
]
}
}
Voorbeeld met gecombineerde afbeeldings- en videoreferentie
Gebruik Image 1 om het uiterlijk van het personage vast te leggen en Video 1 voor de gewenste camerabeweging. Die verwijzen respectievelijk naar het eerste item in de afbeeldingsarray en in de videoarray. Vervang de media-URL's en controleer de duur van de referentievideo voordat je indient.
{
"model": "hailuo-03",
"input": {
"prompt": "Use Image 1 for the character appearance and outfit. The character turns and walks toward the window. Use Video 1 as the camera movement reference.",
"duration": 8,
"resolution": "2K",
"aspect_ratio": "adaptive",
"reference_image_urls": [
"https://example.com/assets/character.png"
],
"reference_video_urls": [
"https://example.com/assets/camera-motion.mp4"
]
}
}
Integratievoorbeelden in Python en Node.js
In de voorbeelden hieronder zijn indienen en opvragen gesplitst in twee functies: haal eerst de taak-ID op en sla die op, en wacht daarna op het resultaat. Wordt het opvragen onderbroken, ga dan verder met de oorspronkelijke taak-ID zonder opnieuw te genereren. Alleen statusopvragingen proberen het opnieuw bij verbindingsfouten, time-outs, HTTP 429 en bepaalde 5xx-fouten; indieningen worden niet automatisch herhaald.
Beide implementaties wachten 10 seconden tussen opvragingen, doen maximaal 60 opvragingen en hanteren een time-out van 30 seconden per verzoek. De totale wachttijd bevat dus ook de duur van de verzoeken. Dit zijn instellingen van de applicatie in de voorbeelden en geen garantie voor de generatietijd. Pas de intervallen en het retrybeleid aan op de behoeften van je applicatie.
Python: dien een taak in en vraag het resultaat op
Installeer de afhankelijkheid met python -m pip install requests en zet de omgevingsvariabele POYO_API_KEY zoals hierboven beschreven. Dit synchrone Python-script pollt een asynchrone generatietaak.
import os
import time
import requests
BASE_URL = "https://api.poyo.ai"
API_KEY = os.environ["POYO_API_KEY"]
if not API_KEY.strip():
raise ValueError("Set POYO_API_KEY")
HEADERS = {"Authorization": f"Bearer {API_KEY}"}
RETRYABLE_HTTP = {429, 500, 502, 503, 504}
def response_data(response):
response.raise_for_status()
body = response.json()
if body.get("code") != 200 or not isinstance(body.get("data"), dict):
raise RuntimeError(f"Unexpected API response: {body}")
return body["data"]
def submit_h3(prompt, duration=5):
response = requests.post(
f"{BASE_URL}/api/generate/submit",
headers=HEADERS,
json={"model": "hailuo-03", "input": {
"prompt": prompt, "duration": duration,
"resolution": "2K", "aspect_ratio": "16:9",
}},
timeout=30,
)
task_id = response_data(response).get("task_id")
if not isinstance(task_id, str) or not task_id:
raise RuntimeError("Submission response is missing a task ID; check records instead of resubmitting automatically")
return task_id
def wait_for_h3(task_id, max_polls=60):
for _ in range(max_polls):
time.sleep(10)
try:
response = requests.get(
f"{BASE_URL}/api/generate/status/{task_id}",
headers=HEADERS, timeout=30,
)
except (requests.Timeout, requests.ConnectionError):
continue
if response.status_code in RETRYABLE_HTTP:
continue
task = response_data(response)
status = task.get("status")
if status == "finished":
for item in task.get("files") or []:
if item.get("file_type") == "video" and item.get("file_url"):
return item["file_url"]
raise RuntimeError(f"Task {task_id} finished, but the response has no video URL")
if status == "failed":
raise RuntimeError(f"Task {task_id} failed: {task.get('error_message')}")
if status not in {"not_started", "running"}:
raise RuntimeError(f"Task {task_id} returned an unknown status: {status}")
raise TimeoutError(f"Query limit reached; keep the task ID and query again later: {task_id}")
if __name__ == "__main__":
task_id = submit_h3("A golden retriever walks through a sunlit autumn park.")
# In your application, save task_id to the database here before polling.
print(f"Task ID: {task_id}", flush=True)
print(wait_for_h3(task_id))
Om het opvragen te hervatten, roep je wait_for_h3(saved_task_id) rechtstreeks aan. HTTP-fouten zoals 401 en 403, fouten op API-niveau of onverwachte antwoorden stoppen het pollen; los de oorzaak op voordat je verdergaat.
Node.js: gebruik de ingebouwde fetch
De volgende JavaScript gebruikt de ingebouwde fetch van Node.js 20 of hoger, dus je hebt geen afhankelijkheid voor een HTTP-client nodig. Sla het op als .mjs-bestand en voer het uit op de server.
const BASE_URL = 'https://api.poyo.ai';
const apiKey = process.env.POYO_API_KEY;
if (!apiKey?.trim()) throw new Error('Set POYO_API_KEY');
const headers = {
Authorization: `Bearer ${apiKey}`,
'Content-Type': 'application/json',
};
const retryableHttp = new Set([429, 500, 502, 503, 504]);
const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
async function responseData(response) {
if (!response.ok) throw new Error(`HTTP ${response.status}`);
const body = await response.json();
if (body.code !== 200 || !body.data || typeof body.data !== 'object') {
throw new Error(`Unexpected API response: ${JSON.stringify(body)}`);
}
return body.data;
}
export async function submitH3(prompt, duration = 5) {
const response = await fetch(`${BASE_URL}/api/generate/submit`, {
method: 'POST', headers,
body: JSON.stringify({
model: 'hailuo-03',
input: { prompt, duration, resolution: '2K', aspect_ratio: '16:9' },
}),
signal: AbortSignal.timeout(30_000),
});
const data = await responseData(response);
if (typeof data.task_id !== 'string' || !data.task_id) {
throw new Error('Submission response is missing a task ID; check records instead of resubmitting automatically');
}
return data.task_id;
}
export async function waitForH3(taskId, maxPolls = 60) {
for (let attempt = 0; attempt < maxPolls; attempt++) {
await sleep(10_000);
let response;
try {
response = await fetch(
`${BASE_URL}/api/generate/status/${encodeURIComponent(taskId)}`,
{ headers, signal: AbortSignal.timeout(30_000) },
);
} catch (error) {
if (error instanceof Error &&
(error.name === 'TimeoutError' || error.name === 'TypeError')) {
continue;
}
throw error;
}
if (retryableHttp.has(response.status)) {
await response.body?.cancel();
continue;
}
const task = await responseData(response);
if (task.status === 'finished') {
const video = task.files?.find((file) => file.file_type === 'video' && file.file_url);
if (!video) throw new Error(`Task ${taskId} finished, but the response has no video URL`);
return video.file_url;
}
if (task.status === 'failed') {
throw new Error(`Task ${taskId} failed: ${task.error_message || 'No error details provided'}`);
}
if (!['not_started', 'running'].includes(task.status)) {
throw new Error(`Task ${taskId} returned an unknown status: ${task.status}`);
}
}
throw new Error(`Query limit reached; keep the task ID and query again later: ${taskId}`);
}
const taskId = await submitH3('A golden retriever walks through a sunlit autumn park.');
// In your application, save taskId to the database here before polling.
console.log(`Task ID: ${taskId}`);
console.log(await waitForH3(taskId));
Om het opvragen te hervatten, vervang je de aanroepen voor indienen en opvragen onderaan het bestand door waitForH3(savedTaskId). Dit pollingvoorbeeld past bij scripts of achtergrondtaken. Geef in een webapplicatie de taak-ID terug aan de frontend en volg de generatie op de achtergrond, in plaats van een paginaverzoek te laten wachten.
Ontvang resultaten via een webhook
Je kunt ook callback_url op het hoogste niveau van het indieningsverzoek meegeven, naast model en input, bijvoorbeeld https://your-domain.com/webhooks/poyo. PoYo stuurt het resultaat naar die URL wanneer de taak slaagt of mislukt.
De ontvanger moet de taak-ID vergelijken met lokale gegevens en dubbele meldingen per taak-ID afhandelen, zodat vervolgacties niet worden herhaald. Tijdrovend werk zoals het downloaden of transcoderen van de video kan in achtergrondtaken draaien. Ook tijdens de integratie van callbacks kun je statusopvragingen blijven gebruiken om resultaten te verifiëren.
Prompts en voorbeeldscènes
Beschrijf eerst het subject en de handeling, en voeg daarna camerabeweging, omgeving, licht en geluid toe. Benoem bij referentiemedia de rol van Image 1, Video 1 of Audio 1, zodat één referentie geen tegenstrijdige eisen krijgt.
De vier Engelse voorbeelden hieronder illustreren hoe je prompts schrijft; ze bevatten geen geteste generatieresultaten. Engelse termen maken de voorbeelden makkelijk herbruikbaar, maar suggereren niet dat Engels per se beter werkt dan Chinees. Instructies over timing en het behoud van uiterlijk beschrijven de bedoelde resultaten; controleer de werkelijke output.
Productadvertentie: 8 seconden, modus met referentieafbeelding
Zet de productafbeelding als eerste in input.reference_image_urls, stel duration: 8 en aspect_ratio: "16:9" in en gebruik de tekst hieronder als prompt. Volg de structuur van het verzoek in de referentiemodus hierboven; haal reference_video_urls weg als je geen referentievideo nodig hebt.
Use Image 1 as the product reference. A clear glass perfume bottle rests on
wet black stone after rain. Preserve the bottle shape, cap, and label placement.
One continuous 8-second shot: begin close to the water droplets, then slowly
pull back to reveal the bottle in warm rim light. Realistic glass reflections,
no added text. Soft rain ambience.
Begin met een eenvoudige shot om te controleren of de fles en het etiket consistent blijven, en probeer daarna een complexere camerabeweging in een baan eromheen.
Dialoog van een personage: 8 seconden, modus met referentieafbeelding
Zet de afbeelding van het personage als eerste in input.reference_image_urls en stel duration: 8 en aspect_ratio: "16:9" in. Met een korte regel dialoog controleer je makkelijker de lipsynchronisatie, het spreektempo en het uiterlijk van het personage.
Use Image 1 as the character reference. An 8-second medium close-up of a pastry
chef in a quiet kitchen at sunrise. She looks into the camera and says:
"Every detail matters in baking." Natural breathing, a subtle smile,
soft window light. Preserve her face, hairstyle, and apron. A steady camera,
clear speech, quiet room tone.
Verticale gameadvertentie: 10 seconden, tekst naar video
Stel duration: 10 en aspect_ratio: "9:16" in. Tijdsegmenten geven de bedoelde volgorde van handelingen aan; voelt de scène te druk, verminder dan eerst het aantal handelingen en personages.
A 10-second vertical fantasy game trailer.
0-3s: An armored knight walks through a ruined stone gate.
3-6s: One creature charges; the knight blocks once with a shield.
6-9s: The camera rises to reveal the fortress walls.
9-10s: Hold the final composition.
Readable action, consistent armor, wind and impact sounds, no UI or captions.
Doorlopende trackingshot: 10 seconden, tekst naar video
Stel duration: 10 en aspect_ratio: "16:9" in. Bouw de shot op rond één subject en één route en controleer daarna op cuts, veranderingen van het subject of een onderbroken beweging.
One unbroken 10-second tracking shot follows a cyclist through a night market.
Begin behind the rear wheel, rise to shoulder height, then move alongside
without cutting. Wet pavement reflections, a clear path between stalls,
consistent bicycle geometry, no speed ramps or scene transitions.
Natural street ambience and bicycle tires rolling on wet pavement.
Veelgestelde vragen en hulp bij integratieproblemen
Kan ik het eigen API-verzoekformaat van MiniMax rechtstreeks gebruiken?
Deze voorbeelden gebruiken POST /api/generate/submit en GET /api/generate/status/{task_id} van PoYo. Endpoints, model-ID's en veldstructuren kunnen per platform verschillen; volg de documentatie van het platform dat je gebruikt.
Moet ik een taak opnieuw indienen die op not_started blijft staan?
not_started betekent dat de taak op verwerking wacht; het is op zichzelf geen mislukking. Bewaar de taak-ID en blijf opvragen. Is de wachtlimiet van je applicatie verstreken, leg de taak dan vast en controleer haar later. Neem indien nodig contact op met support en geef de taak-ID door.
Wat als het indienen een time-out krijgt voordat ik een taak-ID heb ontvangen?
Een time-out van het verzoek bewijst niet dat de server de taak niet heeft geaccepteerd. Controleer eerst de taakgegevens; neem zo nodig contact op met support met details zoals het tijdstip van indienen. Je hebt een taak-ID nodig om het statusendpoint te gebruiken. Zie opnieuw indienen niet als oplossing voor een mislukte opvraging.
Kan ik afbeeldingen, video en audio als referenties combineren?
Ja, combineer ze in de referentiemodus binnen de hierboven genoemde aantallen en duurlimieten. Voor referentie-audio is een referentieafbeelding of -video nodig. Deze velden kun je niet combineren met image_urls voor de modus met eerste en laatste frame.
Hoeveel kost een video van 10 seconden?
Tegen de hier genoemde prijzen, zonder referentiemedia, zijn de kosten 10 × 21 = 210 credits, oftewel $1.05. Referentievideo's en referentieafbeeldingen na de eerste 5 komen daar nog bij.
Controleer voordat je in je applicatie integreert dat de media-URL's rechtstreeks downloaden toestaan, sla taak-ID's op en stel per gebruiker passende limieten in voor generaties en gelijktijdigheid. Controleer voordat je een gegenereerde video publiceert of het uiterlijk van personages, de vorm van producten, tekst, beweging en geluid geschikt zijn voor het beoogde gebruik.
Probeer te genereren op de modelpagina van MiniMax H3 of ga naar de pagina met API-sleutels om met integreren te beginnen. Meer over de modellen lees je in de review van MiniMax H3 en de vergelijking van MiniMax H3 en Seedance 2.5.