WanAPIs developer docs

Get started with WanAPIs

Call GPT, Claude, Gemini, DeepSeek, image, video and audio models with one OpenAI-compatible API key. Most projects only need to swap base_url and the API key.

Introduction

WanAPIs is a unified AI API gateway with an OpenAI-compatible interface, multi-channel routing, failover, a model marketplace, request logs and transparent billing. You can manage models from different upstreams under a single endpoint.

OpenAI-compatible

Works with common SDKs, Chat Completions, Responses and tool calling.

Unified marketplace

See model capabilities, vendors, prices and entry points on one page.

Production-grade reliability

Multi-channel, groups, retries and logs reduce the impact of upstream hiccups.

Quickstart

  1. Create an accountOpen the console, create an account and verify your email.
  2. Create an API keyGenerate a key on the Tokens page and set per-project quota.
  3. Swap the Base URLPoint your OpenAI SDK baseURL to https://api.wanapis.com/v1.
  4. Pick a modelChoose a model ID from the marketplace or pricing page.
cURL
curl https://api.wanapis.com/v1/chat/completions \
  -H "Authorization: Bearer $WANAPIS_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "deepseek-v4-pro",
    "messages": [
      { "role": "user", "content": "Explain RAG in three sentences" }
    ]
  }'

Authentication

Every request must carry a Bearer token in the header. Never put your API key in front-end browser code — proxy requests through your own backend.

FieldDescriptionExample
Base URLOpenAI-compatible API roothttps://api.wanapis.com/v1
HeaderRequest authAuthorization: Bearer sk-...
Content-TypeJSON bodyapplication/json

Key management

Create a separate API key per project with quota limits. After launch, watch model, group, latency and charges on the Logs page.

Chat Completions

Compatible with /v1/chat/completions — for most existing OpenAI SDKs, chatbots, agents and tool-calling projects.

Node.js
import OpenAI from "openai";

const client = new OpenAI({
  apiKey: process.env.WANAPIS_API_KEY,
  baseURL: "https://api.wanapis.com/v1",
});

const response = await client.chat.completions.create({
  model: "deepseek-v4-pro",
  messages: [{ role: "user", content: "Write a TypeScript retry function" }],
});

console.log(response.choices[0].message.content);
Python
from openai import OpenAI

client = OpenAI(
    api_key=os.environ["WANAPIS_API_KEY"],
    base_url="https://api.wanapis.com/v1",
)

response = client.chat.completions.create(
    model="gemini-3.5-flash",
    messages=[{"role": "user", "content": "Give me a product launch checklist"}],
)

print(response.choices[0].message.content)

Responses API

For the next-gen Responses workflow, call /v1/responses. On upstream 503 or high load, add exponential-backoff retries on your side.

Responses
curl https://api.wanapis.com/v1/responses \
  -H "Authorization: Bearer $WANAPIS_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "gpt-5.5",
    "input": "Analyze this log and give troubleshooting steps"
  }'

Model marketplace

The marketplace syncs from the WanAPIs pricing API and shows capabilities, vendors and prices by category: video, image, LLM and audio.

Clients / IDE

A key section. Any OpenAI / Anthropic-compatible client that supports a custom base_url can use WanAPIs. We recommend getting the local CLI working first, then the VS Code extensions: Claude Code → CC Switch → Codex Desktop → Codex CLI → VS Code.

1. Claude Code (recommended)

Anthropic's official CLI agent. With WanAPIs you can use claude-opus-4-7、claude-sonnet-4-6 and other Claude models.
Claude Code
# 1. Install (requires Node.js >= 18)
npm i -g @anthropic-ai/claude-code

# 2. Set env vars; add to ~/.zshrc or ~/.bashrc
export ANTHROPIC_BASE_URL="https://api.wanapis.com"
export ANTHROPIC_AUTH_TOKEN="sk-xxx"

# 3. Start in your project directory
cd your-project && claude

On first launch it asks you to pick a model. Verify the install with claude --version.

2. CC Switch (desktop GUI switcher)

CC Switch manages providers for agents like Claude Code / Codex / Gemini CLI, switching base_url and token in one click.

CC Switch setup

Entrycodex / claude group -> + at top right
NameWanAPIs
Base URLhttps://api.wanapis.com
API Keysk-xxx
EnableAfter saving, click Enable / Switch to
CC Switch
# Download from GitHub Releases:
# https://github.com/farion1231/cc-switch/releases

# 1. Open CC Switch
# 2. Go to the codex or claude group
# 3. Click + on the right to add WanAPIs
# 4. After saving, click Enable / Switch to
# 5. Restart Codex, VS Code or Claude Code
One-click import (if CC Switch is installed)

Click a button below to import the WanAPIs preset (no key included); then paste your API key in CC Switch.

After saving, restart Codex, VS Code or Claude Code so stale config doesn't linger in the process environment.

3. Codex Desktop (macOS / Windows)

OpenAI's official Codex desktop app. Desktop, CLI and IDE extensions share ~/.codex/config.toml; the native Windows path is %USERPROFILE%\.codex\config.toml.

Codex Desktop settings

Auth methodAPI Key
Config file~/.codex/config.toml
Windows%USERPROFILE%\.codex\config.toml
Providermodel_provider = "wanapis"
Base URLhttps://api.wanapis.com/v1
Wire APIresponses
~/.codex/config.toml
model = "gpt-5.5"
model_provider = "wanapis"

[model_providers.wanapis]
name = "WanAPIs"
base_url = "https://api.wanapis.com/v1"
wire_api = "responses"
env_key = "WANAPIS_API_KEY"
Environment variables
# macOS / Linux: add to ~/.zshrc or ~/.bashrc, then reopen the terminal
export WANAPIS_API_KEY="sk-xxx"

# Windows PowerShell: persist to the current user's environment variables
[Environment]::SetEnvironmentVariable("WANAPIS_API_KEY", "sk-xxx", "User")
  1. 1. Install and open Codex Desktop, choose API Key as the auth method instead of ChatGPT account login.
  2. 2. Create the config.toml above and point the model and provider at WanAPIs.
  3. 3. Set WANAPIS_API_KEY, then restart Codex Desktop; restart VS Code/Cursor too if you use them.
  4. 4. Native Windows Codex and WSL Codex don't share the same home; in WSL write a separate ~/.codex/config.toml, or set CODEX_HOME to point at the same directory.

Model choice

For coding tasks prefer gpt-5.5 or claude-sonnet-4.7. If a model doesn't support the Responses format or tool calling, switch to a tool-calling-capable model from the marketplace to verify first.

