ApiLux

Video generation

Create a video from a prompt, from an image, or from a first and last frame. Returns a job immediately — rendering takes tens of seconds to minutes.

ImplementedAvailability depends on the selected model being enabled and priced in ApiLux.

Request

POST/videos/generations

Requires the Authorization: Bearer apl_... header

FieldTypeDescription
modelrequiredstringPublic model ID whose kind is VIDEO.
promptrequiredstringDescribe the scene, motion and style.
duration_secondsrequired4 | 6 | 8Only 4, 6 or 8. Anything else is rejected before the provider is called.
aspect_ratio"16:9" | "9:16"Defaults to 16:9. Use 9:16 for vertical video.
imageImageInputFirst frame, for image-to-video. Same shape as image on the edit endpoint.
last_frameImageInputLast frame. Must be sent together with image.

Response

FieldTypeDescription
idrequiredstringThe ApiLux job ID (vidjob_...). Use it to poll and download.
statusrequired"queued" | "running" | "completed" | "failed"Status at creation time, usually queued.
requested_duration_secondsrequiredintegerThe number of seconds you were charged for.
apilux.credit_chargedrequiredintegerCredits charged at creation.

Billing

Charged at job creation, by the duration_seconds you requested. Polling costs nothing extra. A failed job is refunded automatically, exactly once.

Examples

cURL
curl https://apilux.net/api/v1/videos/generations \
  -H "Authorization: Bearer apl_YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "VIDEO_MODEL_ID",
    "prompt": "Sáng sớm trên biển, chuyển động điện ảnh",
    "duration_seconds": 4,
    "aspect_ratio": "16:9"
  }'
Python
import os, time, requests

BASE = "https://apilux.net/api/v1"
HEAD = {"Authorization": f"Bearer {os.environ['APILUX_API_KEY']}"}

job = requests.post(
    f"{BASE}/videos/generations",
    headers=HEAD,
    json={
        "model": "VIDEO_MODEL_ID",
        "prompt": "Sáng sớm trên biển, chuyển động điện ảnh",
        "duration_seconds": 4,
    },
).json()

while True:
    time.sleep(5)
    state = requests.get(f"{BASE}/videos/generations/{job['id']}", headers=HEAD).json()
    if state["status"] in ("completed", "failed"):
        break

if state["status"] == "completed":
    mp4 = requests.get(BASE.rsplit("/v1", 1)[0] + state["content_url"], headers=HEAD)
    open("video.mp4", "wb").write(mp4.content)

Errors

HTTPCodeMeaning
400invalid_requestInvalid body (missing field, wrong type, value out of range).
401auth_missing_or_malformedMissing Authorization header, or it is not in the Bearer apl_... form.
401auth_invalidThe API key does not exist.
401auth_revokedThe API key has been revoked.
401auth_expiredThe API key has expired.
400unknown_modelThe model does not exist on ApiLux.
400capability_not_supportedThe model exists but cannot be used on this endpoint (e.g. a text model on an image endpoint).
503pricing_not_configuredThe model is implemented but has no price configured on ApiLux yet. This is our state, not a client error.
503model_disabledThe model is currently disabled.
503model_temporarily_unavailableThe model is enabled and priced, but the upstream provider is not currently serving it. This is temporary and can clear on its own — the model reappears in GET /v1/models once the provider serves it again. You are not charged and no provider call is made.
402insufficient_balanceWallet balance is not enough for this request.
429api_key_limit_exceededThis API key hit a limit you configured yourself. The wallet still has funds — only this key is capped until the window resets. The response carries limit_type (spending | requests | tokens) and period (daily | monthly | lifetime). Token limits on text endpoints are measured from actual usage, so the total can exceed the limit by at most one request.
503api_key_quota_reconciliation_requiredAn earlier text request on this same key has not been reconciled yet. The usual cause: the provider returned a successful result without token usage, so the token limit for that window can no longer be trusted and ApiLux stops rather than let the limit be exceeded silently. Retrying will not help until that is done — contact support. You are not charged for the blocked request, no provider call is made, and image/video endpoints are unaffected.
502upstream_errorThe model provider failed. You are not charged.
504upstream_timeoutThe provider did not respond in time. You are not charged.
429upstream_rate_limitedRate limited. Retry after a few seconds.

Notes

If the create request already returned an id, do not resend it — poll that id. Resending creates a second job and charges again.