Your coding agent can do the wiring.
Base URL, auth, models, the three calls and error handling, in one prompt.
Agent prompt
# Task: generate Seedance video through the Loopling API
Add Seedance video generation to this codebase using the Loopling REST API. If the code already calls fal for Seedance, replace those calls with the contract below; otherwise add one small, typed client module. Follow the contract exactly and do not invent endpoints or fields.
## Contract
- Base URL: https://loopling.ai/v1
- Auth: every request sends `Authorization: Bearer $LOOPLING_API_KEY`. Read the key from the LOOPLING_API_KEY environment variable on the server. Never hardcode it, never log it, never ship it to a browser or a mobile app.
- Requests and responses are JSON (`Content-Type: application/json`). Field names are snake_case.
## Models (one endpoint; choose the model per request)
- `seedance-2.5` (Seedance 2.5): resolution "480p" | "720p" | "1080p"; with aspect_ratio "9:16" or "adaptive" the ceiling is 720p; duration 4–30 s (integer); up to 50 references (30 images, 10 videos, 10 audio).
- `seedance-2.0` (Seedance 2.0): resolution "480p" | "720p" | "1080p"; duration 4–15 s (integer); up to 12 references (9 images, 3 videos, 3 audio).
- `seedance-2.0-fast` (Seedance 2.0 Fast): resolution "480p" | "720p"; duration 4–15 s (integer); up to 12 references (9 images, 3 videos, 3 audio).
## The three calls
1. Submit — `POST /v1/video/generations` (https://loopling.ai/v1/video/generations)
Body: {"model": "seedance-2.5", "prompt": "…", "resolution": "720p", "aspect_ratio": "16:9", "duration": 5, "generate_audio": true}
Defaults: resolution "720p", aspect_ratio "16:9", duration 5, generate_audio true. aspect_ratio is one of "21:9", "16:9", "4:3", "1:1", "3:4", "9:16", "adaptive".
Optional: seed (integer); first_frame_url and last_frame_url (last needs first); reference_image_urls, reference_video_urls, reference_audio_urls (arrays). Every input is a public https URL. Frames and reference_* inputs cannot be combined in one request.
Send an `Idempotency-Key` header (1–128 of letters, digits, `.` `_` `:` `-`), unique per intent, so a retried submit never starts a second render.
Answer: 202 with {"id": "vgen_…", "status": "queued", "ink_reserved": …, "request": {…}}.
2. Poll — `GET /v1/video/generations/{id}` every 5 seconds until status is "succeeded" or "failed" (statuses: queued, running, succeeded, failed; `progress` 0–100 may appear while running). Give up after a timeout you choose (renders usually take one to a few minutes).
On "succeeded": `video.url` is a signed MP4 link valid for 15 minutes. Download it straight away, or read the generation again for a fresh link. Results are kept for 7 days.
On "failed": `error.code` and `error.message` explain it, and `ink_charged` is 0.
3. Download — `GET /v1/video/generations/{id}/content` answers 302 to a fresh signed URL; follow the redirect. It answers 409 `generation_not_ready` before the render finishes.
## Errors
Every error is {"error": {"type", "code", "message", "param", "request_id"}}.
- 400 `invalid_request_error`: fix the field named in `param`; never retry it unchanged.
- 401 `authentication_error`: the key is missing, unknown or revoked.
- 402 `insufficient_ink_error`: the wallet (`insufficient_ink`) or the key's Ink cap (`key_ink_limit_reached`) cannot cover the request. Surface it; do not retry.
- 429 `rate_limit_error`: wait for the `Retry-After` seconds, then retry. Limits: 2 video generations running at once per account, 60 requests per minute per key, and the plan's daily cap.
- 502 / 503 `provider_error`: retry later with backoff, honouring `Retry-After`, and with a new `Idempotency-Key`: a 502, or a 503 saying the generation could not be admitted, has already bound the old key to a failed generation, so resending it only replays that failure. Nothing is charged for a request that never ran.
## Moving from fal
- Replace `Authorization: Key $FAL_KEY` with `Authorization: Bearer $LOOPLING_API_KEY`.
- fal picks the model by endpoint path; here every model shares one endpoint and the body carries `model`.
- prompt, resolution, aspect_ratio, generate_audio and seed keep their names. `duration` must be an integer number of seconds (convert a string such as "5"); there is no "auto".
- The image-to-video start image (`image_url` on fal) becomes `first_frame_url`; an end image becomes `last_frame_url`; reference lists become `reference_image_urls`, `reference_video_urls` and `reference_audio_urls`.
- fal's queue status and result calls become one poll: `GET /v1/video/generations/{id}` returns the status and, once done, `video`.
- Remove the fal client and its key from configuration once nothing else uses them.
## Done when
- One function submits, polls with a timeout, and returns the finished MP4 (bytes or a stored copy), surfacing `error.message` on failure.
- The key is read from LOOPLING_API_KEY only, and tests mock the HTTP calls instead of spending Ink.
- Reference: https://loopling.ai/developers/docs/create-video-generation
- Keys: https://loopling.ai/developers/keys (a paid plan or one completed Ink top-up is needed to create one).Shown once. Store it on your server as LOOPLING_API_KEY.
Needs a paid plan or one top-up. Top up
Try one in the Playground first.
up to 1080p · 4–30 s · from $0.116 / s
up to 1080p · 4–15 s · from $0.079 / s
up to 720p · 4–15 s · from $0.063 / s
What changes for the same request.
| What | On fal | On Loopling |
|---|---|---|
| Base URL | https://queue.fal.run | https://loopling.ai/v1 |
| Auth header | Authorization: Key $FAL_KEY | Authorization: Bearer $LOOPLING_API_KEY |
| Choosing the model | The endpoint path | The model field; one endpoint for all |
| Polling | Queue status, then a separate result call | One read: the status, then the video |
| Result link | A file URL in the result | Signed video.url, valid 15 minutes. Kept 7 days. |
prompt, resolution, aspect_ratio, generate_audio and seed keep their names. Add model, and send duration in whole seconds.
loopling.ai · grows with you, grows itself
hello@loopling.ai · for agents · community · pricing · Enterprise · API · privacy · terms