4. Codex CLI

OpenAI's official coding agent. We recommend the responses wire API, and writing the provider into ~/.codex/config.toml.
Codex CLI
# 1. Install
npm i -g @openai/codex

# 2. Edit ~/.codex/config.toml
cat > ~/.codex/config.toml <<'EOF'
model = "gpt-5.5"
model_provider = "wanapis"

[model_providers.wanapis]
name = "WanAPIs"
base_url = "https://api.wanapis.com/v1"
wire_api = "responses"
env_key = "WANAPIS_API_KEY"
EOF

# 3. Set the token
export WANAPIS_API_KEY="sk-xxx"

# 4. Start in your project directory; it reads the same ~/.codex/config.toml
cd your-project && codex

5. VS Code extensions

Two kinds: official Codex / Claude Code extensions usually reuse your local CLI config; third-party ones like Cline, Continue and Roo Code take the URL, key and model directly in their settings.

Official Codex extension (openai.chatgpt)

Install openai.chatgpt from the VS Code extension marketplace. It doesn't take a Base URL in the chat box; first set up ~/.codex/config.toml, then restart VS Code. The official Codex extension reuses the model and provider settings from your local Codex config.

Official Codex extension config path

Install fromVS Code -> openai.chatgpt
Config file~/.codex/config.toml
base_urlhttps://api.wanapis.com/v1
env_keyWANAPIS_API_KEY
How to applyRestart VS Code after saving
~/.codex/config.toml
model = "gpt-5.5"
model_provider = "wanapis"

[model_providers.wanapis]
name = "WanAPIs"
base_url = "https://api.wanapis.com/v1"
wire_api = "responses"
env_key = "WANAPIS_API_KEY"

Claude Code VS Code extension

Install Claude Code from the VS Code extension marketplace. The key isn't entering a URL in the extension; first confirm that claude in your terminal already connects to WanAPIs. The extension reuses your local ~/.claude config. Restart VS Code after changing the config.

Claude Code extension checklist

CLI checkRunning claude in the terminal works
Env varsANTHROPIC_BASE_URL / ANTHROPIC_AUTH_TOKEN
Config dir~/.claude/settings.json / config.json
Common actionRestart VS Code after changing config

Cline (formerly Claude Dev, recommended)

Open the Cline sidebar, click the settings gear, choose OpenAI Compatible as the provider, then fill in Base URL, API Key and Model ID.

Cline settings panel

API ProviderOpenAI Compatible
Base URLhttps://api.wanapis.com/v1
API Keysk-xxx
Model IDclaude-opus-4-7
VerifyClick Verify or start a conversation
Cline settings
API Provider: OpenAI Compatible
Base URL: https://api.wanapis.com/v1
API Key:  sk-xxx
Model:    claude-opus-4-7
# You can also use gpt-5.5 / gemini-3.5-flash / deepseek-v4-pro

Continue

Continue currently recommends YAML config. Open the config file in Continue's settings and add a models entry with provider: openai, then point apiBase at WanAPIs.

~/.continue/config.yaml
name: WanAPIs
version: 0.0.1
schema: v1

models:
  - name: WanAPIs Claude Opus 4.7
    provider: openai
    model: claude-opus-4-7
    apiBase: https://api.wanapis.com/v1
    apiKey: sk-xxx
    roles:
      - chat
      - edit
      - apply

Roo Code

Open Roo Code's sidebar settings and choose OpenAI Compatible as the API Provider. Roo Code's docs note you need to fill in Base URL, API Key and Model ID here; if a model doesn't support tool calling, switch to one that does.

Roo Code settings panel

API ProviderOpenAI Compatible
Base URLhttps://api.wanapis.com/v1
API Keysk-xxx
Modelgpt-5.5 / claude-opus-4-7
NotePrefer a model that supports tool calling

6. Desktop clients / browser extensions

General setup: choose OpenAI Compatible as the provider, set Base URL to https://api.wanapis.com/v1 and API Key to sk-xxx.
  • CherryStudio: a popular desktop LLM client, good for switching between providers.
  • ChatBox: cross-platform desktop client, simple to set up.
  • NextChat / ChatGPT-Next-Web: web and desktop, supports self-hosting.
  • LobeChat: web client with a plugin ecosystem.
  • Page Assist / Sider: browser-extension sidebar LLMs.

Async tasks

For images, video and other long-running jobs, use the async task endpoints or the console's task feature to avoid public-gateway timeouts. After creating a task, poll its status by task ID, or configure a callback URL to receive the result.

Submit an image task
POST /v1/images/gpt-image-2/generation

# Model goes in the URL path; body is the same as the sync endpoint
# {"prompt": "...", "size": "1024x1024", "image_urls": [...]}
# Returns immediately: {"data":[{"status":"submitted","task_id":"task_xxx"}]}
Submit a video task
POST /v1/video/generations

# Put the model name in the request body's model field (OpenAI-compatible)
# {"model": "seedance-2.0", ...}
Query task / download result
# Image tasks: poll the generic task endpoint
GET /v1/tasks/{task_id}

# status is upper-case: NOT_START | SUBMITTED | QUEUED | IN_PROGRESS | SUCCESS | FAILURE
# When done, images are in data.result.image_urls (array; may be data URL/base64)

# Video tasks: use the video-specific endpoint
GET /v1/video/generations/{task_id}   # URL in data.result_url (a flat string)

Long-task tips

Video generation, image editing and Midjourney-style tasks usually take a while. Save the task id and handle the QUEUED, IN_PROGRESS, SUCCESS and FAILURE states separately - note the values are upper-case.

Image generation

Image generation uses the OpenAI-compatible synchronous endpoint POST /v1/images/generations; the model name goes in the request body's model field. gpt-image-2 takes a prompt to generate; add an image_urls to do image-to-image (editing). The response is synchronous, with the image in data[0].b64_json (base64 PNG).

Some models are async-only

Seedream, Flux, Imagen, Qwen Image, WAN, Z-Image, Midjourney and the official-channel (-official) models are async-only. Calling the synchronous /v1/images/generations endpoint returns a 400 telling you to switch. That is deliberate: the sync path would only ever return a task envelope, not an image. See the full list and usage in Async-only models at the end of this section.

Sync vs async (Official)

The gpt-image-2 above is synchronous (returns base64) but capped at ~1.5MP total. For true 1K / 2K / 4K resolution, more aspect ratios, and timeout-proof async jobs, use the official-channel model gpt-image-2-official — see “Official · async HD” at the end of this section.

