API documentation
The WaifuRush API makes anime videos, image packs and captions from your own code, with the same models and prices as the studio. It is a small JSON over HTTPS API: upload an image, create a job, poll it until it finishes, download the result. Every job spends credits from the account that owns the API key.
| Base URL | https://waifurush.com/api/v1 |
| Auth | Authorization: Bearer wr_live_… |
| Format | JSON requests and responses (UTF-8). Times are ISO 8601 UTC. |
| Keys | Settings → API |
Quickstart
- Create a key in Settings → API and make sure the account has credits.
POST /uploadsto get an upload URL, thenPUTthe image bytes to it.POST /videoswith amodeand the uploadidasimage.GET /videos/:idevery 5–10 seconds untilstatusissucceeded,failedorcanceled, then download fromdownload_url.
# 1. Get an upload URL, then PUT the image to it
curl https://waifurush.com/api/v1/uploads \
-H "Authorization: Bearer $WR_KEY" \
-H "Content-Type: application/json" \
-d '{"filename":"mika.png","mime":"image/png","size":482113}'
curl -X PUT "$UPLOAD_URL" -H "Content-Type: image/png" \
--data-binary @mika.png
# 2. Create the video
curl https://waifurush.com/api/v1/videos \
-H "Authorization: Bearer $WR_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: mika-001" \
-d '{"mode":"videoPro","image":"'$UPLOAD_ID'","duration":8}'Authentication
Send your key in the Authorization header on every request. Keys start with wr_live_, are shown once when created, and can be revoked at any time in Settings (requests with a revoked key get 401 immediately). An account can hold up to 10 keys.
Keep keys on your server. The API does not send CORS headers, so it cannot be called from a browser: a key in front-end code would let anyone spend your credits.
Modes & pricing
A mode picks the generator. You never write the model prompt: WaifuRush writes it from your images (and your optional idea), exactly as in the studio. The output follows the aspect ratio of your image (closest of 21:9, 16:9, 4:3, 1:1, 3:4, 9:16); a continuation keeps the size of the video it continues.
| mode | what it makes | inputs | options (default first) |
|---|---|---|---|
video | One start image → a seamless 5-second loop. | image (required) | resolution: 720p | 480p quality: turbo | standard |
videoPro | A start image, an end image or both (+ an optional idea) → 5 to 15 seconds. | image, end_image (image or end_image required), idea | duration: 5 | 8 | 10 | 15 resolution: 720p | 480p quality: turbo | standard |
director | Continues an earlier video (yours, or one published in the community) from its last frame, with an optional end image and idea. Paid plans. | end_image, source (required), idea | duration: 5 | 8 | 10 | 15 resolution: 720p | 480p quality: turbo | standard |
wallpaper | One start image + a motion level → a 5-second video and its best seamless loop (two outputs). | image (required) | motion: medium | still | gentle | strong | extreme resolution: 720p | 480p quality: turbo | standard |
Credits per video (turbo is the fast default; standard takes more steps for more detail). The price is charged when the job is created and refunded in full if it fails or is canceled before it reaches the GPU. GET /models returns this table as JSON.
| mode | length | 480p turbo | 720p turbo | 480p standard | 720p standard |
|---|---|---|---|---|---|
video | 5 s | 26 | 32 | 60 | 74 |
videoPro | 5 s | 26 | 32 | 60 | 74 |
videoPro | 8 s | 53 | 66 | 109 | 136 |
videoPro | 10 s | 76 | 95 | 148 | 185 |
videoPro | 15 s | 144 | 180 | 320 | 400 |
director | 5 s | 32 | 40 | 74 | 93 |
director | 8 s | 66 | 83 | 136 | 170 |
director | 10 s | 95 | 119 | 185 | 232 |
director | 15 s | 180 | 225 | 400 | 500 |
wallpaper | 5 s | 26 | 32 | 60 | 74 |
Upload an image
Body: filename, mime (image/png, image/jpeg or image/webp) and size in bytes (up to 25 MB). The response holds a presigned upload_url, valid for expires_in seconds: PUT the raw bytes to it with the returned headers. Then use the upload id as image or end_image. Uploads belong to your account; another account's upload id is rejected.
{
"id": "waifurush/prod/<account>/inputs/<uuid>/mika.png",
"object": "upload",
"upload_url": "https://…r2.cloudflarestorage.com/…",
"headers": { "Content-Type": "image/png" },
"expires_in": 900
}Use clean, reasonably large images (at least 512 px on the short side). Drawn or anime art works best.
Create a video
| field | type | |
|---|---|---|
mode | string | Required. video, videoPro, director or wallpaper. |
image | upload id | Start image (see the mode table). |
end_image | upload id | End image: the video ends on it. |
source | video id | The video to continue (director): one of yours, or one published in the community. |
idea | string | Optional direction, up to 1500 characters (videoPro, director). |
duration | number | Seconds: 5, 8, 10 or 15 (videoPro, director). |
resolution | string | 480p or 720p (default). |
quality | string | turbo (default) or standard. |
motion | string | still, gentle, medium (default), strong or extreme (wallpaper). |
seed | integer | 0 – 2147483647, for repeatable results. |
visibility | string | private (default) or public (shared in the community feed). |
Unknown fields, and options the mode does not take, are rejected with 422 invalid_input rather than ignored. The response is 201 with the video object in status preparing; the credits are already charged.
Get a video
Returns the video object with fresh status and progress. Poll every 5–10 seconds. A job goes preparing (writing the prompt, a few seconds) → queued (waiting for a GPU; a cold GPU takes 2–4 minutes to start) → running (progress moves from 0 to 1) → succeeded, failed or canceled. Most videos finish within a few minutes of starting to run.
List videos
Your videos, newest first, made in the studio or through the API. limit is 1–100 (default 20). When has_more is true, pass next_cursor as before to get the next page. List items are not refreshed against the GPU: use GET /videos/:id to follow a running job.
{ "object": "list", "data": [ { "id": "…", "object": "video", … } ], "has_more": true, "next_cursor": "2026-10-09T12:31:08.512Z" }Cancel
Cancels a video that is still preparing and refunds it. Once a job has been sent to the GPU it can no longer be canceled and is paid: the call answers 409 already_started.
Download
Redirects (302) to a download URL of the full-quality MP4, valid for one hour. variant=loop downloads the seamless loop of a wallpaper video. Follow redirects (curl -L). The url of each output is a lighter, web-optimized copy, fine for previews.
Account & models
{ "id": "…", "object": "account", "plan": "pro", "credits": 2410, "concurrency": 4, "director": true, "pack_max_images": 120 }Every mode with its inputs, options, defaults and the credit price of each option combination.
The video object
{
"id": "5f0c2a8e-3b1d-4c7a-9e21-8d4b6f1a0c37",
"object": "video",
"mode": "wallpaper",
"status": "succeeded", // preparing | queued | running | succeeded | failed | canceled
"progress": 1, // 0..1, real sampling progress
"cost": 20, // credits charged (refunded on failure)
"visibility": "private",
"created_at": "2026-10-09T12:30:41.120Z",
"finished_at": "2026-10-09T12:33:02.877Z",
"input": { "idea": null, "motion": "gentle", "resolution": "720p", "quality": "turbo",
"source": null, "image": "waifurush/prod/…/mika.png", "end_image": null, "seed": null },
"outputs": [
{ "type": "loop", "url": "https://media.waifurush.com/…/loop.mp4", "poster_url": "…",
"width": 720, "height": 1280, "download_url": "https://waifurush.com/api/v1/videos/5f0c…/content?variant=loop" },
{ "type": "video", "url": "https://media.waifurush.com/…/video_web.mp4", "poster_url": "…",
"width": 720, "height": 1280, "download_url": "https://waifurush.com/api/v1/videos/5f0c…/content?variant=video" }
],
"error": null // { "code": "INVALID_INPUT" | "TIMEOUT" | "INTERNAL" } when failed
}Output urls are stable and public to anyone holding them, including for private videos; download URLs expire. A failed video is always refunded.
Image packs
One order → 8 to 120 coherent images of one or two characters. Our planner turns what you want into a varied set of scenes; you never write prompts. Characters are any names or booru tags: the planner matches names, series and typos, and uses an unknown name as a tag. 4 credits per image; images the GPU fails to deliver are refunded one by one.
| field | type | |
|---|---|---|
characters | string[] | Required. 1 or 2 character names or tags, e.g. ["tifa_lockhart"] or ["Tifa Lockhart"]. |
aspect_ratio | string | 9:16 (default, 872×1552) or 16:9 (1552×872). |
image_count | integer | 8 – 120, even numbers only (default 20); above 30 on paid plans. |
outfit | string | default (their official outfit) or any outfit name up to 80 characters, e.g. maid, bikini; GET /models lists the 146 it knows. |
what_i_want | string | Optional, any language, up to 2000 characters. |
what_i_dont_want | string | Optional, any language, up to 2000 characters. |
seed | integer | 0 – 2147483647, for repeatable packs. |
visibility | string | private (default) or public. |
GET /packs/:id while it runs: progress (0..1) and images_done grow as images finish; images lists the finished ones once it succeeds. GET /packs, POST /packs/:id/cancel (only while preparing) and Idempotency-Key work as for videos. GET /packs/:id/content?index=0&variant=original redirects to the full-quality PNG of one image (variant=web: a lighter WebP).
{
"id": "8c1d…", "object": "pack", "status": "succeeded", "progress": 1, "cost": 60,
"visibility": "public", "created_at": "…", "finished_at": "…", "images_done": 19,
"input": { "characters": ["tifa_lockhart"], "aspect_ratio": "9:16", "image_count": 20, "outfit": "maid",
"what_i_want": "beach day", "what_i_dont_want": null, "seed": null },
"images": [ { "index": 0, "url": "https://media.waifurush.com/…/image_0.webp", "thumbnail_url": "…",
"width": 872, "height": 1552, "download_url": "https://waifurush.com/api/v1/packs/8c1d…/content?index=0" }, … ],
"refunded": 3, // credits back for images that could not be made (here 1 of 20)
"error": null
}Captions
Draws text written for each image onto it: caption (3–6 speech lines around the subject), snapchat (one line on a bar) or panel (a monologue panel beside the image). 2 credits per image; an image that could not be made is refunded.
| field | type | |
|---|---|---|
images | array | Required, 1 – 20. An upload id (from POST /uploads), or { "creation": "<pack id>", "index": 3 } for an image of one of your packs. |
type | string | caption (default), snapchat or panel. |
request | string | Optional: what the text should say, any language, up to 2000 characters. Empty: written from the image. |
visibility | string | private (default) or public. |
The object is like a pack's ("object": "caption", images, refunded); GET /captions/:id/content?index=i downloads one PNG.
Idempotency
Send an Idempotency-Key header (1–255 printable characters, unique per job you mean to create) with POST /videos, /packs or /captions. If the request is retried with the same key — after a timeout, say — the API returns the video the first request created (200) instead of charging again. Keys are scoped to your account and never expire; the body of a retry is not compared, so use a new key for a new job.
Limits
- 120 requests per minute per account and per IP address. Over it:
429 rate_limitedwithRetry-After. - Starting videos: 20 per minute per account.
- Videos running at once, by plan: free 1 · starter 2 · pro 4 · studio 8. Starting one more answers
429 concurrency_limit; wait for one to finish. - Images up to 25 MB; ideas up to 1500 characters.
Errors
Errors use HTTP status codes and a stable machine-readable code:
{ "error": { "code": "insufficient_credits", "message": "…" } }| status | code | meaning |
|---|---|---|
| 401 | unauthenticated | Missing, malformed or revoked API key. |
| 402 | insufficient_credits | Not enough credits for this job. Buy credits on the pricing page. |
| 403 | plan_required | A paid plan is needed: director, or a pack over 30 images. |
| 404 | not_found | No such video (or upload, or source) in this account. |
| 409 | already_started | The video is on the GPU and can no longer be canceled. |
| 422 | invalid_input | The body is invalid; the message names the field. |
| 429 | concurrency_limit | Too many videos running at once for your plan. |
| 429 | rate_limited | Too many requests. Retry after the Retry-After seconds. |
| 5xx | unknown | Our side failed. Retry with the same Idempotency-Key. |
Content policy
API use follows the same terms and content policy as the studio. Questions or higher limits: support@waifurush.com.