Submit a generation job, poll for the result, and manage your account — all with a single API key issued from your Sceneviz dashboard.
All requests go to https://api.opraiz.com. Every request and response is JSON (content-type: application/json), except multipart uploads.
https://api.opraiz.comEvery request (except GET /healthz) requires your API key. Send it with the x-api-key header (recommended — this is what the Sceneviz apps send). Two aliases are accepted: Authorization: Bearer sk_live_YOUR_KEY or an ?api_key= query parameter.
curl https://api.opraiz.com/api/v1/account/balance -H "x-api-key: sk_live_YOUR_KEY"| Status | Body | Meaning |
|---|---|---|
| 401 | { "detail": "Not authenticated" } | Key missing or unknown |
| 403 | { "detail": { "error": "Key is disabled" } } | Key revoked / disabled |
Keys are issued from your Sceneviz dashboard. Treat them like passwords — only the hash is stored server-side, so a lost key cannot be recovered and must be reissued.
Errors follow FastAPI-style detail shapes: a string form for auth/not-found ({ "detail": "Not found" }) and an object form for validation/limits ({ "detail": { "error": "…message…" } }). Unknown paths return 404. Authentication is checked first — an invalid key always answers 401 regardless of path.
CORS is permissive (Access-Control-Allow-Origin: *, headers x-api-key, authorization, content-type), so browser and desktop apps may call the API directly.
60 generation submits per key per 60-second window (fixed window, applies only to POST /api/v1/{model}). Result polling is not rate-limited — poll every ~2 s.
429 { "detail": { "error": "Rate limit exceeded" } }Liveness probe. No auth.
{ "ok": true, "service": "sceneviz-api" }Current credit balance for the key.
{ "balance": 500, "email": "you@example.com" }Model catalog — the live list of served models with provider, credit cost and accepted parameters per model. Always use this list for available model ids.
{
"models": [
{ "id": "sdxl-image", "modality": "image", "provider": "runpod",
"cost_credits": 2, "params": [ { "name": "prompt", "type": "string", "required": true }, … ] }
]
}Replace {model} with a live model id (images: flux-dev-image, flux-schnell-image, flux-kontext-pro-t2i, flux-kontext-max-t2i, sdxl-image; videos: Kling, Seedance and Runway ids from the catalog). Unknown ids return 501. The job is asynchronous — poll with the returned request_id.
{
"prompt": "a cinematic shot of fog over pine ridges at dawn",
"negative_prompt": "blurry, watermark",
"width": 1024,
"height": 1024,
"num_images": 1,
"seed": -1
}| Field | Type | Default | Notes |
|---|---|---|---|
| prompt | string | — | required |
| negative_prompt | string | "" | sdxl only |
| width / height | int | 1024 | BFL clamps to 256–1440, multiples of 32 |
| aspect_ratio | string | 1:1 | kontext / video models (e.g. 16:9, 9:16) |
| image_url | string | — | start frame — required for i2v, optional i2i edit for kontext |
| resolution | string | 480p | Seedance only: 480p / 720p / 1080p |
| duration | int | 5 | seconds; Kling 5/10, Seedance 2–12, Runway 2–10 |
| num_images | int | 1 | clamped to 1–2, images only (each charges separately) |
| seed | int | random | reproducibility |
Response:
{ "status": "submitted", "request_id": "c0a80101-7ab2-4c1e-9f3a-1b2c3d4e5f60" }Errors:
| Status | Body | When |
|---|---|---|
| 400 | { "detail": { "error": "Field 'prompt' is required" } } | malformed request |
| 403 | { "detail": { "error": "Insufficient credits" } } | balance below cost |
| 429 | { "detail": { "error": "Rate limit exceeded" } } | >60 submits / 60 s |
| 501 | { "detail": { "error": "Model '…' is not yet served" } } | unknown model id |
| 502 | { "detail": { "error": "Provider submit failed: …" } } | upstream provider error |
| 503 | { "detail": { "error": "GPU endpoint not provisioned yet" } } | model temporarily unavailable |
Poll every ~2 s until a terminal status arrives.
{
"status": "completed",
"request_id": "c0a80101-…",
"output": "https://…/image.png",
"outputs": ["https://…/image.png"]
}| Field | Meaning |
|---|---|
| status | completed / succeeded / success → done; failed / error / cancelled → failed; anything else → keep polling |
| output | first output URL, or null while running |
| outputs | all output URLs |
| error | present on failure, human-readable message |
Unknown request ids return 404. HTTP ≥500 is transient — retry; 4xx should abort the poll loop.
Full example:
curl -X POST https://api.opraiz.com/api/v1/sdxl-image \
-H "x-api-key: sk_live_YOUR_KEY" -H "content-type: application/json" \
-d '{"prompt":"neon koi swimming through fog","num_images":1}'Each generation debits credits from your key's balance at submit time. Images charge per output (cost × num_images); videos are one output per job. Credits are debited on successful submit; automatic refunds for failed jobs are not yet available. Check your balance any time via GET /api/v1/account/balance.
| Model | Cost (credits) | Modality |
|---|---|---|
| flux-schnell-image | 2 | image |
| sdxl-image | 2 | image |
| flux-kontext-pro-t2i | 4 | image (+ optional input-image edit) |
| flux-dev-image | 5 | image |
| flux-kontext-max-t2i | 8 | image |
| seedance-*-t2v / seedance-pro-i2v | 60 | video |
| kling-v2.1-master-t2v / -i2v | 80 | video |
| kling-v2.5-turbo-pro-t2v | 100 | video |
| runway-text-to-video / -image-to-video | 90 | video |
Credits come in three one-time packs — no subscription. Buying is a dashboard action (POST /billing/checkout requires dashboard session auth; API keys get 401). Prices shown in your local currency (approximate) at checkout.
| Pack | Credits | Price (USD) |
|---|---|---|
| starter | 10,000 | $50 |
| growth | 30,000 | $149 |
| scale | 100,000 | $499 |
The public pack list is served by GET /billing/packs (no auth) — it returns the live tiers with localized prices:
{
"currency": "MYR",
"tiers": [
{ "id": "starter", "credits": 10000, "usd": 50, "priceUSD": "$50", "localPrice": "MYR 203.51" },
{ "id": "growth", "credits": 30000, "usd": 149, "priceUSD": "$149", "localPrice": "MYR 606.45" },
{ "id": "scale", "credits": 100000, "usd": 499, "priceUSD": "$499", "localPrice": "MYR 2,030.99" }
]
}An MCP server is exposed at https://api.opraiz.com/mcp for CLI and agent integrations, authenticated with Authorization: Bearer sk_live_YOUR_KEY (streamable HTTP transport). MCP-compatible tools can register it directly once available.