gpt-image-2

General image model: text-to-image + image-to-image (editing); up to 16 reference images.

flux / imagen / seedream

For other image models, refer to what the marketplace shows.

ParameterTypeRequiredDescription
modelstringYesFixed: gpt-image-2.
promptstringYesImage description or edit instruction; Chinese or English.
image_urlsstring[]NoReference images for image-to-image: public URLs or base64 data URLs (mixable), up to 16.
sizestringNoPixel WxH sets only the aspect ratio (e.g. 1024x1024 square, 1536x1024 landscape); ratio strings like 16:9 are not recognized. Total output is fixed at ~1.5MP (~1254×1254); larger sizes / 4k do not yield more pixels.
nintegerNoNumber of images, default 1.
Text-to-image
curl https://api.wanapis.com/v1/images/generations \
  -H "Authorization: Bearer $WANAPIS_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "gpt-image-2",
    "prompt": "An orange cat on a windowsill at sunset, watercolor style",
    "size": "1024x1024"
  }'

For image-to-image (editing), use the same endpoint and add image_urls with your reference image (a public URL or a data:image/png;base64,... data URL; multiple allowed); prompt is the edit instruction.

Image-to-image (editing)
curl https://api.wanapis.com/v1/images/generations \
  -H "Authorization: Bearer $WANAPIS_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "gpt-image-2",
    "prompt": "Repaint this into a neon cyberpunk night scene, keep the cat as the subject",
    "image_urls": [
      "https://example.com/cat.png"
    ]
  }'
Response (synchronous)
{
  "created": 1783144062,
  "data": [
    { "b64_json": "iVBORw0KGgoAAAANSUhEUgAA...<base64 PNG>" }
  ]
}

Tested notes

① The image is returned as base64 in data[0].b64_json; base64-decode it to get the PNG. ② A single image takes ~40–60s, close to Cloudflare's 100s limit; for slower/larger jobs use the async task endpoint to avoid timeouts (see “Async tasks”). ③ size only takes effect in pixel format (e.g. 1536x1024); ratio format (16:9) is currently ignored.

Seedream

ByteDance's Seedream series has strong photorealism and prompt adherence. Four models are available: seedream-5-0-pro (the strongest, with 1K/2K resolution tiers), seedream-5-0-lite, seedream-4-5 and seedream-4-0.

FieldDescriptionExample
modelOne of the four. Only seedream-5-0-pro has resolution tiers; the rest have a single price.seedream-5-0-pro
promptRequired. The image description.string
sizeAspect ratio: 1:1 / 16:9 / 9:16 / 4:3 / 3:4 and more.1:1
resolutionOutput resolution. seedream-5-0-pro supports 1K / 2K, and the price follows the tier.2K
image_urlsReference images for image-to-image.["https://...jpg"]

Nano Banana

The nickname for Google's Gemini image models: strong semantic understanding, character consistency and text rendering. Available: nano-banana-pro (Gemini 3 Pro Image, supporting 1K/2K/4K) and nano-banana-2 (Gemini 3.1 Flash Image).

FieldDescriptionExample
modelnano-banana-pro (quality-first) or nano-banana-2 (speed and price first).nano-banana-pro
promptRequired. Up to about 1000 characters.string
sizeAspect ratio: auto / 1:1 / 16:9 / 9:16 / 4:3 / 3:4 / 21:9 and more.auto
resolutionOutput resolution. nano-banana-pro supports 1K / 2K / 4K, with 4K priced higher.1K
image_urlsReference images for image-to-image, up to 14, as URLs or base64.["https://...jpg"]
nNumber of images. Currently only 1 is supported.1

Midjourney

Midjourney uses the async task API: submit to POST /v1/images/tasks to get a task_id, then poll GET /v1/images/tasks/{task_id}. One generation returns four images (Midjourney's 2x2 grid is split into four URLs).

Do not use the synchronous image endpoint

Midjourney is async-only. Calling the synchronous /v1/images/generations endpoint is rejected outright with a hint to switch. That is deliberate: the sync path would return a task envelope instead of an image while still charging you.
FieldDescriptionExample
modelAlways midjourney.midjourney
promptRequired. Supports native Midjourney flags such as --ar 16:9 (ratio), --q .25 (low quality to save cost) and --niji (anime style).--ar 16:9 --q .25
image_urlsReference images for image-to-image. You can also put the image URL at the start of the prompt, the native Midjourney way.["https://...jpg"]
speedSpeed mode: relax / fast / turbo, default relax.relax
versionModel version, e.g. v8.2 / v8.1 / v7 / v6.1.v8.2
Text-to-image
curl https://api.wanapis.com/v1/images/tasks \
                -H "Authorization: Bearer $WANAPIS_API_KEY" \
                -H "Content-Type: application/json" \
                -d '{
                  "model": "midjourney",
                  "prompt": "a small red apple on a white table --ar 1:1 --q .25"
                }'
Image-to-image
curl https://api.wanapis.com/v1/images/tasks \
                -H "Authorization: Bearer $WANAPIS_API_KEY" \
                -H "Content-Type: application/json" \
                -d '{
                  "model": "midjourney",
                  "prompt": "turn this into watercolor style --ar 1:1",
                  "image_urls": ["https://example.com/source.jpg"]
                }'

GPT Image 2 Official · async HD

gpt-image-2-official is the OpenAI official-channel GPT Image 2, with 1K / 2K / 4K resolution tiers, 15 aspect ratios, up to 4 images per call and up to 16 reference images. It is an async task: submit POST /v1/images/tasks to immediately get a task_id, then poll GET /v1/images/tasks/{task_id} for the result.

Submit & poll paths

Submit POST /v1/images/tasks with the model name in the request body's model field. Poll GET /v1/images/tasks/{task_id}; once the status reaches SUCCESS, the image URLs live at data.data.data.result.images[].url[] in the response (url is an array). ⚠️ These image URLs expire after ~24h, so download and store them promptly.
FieldDescriptionExample
modelFixed: gpt-image-2-official.gpt-image-2-official
promptImage description or edit instruction, Chinese or English (required)."a starry-sky castle"
sizeAspect ratio (NOT pixels). 15 supported, e.g. 1:1 / 16:9 / 9:16 / 4:3 / 3:4.16:9
resolutionResolution tier 1k / 2k / 4k. If omitted, the upstream defaults to the lowest tier.2k
qualityQuality low / medium / high; defaults to low if omitted. Together with resolution it drives the price (see below) — higher quality costs more.low
nNumber of images, 1–4, default 1.1
image_urlsReference images for image-to-image / editing: public URLs or base64 data URLs, up to 16.["https://...png"]
Submit (text-to-image)
curl https://api.wanapis.com/v1/images/tasks \
  -H "Authorization: Bearer $WANAPIS_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "gpt-image-2-official",
    "prompt": "An ancient castle beneath a starry sky, cinematic",
    "size": "16:9",
    "resolution": "2k",
    "quality": "low"
  }'
