Wan 3.0 Video API
Base URL: https://api.amazingaitoken.com/v1
Authentication
Create an API key in your dashboard and send it in every request:
Authorization: Bearer aat_live_...
Keep keys secret (server-side only). Revoke a key anytime in the dashboard. Limit: 120 requests per minute per key, 5 videos in progress at once.
Pricing
Videos are paid with Wan credits: 1 credit per second at 480P, 2 at 720P, 4 at 1080P. Billed seconds = output video seconds + any reference video seconds you send. Failed videos cost nothing.
When you start a video we hold the most it can cost (requested duration, or 30 s if you send a reference video or use duration: -1). When it finishes we charge the real cost and return the rest.
Start a video — POST /wan/videos
curl https://api.amazingaitoken.com/v1/wan/videos \
-H "Authorization: Bearer $AAT_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: my-order-123" \
-d '{
"prompt": "A kitten running on a rooftop under the moonlight, cinematic",
"resolution": "720P",
"ratio": "16:9",
"duration": 5
}'| Field | Type | Description |
|---|---|---|
| prompt | string | What to generate (up to 20,000 characters). Required unless you send media. In reference mode, refer to inputs as "Image 1", "Video 1"… |
| media | array | Optional inputs: {"type": "...", "url": "https://..."}. Types: first_frame, last_frame (image-to-video), reference_image (≤10), reference_video (≤5, total ≤15 s), reference_audio (≤5, total ≤15 s), file or link (document/web page to video). First/last frame cannot be combined with reference_* / file / link. URL must be public, or a data: base64 URI. |
| resolution | string | 480P, 720P or 1080P. Default 1080P. |
| duration | integer | Seconds, 2–30 (default 5). With a reference video, input + output must be ≤ 30. -1 = automatic. |
| ratio | string | adaptive (default), 21:9, 16:9, 4:3, 1:1, 3:4, 9:16. |
| audio | boolean | Generate sound (default true, same price). |
| prompt_extend | boolean | Let the model improve your prompt (default true; must be true with file/link). |
| seed | integer | -1 (random) or 0–2147483647. |
| watermark | boolean | Add a watermark (default false). |
The optional Idempotency-Key header makes retries safe: the same key returns the same video instead of starting (and charging) a new one.
Response 201:
{
"id": "vid_4fK2...",
"object": "video",
"status": "queued",
"model": "wan3.0-video",
"resolution": "720P",
"duration": 5,
"credits_held": 10,
"credits_charged": null,
"video_url": null,
"balance": 170
}Check a video — GET /wan/videos/{id}
Videos usually take 1–5 minutes. Check every 15–30 seconds until status is succeeded or failed.
curl https://api.amazingaitoken.com/v1/wan/videos/vid_4fK2... -H "Authorization: Bearer $AAT_KEY"
{
"id": "vid_4fK2...",
"status": "succeeded",
"resolution": "720P",
"credits_held": 0,
"credits_charged": 10,
"video_url": "https://...mp4",
"video_expires_at": "2026-11-07T10:00:00.000Z",
"usage": { "input_video_seconds": 0, "output_video_seconds": 5, "billed_seconds": 5 },
"error": null,
"balance": 170
}Video links expire after 24 hours. Download and store the MP4 yourself. Status values: queued, running, succeeded, failed (with error.code and error.message; nothing charged).
List your recent videos: GET /wan/videos?limit=20.
Balance — GET /wan/balance
curl https://api.amazingaitoken.com/v1/wan/balance -H "Authorization: Bearer $AAT_KEY"
{ "object": "balance", "credits": 170, "unit": "wan_credit" }Buy credits — POST /wan/topup
Returns a Stripe payment link. Open it (or send it to the person paying); credits are added automatically after payment. Packages: usd_5 (USD 5 = 90 credits), usd_10 (USD 10 = 180 credits), usd_50 (USD 50 = 900 credits), usd_100 (USD 100 = 1,800 credits), usd_500 (USD 500 = 9,000 credits), usd_1000 (USD 1000 = 18,000 credits). Also listed at GET /wan/packages (no key needed).
curl https://api.amazingaitoken.com/v1/wan/topup \
-H "Authorization: Bearer $AAT_KEY" \
-H "Content-Type: application/json" \
-d '{"package": "usd_50"}'
{ "object": "checkout", "package": "usd_50", "price_usd": 50, "credits": 900,
"checkout_url": "https://checkout.stripe.com/...", "expires_at": "..." }Python example
import os, time, requests
BASE = "https://api.amazingaitoken.com/v1"
H = {"Authorization": f"Bearer {os.environ['AAT_KEY']}"}
job = requests.post(f"{BASE}/wan/videos", headers=H, json={
"prompt": "A red sports car driving through a neon city at night",
"resolution": "720P", "duration": 5,
}).json()
while job["status"] in ("queued", "running"):
time.sleep(20)
job = requests.get(f"{BASE}/wan/videos/{job['id']}", headers=H).json()
print(job["status"], job.get("video_url"), job.get("error"))JavaScript example
const BASE = "https://api.amazingaitoken.com/v1";
const H = { Authorization: `Bearer ${process.env.AAT_KEY}`, "Content-Type": "application/json" };
let job = await fetch(`${BASE}/wan/videos`, {
method: "POST", headers: H,
body: JSON.stringify({ prompt: "Drone shot over a tropical island", resolution: "480P", duration: 5 }),
}).then(r => r.json());
while (job.status === "queued" || job.status === "running") {
await new Promise(r => setTimeout(r, 20000));
job = await fetch(`${BASE}/wan/videos/${job.id}`, { headers: H }).then(r => r.json());
}
console.log(job.status, job.video_url);Errors
Errors return a non-2xx status and {"error": {"code": "...", "message": "..."}}.
| HTTP | code | Meaning |
|---|---|---|
| 400 | invalid_* | A field is wrong; the message says which. Model errors (e.g. InvalidParameter) are passed through. |
| 401 | invalid_api_key | Missing, wrong or revoked key. |
| 402 | insufficient_credits | Not enough Wan credits for this video. Top up. |
| 404 | not_found | No video with that id on your account. |
| 429 | rate_limited / too_many_active_jobs | Slow down, or wait for running videos to finish. |
| 502/503 | upstream_* | The video service had a problem. Nothing charged; retry. |