Programmatic access to every AI image & video model. Same balance as your WOWFLOW account. Bearer-token auth, JSON in / JSON out, no SDK required.
All endpoints require an API key in the Authorization header:
Authorization: Bearer wf_live_...
Generate keys in Settings → API Access. Each account can have up to 10 active keys. The secret value is shown only once at creation time — store it somewhere safe.
https://wowflow.space/api/v1
curl https://wowflow.space/api/v1/models \
-H "Authorization: Bearer $WOWFLOW_KEY"
import os, requests
r = requests.get(
"https://wowflow.space/api/v1/models",
headers={"Authorization": f"Bearer {os.environ['WOWFLOW_KEY']}"},
)
print(r.json())
const r = await fetch("https://wowflow.space/api/v1/models", {
headers: { Authorization: `Bearer ${process.env.WOWFLOW_KEY}` },
});
console.log(await r.json());
Response:
{
"data": [
{
"id": "google/nano-banana-2-pro-1k",
"name": "Nano Banana Pro 1K",
"type": "image",
"price_cents": 11,
"price_usd": 0.11,
"resolution": "1K",
"duration_sec": null
},
...
]
}
Body:
| Field | Type | Required | Description |
|---|---|---|---|
model | string | yes | id from /models |
prompt | string | yes | Text description |
input | object | no | Extra model-specific params (image refs, seed, etc.) |
curl -X POST https://wowflow.space/api/v1/generations \
-H "Authorization: Bearer $WOWFLOW_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "google/nano-banana-2-pro-1k",
"prompt": "a misty forest at dawn, soft light, cinematic"
}'
import os, requests
r = requests.post(
"https://wowflow.space/api/v1/generations",
headers={
"Authorization": f"Bearer {os.environ['WOWFLOW_KEY']}",
"Content-Type": "application/json",
},
json={
"model": "google/nano-banana-2-pro-1k",
"prompt": "a misty forest at dawn, soft light, cinematic",
},
)
gen = r.json()
print(gen["id"], gen["status"])
const r = await fetch("https://wowflow.space/api/v1/generations", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.WOWFLOW_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
model: "google/nano-banana-2-pro-1k",
prompt: "a misty forest at dawn, soft light, cinematic",
}),
});
const gen = await r.json();
console.log(gen.id, gen.status);
Response (201):
{
"id": "8c2e90b1-...",
"status": "processing",
"model": "google/nano-banana-2-pro-1k",
"cost_cents": 11,
"cost_usd": 0.11,
"created_at": "2026-05-08T14:23:11.000Z"
}
Poll every 2–5 seconds until status is completed or failed. Webhooks are coming in v2.
curl "https://wowflow.space/api/v1/generations?id=$ID" \
-H "Authorization: Bearer $WOWFLOW_KEY"
import time, os, requests
def wait_for(gen_id, timeout=300):
headers = {"Authorization": f"Bearer {os.environ['WOWFLOW_KEY']}"}
deadline = time.time() + timeout
while time.time() < deadline:
r = requests.get(
f"https://wowflow.space/api/v1/generations?id={gen_id}",
headers=headers,
).json()
if r["status"] == "completed":
return r["result_url"]
if r["status"] == "failed":
raise Exception(r.get("error") or "failed")
time.sleep(3)
raise TimeoutError("Generation timed out")
async function waitFor(id, timeoutMs = 300_000) {
const headers = { Authorization: `Bearer ${process.env.WOWFLOW_KEY}` };
const deadline = Date.now() + timeoutMs;
while (Date.now() < deadline) {
const r = await fetch(
`https://wowflow.space/api/v1/generations?id=${id}`,
{ headers }
).then(x => x.json());
if (r.status === "completed") return r.result_url;
if (r.status === "failed") throw new Error(r.error || "failed");
await new Promise(r => setTimeout(r, 3000));
}
throw new Error("Generation timed out");
}
Response when ready:
{
"id": "8c2e90b1-...",
"status": "completed",
"model": "google/nano-banana-2-pro-1k",
"result_url": "https://tempfile.aiquickdraw.com/...",
"cost_cents": 11,
"cost_usd": 0.11,
"created_at": "2026-05-08T14:23:11.000Z",
"completed_at": "2026-05-08T14:23:32.000Z"
}
Omit id to list your account's most recent generations (up to 200).
{
"balance_cents": 1234,
"balance_usd": 12.34,
"total_topup_cents": 5000,
"total_spent_cents": 3766,
"currency": "USD"
}
Returns recent spend + top-up transactions, ordered newest-first.
All errors follow this shape:
{ "error": { "code": "insufficient_balance", "message": "..." } }
| HTTP | code | Meaning |
|---|---|---|
| 400 | missing_model / missing_prompt / unknown_model | Bad request |
| 401 | missing_api_key / invalid_api_key | Auth failure |
| 402 | insufficient_balance | Top up to continue |
| 404 | not_found | Generation id doesn't belong to your account |
| 502 | upstream_error | Provider rejected the request (you were refunded) |
This is v1. Breaking changes will be released under a new path (/api/v2/...). Additive changes — new models, new fields — may happen at any time on v1.
input.refImages as URLs in the create callQuestions? Ping @fukfaku on Telegram.