Poll task
curl https://api.wanapis.com/v1/images/tasks/task_xxxxxxxxxxxxxxxxxxxxxxxxxx \
  -H "Authorization: Bearer $WANAPIS_API_KEY"
completed result
{
  "code": "success",
  "data": {
    "task_id": "task_xxxxxxxxxxxxxxxxxxxxxxxxxx",
    "status": "SUCCESS",
    "progress": "100%",
    "data": {
      "code": 200,
      "data": {
        "status": "completed",
        "result": {
          "images": [
            {
              "url": ["https://.../image.png"],
              "expires_at": 1784819826
            }
          ]
        }
      }
    }
  }
}

Billing & notes

Billed by quality × resolution, and the spread is large: low quality + low resolution (low / 1k) is cheapest, high quality 4K (high / 4k) the most expensive — see the model marketplace for exact prices. While the status is SUBMITTED / IN_PROGRESS, poll every 3 to 5 seconds; it usually completes in 20 to 60 seconds. For image-to-image, add image_urls (publicly accessible HTTPS image URLs so the upstream can fetch them).

GPT Image 2.5 · tiered HD

GPT Image 2.5 comes in two variants: gpt-image-2.5-flare for fast everyday generation and gpt-image-2.5-sunburst for higher editing precision. Both are async tasks: submit POST /v1/images/tasks and poll GET /v1/images/tasks/{task_id}. Both accept reference images.

FieldDescriptionExample
modelRequired. Either variant.gpt-image-2.5-flare
promptRequired. The description of the image.a white ceramic mug
qualityQuality tier; it drives the price directly, see the table below. Omitting it is the same as low.low
resolutionResolution tier 1k / 2k / 4k, multiplied with quality for pricing. Omitting it is the same as 1k.1k
sizeAspect ratio such as 1:1, 16:9 or 3:2.1:1
image_urlsReference images; providing them switches to image-to-image editing.["https://.../a.jpg"]
nNumber of images, default 1, billed per image.1

Price multiplies across tiers, and the spread is large

Taking low + 1k as the 1x baseline: quality medium is 2.25x, high 9x, xhigh 16x and max 36x, while resolution 2k is 2x and 4k 3.4x, and the two multiply. So max + 4k lands around 122x the baseline. Check your tier before running a batch, and see the model marketplace for exact prices.
Submit (cheapest tier by default)
curl https://api.wanapis.com/v1/images/tasks \
  -H "Authorization: Bearer $WANAPIS_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "gpt-image-2.5-flare",
    "prompt": "a plain white ceramic mug on a white table, product photo",
    "size": "1:1",
    "quality": "low",
    "resolution": "1k"
  }'
Editing (with a reference image)
curl https://api.wanapis.com/v1/images/tasks \
  -H "Authorization: Bearer $WANAPIS_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "gpt-image-2.5-sunburst",
    "prompt": "replace the background with a clean white studio",
    "image_urls": ["https://example.com/source.jpg"],
    "quality": "low"
  }'
# Use sunburst for editing. Polling works the same as the other async models,
# and result URLs expire after about 24 hours.

Async-only models

The image models below only expose an async task API upstream. Always submit with POST /v1/images/tasks and poll GET /v1/images/tasks/{task_id}. Do not use /v1/images/generations.

FieldDescriptionExample
SeedreamPoster and product-photography style; Lite and Pro tiers.seedream-5-0-lite / seedream-5-0-pro
FluxThe FLUX.2 family, including Kontext for image editing.flux-2-pro / flux-kontext-pro
ImagenGoogle Imagen 4.imagen-4.0-apimart
Qwen ImageQwen image generation; the Pro tier has finer detail.qwen-image-2.0 / qwen-image-2.0-pro
WANWAN 2.7 image models; the Pro tier renders at higher resolution.wan2.7-image / wan2.7-image-pro
Z-ImageLightweight and fast, the cheapest tier.z-image-turbo
MidjourneyReturns four images per generation; see the Midjourney subsection above for its parameters.midjourney
OfficialOpenAI official channel with 1K / 2K / 4K support; see the subsection above for its parameters.gpt-image-2-official

Request parameters

Apart from Midjourney and the Official models, which have their own parameters, the models above share one common set of fields:

FieldDescriptionExample
modelRequired. The model name, from the table above.qwen-image-2.0
promptRequired. The description of the image, in any language. Leaving it empty returns a 400.a white ceramic mug
sizeOptional. Controls the frame. Support for pixel format versus ratio format varies by model — see the table below.16:9
image_urlsOptional. Reference images; providing them switches to image-to-image, rewriting the source per your prompt while keeping the subject and composition. Accepts public HTTPS image URLs or inline data:image/png;base64,... images.["https://.../a.jpg"]
nOptional. Number of images, default 1. Billed per image: n=2 costs twice as much and returns two URLs.1

How size actually behaves

Upstreams do not handle size consistently. The following is measured behaviour; omitting size falls back to each model's default:

FieldDescriptionExample
Qwen ImageBoth formats work. Pixel format renders at exactly the size you ask for, and ratio format is accepted too. Default 1024x1024.1280x720 → 1280×720 / 16:9 → 1280×720
SeedreamOnly ratio format is honoured; pixel format is ignored and falls back to the default 2048x2048. Pass a ratio such as 16:9 to change the frame.16:9 → 2848×1600 / 1792x1024 → 2048×2048
Other modelsFor Flux / Imagen / WAN / Z-Image, prefer ratio format and trust the dimensions of the image you actually get back.16:9

quality and resolution do nothing for these models

Only the Official (-official) models have quality / resolution tiers and are priced by tier. The upstreams behind the models above ignore both fields: passing quality: "high" changes neither the image nor the price, so there is no reason to send it. Use size to change the frame instead.

If your key restricts models, allow the model for polling too

If your key has a model allow-list enabled, polling GET /v1/images/tasks/{task_id} resolves the model name recorded on the task itself. So as long as the model you submitted with is on the allow-list, polling works with no extra configuration. If you still get a 403, check that you are submitting and polling with the same key.
Text-to-image
curl https://api.wanapis.com/v1/images/tasks \
  -H "Authorization: Bearer $WANAPIS_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "qwen-image-2.0",
    "prompt": "a plain white ceramic mug on a white table, product photo",
    "size": "16:9"
  }'
# => {"code":"success","data":{"status":"submitted","task_id":"task_xxx"}}
Image-to-image / reference image
curl https://api.wanapis.com/v1/images/tasks \
  -H "Authorization: Bearer $WANAPIS_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "qwen-image-2.0",
    "prompt": "turn this photo into a watercolor painting",
    "image_urls": ["https://example.com/source.jpg"]
  }'
# The reference image must be reachable from the public internet; inline
# data:image/png;base64,... images work too.
# For editing tasks, flux-kontext-pro stays closer to the source image.
Poll for the result
curl https://api.wanapis.com/v1/images/tasks/task_xxx \
  -H "Authorization: Bearer $WANAPIS_API_KEY"
# Poll every 3-5 seconds; most jobs finish in 10-30 seconds.
# Once status is SUCCESS, image URLs live at data.data.data.result.images[].url[]
# Those URLs expire after ~24h, so download and store them promptly.

Video generation

Video generation lives under the video capability category, with per-model setup guides for Seedance 2.5/2.0, Veo 3.1, Kling, Vidu Q3, HappyHorse and more. All video models use async task mode by default: submit POST /v1/video/generations (model name in the request body's model field), then poll for the task result.

Seedance 2.0

ByteDance Doubao video generation: text-to-video, image-to-video, first/last frame and reference assets.

Veo 3.1

Google. 4K/60fps with synced audio in one pass, the most polished output. Three tiers: quality / fast / lite.

MiniMax H3

Hailuo 03. Every clip carries a native audio track, and it accepts up to 9 images, 3 video clips and 3 audio clips as references. 480P to 4K.

Kling

Kuaishou. The most natural human motion. Two generations (v3, v2-6) with pro / sound tiers.

Vidu Q3

Shengshu. Good value, with pro / turbo / mix variants.

HappyHorse 1.0

Alibaba ATH, released April 2026, ranks near the top overall.

Grok Video

xAI. Fixed 6-second clips at the lowest price.

All video models and parameters

The table below lists the video models currently on sale. They all use the same async endpoint POST /v1/video/generations; only the model name and the supported parameter tiers differ. Prices follow the model marketplace, where per-second models show a price for each resolution.

FieldDescriptionExample
seedance-2.5ByteDance's latest generation. 480p / 720p / 1080p, 4-15s, best quality and consistency.per second
seedance-2.0Standard version, quality-first. 480p / 720p / 1080p, 4-15s.per second
seedance-2.0-fastFast version for drafts and batch previews.per second
seedance-2.0-miniLightweight and cheapest, good for high-volume drafts.per second
veo3.1-qualityGoogle Veo 3.1 quality tier, supports 4K and synced audio.per call
veo3.1-fastVeo 3.1 fast tier.per call
veo3.1-liteVeo 3.1 lite tier, the cheapest.per call
minimax-h3MiniMax Hailuo 03. 768P / 2K, native audio track, text-to-video and single-image-to-video. Uses size / seconds.per second
minimax-h3-maxfal's post-trained variant with stronger prompt adherence. 480P / 768P only, and image-to-video / reference-to-video only.per second
kling-v3Kuaishou Kling v3, natural human motion, with pro / sound / 4k tiers.per second
kling-v2-6Kling 2.6, the value tier.per second
viduq3Shengshu Vidu Q3, with pro / turbo / mix variants. 540p / 720p / 1080p.per second
happyhorse-1.0Alibaba ATH, released April 2026. 720p / 1080p.per second
grok-videoxAI Grok, 6 seconds only, at the lowest price. Duration is required (seconds or duration, and the value must be 6); omitting it gets a 400 from the upstream.per second
grok-imagine-videoxAI Grok's proper video model and a step up from grok-video: any length from 1 to 15 seconds, selectable 480P/720P, a native audio track, and image-to-video support.per second
grok-imagine-video-1.5xAI's newest video model (Aurora-2). Everything grok-imagine-video does, plus 1080P, with audio generated in the same pass as the picture. Priced by resolution tier.per second

Two parameter styles - send both to be safe

Upstreams differ in where they read parameters: some read the top-level resolution and duration, others read metadata.resolution plus the top-level seconds. A single model may be served by more than one upstream, so the safest approach is to send both; extra fields are ignored rather than rejected. Defaults are 720p and 5 seconds.

Kling

Kuaishou's Kling has the most natural human motion. Note its parameters differ from Seedance: quality is selected with mode (not resolution), and the aspect ratio uses aspect_ratio (not size).

FieldDescriptionExample
modelkling-v3 or kling-v2-6.kling-v3
promptRequired. The video prompt.string
negative_promptNegative prompt to exclude unwanted elements.string
modeQuality tier: std / pro / 4k. Price rises with the tier.std
durationDuration in seconds, 3-15, default 5.5
aspect_ratioAspect ratio: 16:9 / 9:16 / 1:1, default 16:9.16:9
image_urlsReference images for image-to-video.["https://...jpg"]
audioWhether to generate synced audio, default false.false
multi_shotMulti-shot mode, used with shot_type and multi_prompt.false
watermarkWhether to add a watermark.false
Text-to-video
curl https://api.wanapis.com/v1/video/generations \
  -H "Authorization: Bearer $WANAPIS_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "kling-v3",
    "prompt": "a cat walking through a neon-lit alley, cinematic",
    "mode": "pro",
    "duration": 5,
    "aspect_ratio": "16:9"
  }'

Veo 3.1

Google Veo 3.1 supports 4K and synced audio in one pass, with the most polished output. Three tiers map to three model names: veo3.1-quality / veo3.1-fast / veo3.1-lite. These three are billed per call (not per second), so duration does not change the unit price.

FieldDescriptionExample
modelveo3.1-quality / veo3.1-fast / veo3.1-lite.veo3.1-fast
promptRequired. The video prompt.string
resolutionOutput resolution: 720p / 1080p / 4k; price rises accordingly.1080p
durationDuration in seconds. Billed per call, so duration does not change the unit price.5
image_urlsReference images for image-to-video.["https://...jpg"]

MiniMax H3 (Hailuo 03)

MiniMax Hailuo 03 renders a native audio track with every clip. Two model names: minimax-h3 (768P / 2K, text-to-video, and single opening-frame image) and minimax-h3-max (fal's post-trained variant, with stronger prompt adherence and better aesthetics, but only 480P / 768P and it always needs an image or reference assets).

The two models take different parameters - do not mix them

They run on different upstreams: minimax-h3 takes size and seconds (pixel size + seconds); minimax-h3-max takes resolution, duration and aspect_ratio. A wrong parameter name is silently ignored and you fall back to the default tier, so follow the table for the model you are calling. 2K costs about 1.67x per second versus 768P, and takes noticeably longer to render (measured on a 4s clip: 768P about 20s, 2K about 60s).

Parameters for minimax-h3

FieldDescriptionExample
modelAlways minimax-h3.minimax-h3
promptRequired. The video prompt.string
sizeA tier + orientation selector, not the exact pixel size of the clip. 768P: 1280x720 (landscape) / 720x1280 (portrait); 2K: 1792x1024 (landscape) / 1024x1792 (portrait). Measured: landscape clips come back at 1344x768 (768P) and 2560x1440 (2K) - the model renders at its own native size, so it will not exactly match what you asked for. Read the real dimensions off the file before post-processing.1280x720
secondsDuration in seconds, as a string. Billed per second, so duration drives the price directly."4"
input_referenceOptional. The opening frame; supplying this field selects image-to-video. It must be written as an object (see the example below) - a bare string is rejected by the upstream with invalid_value. The output size still follows size and does not adopt the input image's aspect ratio (measured: a 1400x944 input with size=1280x720 still returned 1344x768).{ image_url }

input_reference must be an object for image-to-video

Put the opening frame in input_reference, and it must be the object form {"image_url": "https://..."}; a bare URL string is rejected by the upstream with invalid_value. For last-frame transitions, multiple reference images, reference video or reference audio, use minimax-h3-max instead. Also note that minimax-h3 has no 480P or 4K tier.

Parameters for minimax-h3-max

FieldDescriptionExample
modelAlways minimax-h3-max.minimax-h3-max
promptRequired. The video prompt. When using references, cite them in the prompt in the order they are supplied.string
resolution480P / 768P only. Case-insensitive, so 480p works too.768P
durationDuration in seconds, 5-15, default 5. Billed per second.5
aspect_ratioAspect ratio: 21:9 / 16:9 / 4:3 / 1:1 / 3:4 / 9:16, default 16:9. Ignored for image-to-video, where the aspect ratio follows the input image.16:9
image_urlThe opening frame for image-to-video. Supplying this field selects image-to-video.https://...jpg
end_image_urlThe last frame, paired with image_url to render a transition between the two images.https://...jpg
reference_image_urlsReference images, up to 9, used to lock subject and style.["https://...jpg"]
reference_video_urlsReference video clips, up to 3, used as motion references.["https://...mp4"]
reference_audio_urlsReference audio clips, up to 3.["https://...mp3"]
prompt_expansion_modeHow much effort goes into rewriting the prompt: fast / balanced / quality, default balanced.balanced
seedRandom seed, for reproducing the same result.int
Text-to-video (minimax-h3)
curl https://api.wanapis.com/v1/video/generations \
  -H "Authorization: Bearer $WANAPIS_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "minimax-h3",
    "prompt": "a white kitten chases a butterfly across a sunlit garden, gentle camera tracking",
    "size": "1280x720",
    "seconds": "4"
  }'
Image-to-video (minimax-h3, single opening frame)
curl https://api.wanapis.com/v1/video/generations \
  -H "Authorization: Bearer $WANAPIS_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "minimax-h3",
    "prompt": "the camera slowly pushes in, petals drifting past",
    "input_reference": {"image_url": "https://example.com/first.jpg"},
    "size": "1280x720",
    "seconds": "4"
  }'
Image-to-video / first-last frame transition (minimax-h3-max)
curl https://api.wanapis.com/v1/video/generations \
  -H "Authorization: Bearer $WANAPIS_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "minimax-h3-max",
    "prompt": "slow cinematic push in",
    "image_url": "https://example.com/first.jpg",
    "end_image_url": "https://example.com/last.jpg",
    "resolution": "768P",
    "duration": 5
  }'
Reference-to-video (images + video + audio, minimax-h3-max only)
curl https://api.wanapis.com/v1/video/generations \
  -H "Authorization: Bearer $WANAPIS_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "minimax-h3-max",
    "prompt": "the character in image 1 walks through the alley in image 2, moving like the clip",
    "reference_image_urls": ["https://example.com/character.jpg", "https://example.com/alley.jpg"],
    "reference_video_urls": ["https://example.com/motion.mp4"],
    "resolution": "768P",
    "duration": 10
  }'

Vidu Q3 / HappyHorse / Grok Video

FieldDescriptionExample
viduq3Shengshu. Resolutions 540p / 720p / 1080p, with viduq3-pro (higher quality), viduq3-turbo (cheaper) and viduq3-mix variants.per second
happyhorse-1.0Alibaba ATH, released April 2026. Supports 720p / 1080p.per second
grok-videoxAI. 6 seconds only, at the lowest price, and it does support image-to-video. Duration is required: pass either seconds: "6" (string) or duration: 6 (number) - both work, but omitting both gets a 400 duration required from the upstream. Reference images go in reference_images (an array of URLs); note it does not accept input_reference and will 400 on it. size is not honoured: text-to-video comes back 720x405 and image-to-video 1280x720.per second
grok-imagine-videoxAI Grok's proper video model. Length 1-15 seconds (14 steps); resolution takes 480p / 720p and is actually honoured (measured: 480p returns 848x480); ratios 1:1 / 16:9 / 9:16 / 3:2 / 4:3 / 3:4 / 2:3, and clips carry a native audio track. Image-to-video uses reference_images here too. Pass the duration explicitly: leave it out and the upstream defaults to 8 seconds and bills for 8.per second
grok-imagine-video-1.5xAI's newest video model (Aurora-2). Length 1-15 seconds; resolution takes 480p / 720p / 1080p and all three are real (measured: 848x480, 1280x720 and 1920x1088 respectively), each with an aac audio track. Image-to-video uses reference_images here too. Billing is tiered by resolution: 480p is the base, 720p costs 1.25x and 1080p 1.875x, then multiplied by duration. Pass the duration explicitly - leave it out and the upstream defaults to 8 seconds and bills for 8.per second

grok-video needs the duration spelled out

It only renders 6-second clips, but the duration is still required: the upstream will not default it for you. seconds takes a string and duration takes a number; either works, but leaving both out returns 400 duration required. For image-to-video pass reference_images (an array of publicly reachable HTTPS image URLs); input_reference - the Sora-style field - is rejected with a 400 here. It is also a web-proxy upstream and occasionally fails with grok auth failed; those failures are refunded automatically, so just retry.
grok-video, 6-second clip
curl https://api.wanapis.com/v1/video/generations \
  -H "Authorization: Bearer $WANAPIS_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "grok-video",
    "prompt": "a paper plane glides over a neon city at night",
    "seconds": "6"
  }'
grok-video image-to-video (reference image)
curl https://api.wanapis.com/v1/video/generations \
  -H "Authorization: Bearer $WANAPIS_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "grok-video",
    "prompt": "slow cinematic push in",
    "seconds": "6",
    "reference_images": ["https://example.com/first.jpg"]
  }'
grok-imagine-video (choose length and resolution, with audio)
curl https://api.wanapis.com/v1/video/generations \
  -H "Authorization: Bearer $WANAPIS_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "grok-imagine-video",
    "prompt": "a paper plane glides over a neon city at night",
    "duration": 6,
    "resolution": "720p"
  }'
grok-imagine-video-1.5 (1080P, image-to-video)
curl https://api.wanapis.com/v1/video/generations \
  -H "Authorization: Bearer $WANAPIS_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "grok-imagine-video-1.5",
    "prompt": "slow cinematic push in",
    "duration": 6,
    "resolution": "1080p",
    "reference_images": ["https://example.com/first.jpg"]
  }'

Task status and result

All video models share the same task state machine. Submitting returns a task_id immediately; then poll until it reaches a terminal state.

FieldDescriptionExample
data.statusUpper-case enum: NOT_START / QUEUED / IN_PROGRESS / SUCCESS / FAILURE. Note these are upper-case, not lower-case values like completed.SUCCESS
data.result_urlThe video URL - a flat string field, neither an array nor nested under metadata. Reading the wrong field typically looks like the task being stuck in processing forever when it actually finished upstream.https://.../content
data.progressProgress - a string including the percent sign, not a number."100%"
data.fail_reasonFailure reason as a string; an empty string when the task succeeded.string
data.submit_time / start_time / finish_timeSubmit / start / finish timestamps in seconds; subtract them to get queue time and render time.1790087400
data.quotaQuota charged for this task; divide by 500000 for the amount in CNY.234000
data.dataThe raw upstream response passed through as-is. Fields vary by model; look here when debugging.object

Video links expire in about 24 hours

Video URLs in the completed result are upstream-hosted and expire after roughly 24 hours (see expires_at). Re-host them in your own storage right after you receive the result if you need them long-term.

Seedance 2.0

Seedance 2.0 is ByteDance's Doubao video generation model, suited to text-to-video, image-to-video, first/last-frame transitions and reference-driven video tasks. WanAPIs wraps these long-running calls in an async task API: submitting a task returns a task_id immediately, then you poll /v1/video/generations/{task_id} for the result.

Submit path (OpenAI-compatible)

The WanAPIs video submit endpoint is POST /v1/video/generations (singular video), with the model name in the request body's model field, not the URL. Poll GET /v1/video/generations/{task_id}; when done, download the video via GET /v1/videos/{task_id}/content.

Request parameter conventions (important)

Put resolution, ratio, first/last-frame and reference-asset parameters inside the metadata object (resolution / ratio / content / generate_audio); use the top-level seconds for duration (a string, e.g. "5"), and for simple image-to-video you can pass reference images via the top-level images. Putting resolution at the top level is ignored and falls back to the default 720p. Use the metadata.content array for first/last frames, each item carrying a role (first_frame / last_frame / reference_image).

seedance-2.5

Latest generation with the best quality and consistency; the priciest per second.

seedance-2.0

Standard version, quality-first, suited to production assets.

seedance-2.0-fast

Fast version, good for drafts, batch previews and low-latency scenarios.

seedance-2.0-mini

Lightweight and cheapest, good for high-volume drafts.

Text-to-video
curl https://api.wanapis.com/v1/video/generations \
  -H "Authorization: Bearer $WANAPIS_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "seedance-2.0",
    "prompt": "An orange cat stretches by the window at dawn, slow push-in, soft natural light, cinematic",
    "seconds": "5",
    "metadata": {
      "resolution": "720p",
      "ratio": "16:9",
      "generate_audio": true
    }
  }'
Image-to-video
curl https://api.wanapis.com/v1/video/generations \
  -H "Authorization: Bearer $WANAPIS_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "seedance-2.0-fast",
    "prompt": "Have the person in the photo turn naturally toward the camera, breeze moving their hair, background stays consistent",
    "images": ["https://example.com/portrait.jpg"],
    "seconds": "5",
    "metadata": {
      "resolution": "720p",
      "ratio": "adaptive"
    }
  }'
First/last-frame transition
curl https://api.wanapis.com/v1/video/generations \
  -H "Authorization: Bearer $WANAPIS_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "seedance-2.0",
    "prompt": "Smoothly transition from a daytime city street to a neon-lit night street, camera moving forward",
    "seconds": "5",
    "metadata": {
      "resolution": "720p",
      "ratio": "16:9",
      "content": [
        {"type": "image_url", "role": "first_frame", "image_url": {"url": "https://example.com/day.jpg"}},
        {"type": "image_url", "role": "last_frame", "image_url": {"url": "https://example.com/night.jpg"}}
      ]
    }
  }'
FieldDescriptionExample
promptVideo prompt. Describe the subject, action, scene, camera, style and constraints."cinematic dolly-in"
secondsVideo duration in seconds, top-level field, a string. Commonly "5" / "10"; the actual upper limit depends on the model's response."5"
imagesReference images for image-to-video (top-level array). Usually one image; without a role it defaults to the first frame / reference image.["https://...jpg"]
metadata.resolutionOutput resolution, inside metadata. 480p / 720p / 1080p; refer to the marketplace and the upstream response.720p
metadata.ratioVideo ratio (metadata). Commonly 16:9, 9:16, 1:1; image-to-video can also use adaptive.16:9
metadata.contentArray of first/last frames and reference assets (metadata); each item has type=image_url and a role: first_frame / last_frame / reference_image.first_frame
metadata.generate_audioWhether to generate synced audio (metadata). Enabling it may take longer.true
metadata.return_last_frameWhether to return the last frame (metadata), handy for continuous shots or the first frame of the next clip.true

Submit response

response
{
  "id": "task_xxxxxxxxxxxxxxxxxxxxxxxxxx",
  "task_id": "task_xxxxxxxxxxxxxxxxxxxxxxxxxx",
  "object": "video",
  "model": "seedance-2.0",
  "status": "queued",
  "progress": 0,
  "created_at": 1780000000
}

Poll task

poll
curl https://api.wanapis.com/v1/video/generations/task_xxxxxxxxxxxxxxxxxxxxxxxxxx \
  -H "Authorization: Bearer $WANAPIS_API_KEY"
completed result
{
  "code": "success",
  "message": "",
  "data": {
    "task_id": "task_xxxxxxxxxxxxxxxxxxxxxxxxxx",
    "status": "SUCCESS",
    "progress": "100%",
    "result_url": "https://api.wanapis.com/v1/videos/task_xxxxxxxxxxxxxxxxxxxxxxxxxx/content",
    "fail_reason": "",
    "quota": 234000,
    "submit_time": 1790087400,
    "start_time": 1790087406,
    "finish_time": 1790087421,
    "properties": {
      "origin_model_name": "minimax-h3",
      "upstream_model_name": "MiniMax-H3"
    },
    "data": { "...": "上游原始响应,字段随模型而异" }
  }
}

Production tips

While the task status is QUEUED or IN_PROGRESS, poll every 5 to 10 seconds; the terminal states are SUCCESS and FAILURE (note they are upper-case). On failure, record the task id, the model name and fail_reason. For image-to-video, use publicly accessible HTTPS image URLs so the upstream can fetch the assets.

Music generation

Music generation is powered by the Suno model in async task mode: submit POST /v1/music/generations to immediately get a task_id, then poll GET /v1/music/tasks/{task_id} for the result. Each run returns 2 candidate songs with directly playable audio, cover art and lyrics.

Submit & poll paths

Submit POST /v1/music/generations with the model name in the request body's model field (currently suno). Poll GET /v1/music/tasks/{task_id}; once the status reaches SUCCESS, the songs live at data.data.data.result.music[] in the response — each carrying an audio_url (a directly playable / downloadable mp3), a cover and lyrics.

Two modes

Inspiration mode custom: false: pass a single prompt description and the model writes the lyrics and arrangement for you. Custom mode custom: true: use prompt as the lyrics, plus style for the style and title for the title. Both modes accept instrumental: true to produce an instrumental (no vocals).
Inspiration mode
curl https://api.wanapis.com/v1/music/generations \
  -H "Authorization: Bearer $WANAPIS_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "suno",
    "custom": false,
    "version": "v5",
    "prompt": "late-night city lo-fi piano with rain"
  }'
Custom mode (lyrics + style)
curl https://api.wanapis.com/v1/music/generations \
  -H "Authorization: Bearer $WANAPIS_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "suno",
    "custom": true,
    "version": "v5",
    "title": "City Lights",
    "style": "lo-fi, chill, piano",
    "prompt": "[Verse]\nNeon rain on empty streets\n[Chorus]\nCity lights ...",
    "instrumental": false
  }'
FieldDescriptionExample
modelMusic model name; currently suno.suno
versionSuno version (required). v3.5 / v4 / v4.5 / v4.5+ / v5 / v5.5; newer is higher quality.v5
customMode switch. false = inspiration (prompt only); true = custom (lyrics + style).false
promptInspiration mode = music description; custom mode = lyrics. May be empty when instrumental is true."lo-fi piano"
instrumentalWhether to produce an instrumental (no vocals); works in both modes.true
titleSong title (custom mode only)."City Lights"
styleStyle / tags (custom mode only), e.g. lo-fi, chill, piano."lo-fi, chill"
vocal_genderPreferred vocal gender (optional). male / female.female
negative_tagsNegative style tags to exclude unwanted styles (custom mode only)."heavy metal"

Submit response

response
{
  "code": "success",
  "data": {
    "task_id": "task_xxxxxxxxxxxxxxxxxxxxxxxxxx",
    "status": "submitted"
  }
}

Poll task

poll
curl https://api.wanapis.com/v1/music/tasks/task_xxxxxxxxxxxxxxxxxxxxxxxxxx \
  -H "Authorization: Bearer $WANAPIS_API_KEY"
completed result
{
  "code": "success",
  "data": {
    "task_id": "task_xxxxxxxxxxxxxxxxxxxxxxxxxx",
    "status": "SUCCESS",
    "progress": "100%",
    "data": {
      "code": 200,
      "data": {
        "status": "completed",
        "progress": 100,
        "result": {
          "music": [
            {
              "title": "City Lights",
              "audio_url": "https://.../song.mp3",
              "image_url": "https://.../cover.jpg",
              "lyrics": "[Verse] Neon rain on empty streets ...",
              "duration": 153.8,
              "tags": "lo-fi, chill, piano"
            }
          ]
        }
      }
    }
  }
}

Production tips

While the status is SUBMITTED / IN_PROGRESS, poll every 3 to 5 seconds; it usually completes in 30 to 120 seconds. audio_url is an upstream-hosted mp3 you can feed straight to an <audio> element without re-proxying. On failure the status is FAILURE, with the reason in data.fail_reason.

Billing & quota

WanAPIs bills by model ratio and actual tokens or tasks. Text models are charged for input and output separately; task-style models are usually billed per call or per spec.

FieldDescriptionExample
Input pricemodel_ratio × $2 / 1M tokensinput_tokens
Output pricemodel_ratio × completion_ratio × $2 / 1M tokensoutput_tokens
Quota unitConsole balance is deducted in real time; reconcile it in the logs$1 = 500,000 quota

Errors & retries

The API returns standard HTTP status codes. Retry a limited number of times on 429, 500, 502, 503, 504; for 400, 401, 403, surface a config or permission error directly.

FieldDescriptionExample
401API key missing or invalidCheck the Authorization header
429Rate limit or quota protection triggeredLower concurrency or switch group
503Upstream or system overloadedWait and retry with backoff

Migration

When migrating from the official OpenAI or another aggregator, you usually keep the SDK and request structure and only swap these two:

Environment variables
OPENAI_API_KEY=$WANAPIS_API_KEY
OPENAI_BASE_URL=https://api.wanapis.com/v1

Then change the model ID to one available in the WanAPIs marketplace. Before launch, make 10 to 20 requests in a low-concurrency environment to confirm the response format, token counts and charges match expectations.

Support

For channel, billing, model or response-format issues, contact support with the request time, model ID, request id and error message.