Change history
Every change to this page, newest first. Expand an entry to see what changed.
- 16 Oct 2026 · +43 −21 lines
Show changes
# Quickstart - > **TL;DR** — Sign up, copy your test key, and POST one request with an `Idempotency-Key` and an `end_user_id`. Poll the `status_url` until the run is final. + > **TL;DR** — Sign up, copy your test key, and `POST /v2/jobs` with a `model` and a `style`. Get the result by a signed webhook or by polling `GET /v2/jobs/{job_id}`. - Run your first style in three steps. Calls go from your server to `https://api.wandura.ai` with an API key. + Run your first style as a job. Calls go from your server to `https://api.wandura.ai` with an API key. ## 1. Sign up {#sign-up} ⋯ ``` - ## 3. Send your first request {#first-request} + ## 3. Pick a style {#pick-a-style} - Every submit needs an `Idempotency-Key` header and an `end_user_id` (the person in your app) in the body. + ```bash + curl "https://api.wandura.ai/v2/styles?model=wandura-video-v1" -H "Authorization: Bearer $WANDURA_API_KEY" + ``` + Each style lists its `id`, its `model` (`wandura-image-v1` or `wandura-video-v1`), the fields it takes (`inputs`, each `required` or `optional`), its `price` and a `preview_url`. The [styles catalog](https://open.wandura.ai/styles) shows the same list with previews. + + ## 4. Send your first job {#first-request} + ```bash - curl -X POST https://api.wandura.ai/v2/styles/sty_ghibli_portrait \ + curl -X POST https://api.wandura.ai/v2/jobs \ -H "Authorization: Bearer $WANDURA_API_KEY" \ -H "Content-Type: application/json" \ -H "Idempotency-Key: $(uuidgen)" \ - -d '{"lane": "priority", "end_user_id": "user_123", "inputs": {"subject": "a girl smiling at the camera"}}' + -d '{"model": "wandura-video-v1", "style": "twenty-four", "image_urls": ["https://your-bucket.example.com/u/42/photo.jpg"], "end_user_id": "user_123"}' + # HTTP 202 + # {"job_id":"run_QVqsXwr7VGSP","status":"queued","model":"wandura-video-v1","created_at":"2026-10-16T09:15:40.825Z"} ``` ⋯ ```ts - const res = await fetch('https://api.wandura.ai/v2/styles/sty_ghibli_portrait', { + const res = await fetch('https://api.wandura.ai/v2/jobs', { method: 'POST', headers: { ⋯ }, body: JSON.stringify({ - lane: 'priority', + model: 'wandura-video-v1', + style: 'twenty-four', + image_urls: ['https://your-bucket.example.com/u/42/photo.jpg'], end_user_id: 'user_123', - inputs: { subject: 'a girl smiling at the camera' }, }), }); - const run = await res.json(); - console.log(run.status, run.status_url); + const job = await res.json(); + console.log(job.job_id, job.status); ``` ⋯ res = requests.post( - "https://api.wandura.ai/v2/styles/sty_ghibli_portrait", + "https://api.wandura.ai/v2/jobs", headers={ "Authorization": f"Bearer {os.environ['WANDURA_API_KEY']}", ⋯ }, json={ - "lane": "priority", + "model": "wandura-video-v1", + "style": "twenty-four", + "image_urls": ["https://your-bucket.example.com/u/42/photo.jpg"], "end_user_id": "user_123", - "inputs": {"subject": "a girl smiling at the camera"}, }, ) - run = res.json() - print(run["status"], run["status_url"]) + job = res.json() + print(job["job_id"], job["status"]) ``` - The response is a run with `request_id`, `status_url` and `cancel_url`. Poll `status_url` or get a [signed webhook](concepts.md#webhooks) when it finishes. + - `Idempotency-Key` is optional but recommended: the same key and body never make a second job. Without it, the same body within 10 minutes is the same job. + - `end_user_id` is optional: send the person in your app and a per-person daily cap protects your wallet. + - A wrong body is refused at once with `422 INVALID_INPUT` and every problem listed (see [Validation](jobs.md#validation)). + - Test keys return a sample file for $0; live keys run for real and are charged only when the job `succeeded`. - ## Poll for the result {#poll} + ## 5. Get the result {#poll} + Add `"webhook_url": "https://your-backend.example.com/hooks/wandura"` to the submit and Wandura POSTs the signed final job there (see [Webhooks](jobs.md#webhooks)). Or poll: + ```bash - curl https://api.wandura.ai/v2/runs/run_Qk2m9XaB7Lc4 -H "Authorization: Bearer $WANDURA_API_KEY" + curl https://api.wandura.ai/v2/jobs/run_QVqsXwr7VGSP -H "Authorization: Bearer $WANDURA_API_KEY" ``` - Priority: start at **2 s**, multiply by 1.5, cap at **10 s**, add 0–0.5 s of random jitter. Relax: 10 s up to 60 s. Final statuses: `completed`, `failed`, `nsfw`, `canceled`. + Start at **2 s**, multiply by 1.5, cap at **10 s**, add 0–0.5 s of random jitter. Statuses: `queued` → `processing` → `succeeded`, `failed`, `cancelled` or `timeout` (final). A `succeeded` job has `output[0].url`; a `failed` or `timeout` job has `error` with `code` and `retryable`. + **Rolling out:** `"lane": "relax"` (cheaper or the same price, no deadline) and `"inputs": {…}` for a style's own inputs such as `keep_audio` (see [Relax lane and a style's own inputs](jobs.md#lane-and-inputs)). + + ## Runs (same engine) {#runs} + + Integrations built on runs keep working: `POST /v2/styles/{style}` with `{"lane", "end_user_id", "inputs"}` and an `Idempotency-Key` returns a run with `status_url` and `cancel_url`. Runs carry the same status words as jobs in `state`. See [Concepts](concepts.md#runs). + ## Next {#next} - - [Concepts](concepts.md): runs, lanes, free runs, webhooks, limits, idempotency, end-user ID. + - [Jobs API](jobs.md): every field, status, error, webhook and limit. + - [Concepts](concepts.md): lanes, free runs, webhooks, limits, idempotency, end-user ID. - [Styles reference](styles.md): every style with its inputs and price. - [SDKs](sdks.md): official JavaScript and Python clients, in private preview (not on npm or PyPI). ⋯
- 16 Oct 2026 · +31 −18 lines
Show changes
⋯ ``` - With the [SDKs](sdks.md): + The same call from JavaScript (Node 18+) or Python, with no Wandura package to install: ```ts - import { Wandura } from '@wandura/sdk'; - - const wandura = new Wandura(); // reads WANDURA_API_KEY - const run = await wandura.runs.createAndWait('sty_ghibli_portrait', { - lane: 'priority', - end_user_id: 'user_123', - inputs: { subject: 'a girl smiling at the camera' }, + const res = await fetch('https://api.wandura.ai/v2/styles/sty_ghibli_portrait', { + method: 'POST', + headers: { + Authorization: `Bearer ${process.env.WANDURA_API_KEY}`, + 'Content-Type': 'application/json', + 'Idempotency-Key': crypto.randomUUID(), + }, + body: JSON.stringify({ + lane: 'priority', + end_user_id: 'user_123', + inputs: { subject: 'a girl smiling at the camera' }, + }), }); - console.log(run.status, run.output?.[0]?.url); + const run = await res.json(); + console.log(run.status, run.status_url); ``` ```python - from wandura import Wandura + import os, uuid, requests - wandura = Wandura() # reads WANDURA_API_KEY - run = wandura.runs.create_and_wait("sty_ghibli_portrait", { - "lane": "priority", - "end_user_id": "user_123", - "inputs": {"subject": "a girl smiling at the camera"}, - }) - print(run["status"], run.get("output")) + res = requests.post( + "https://api.wandura.ai/v2/styles/sty_ghibli_portrait", + headers={ + "Authorization": f"Bearer {os.environ['WANDURA_API_KEY']}", + "Idempotency-Key": str(uuid.uuid4()), + }, + json={ + "lane": "priority", + "end_user_id": "user_123", + "inputs": {"subject": "a girl smiling at the camera"}, + }, + ) + run = res.json() + print(run["status"], run["status_url"]) ``` ⋯ - [Concepts](concepts.md): runs, lanes, free runs, webhooks, limits, idempotency, end-user ID. - [Styles reference](styles.md): every style with its inputs and price. - - [SDKs](sdks.md): official JavaScript and Python clients that do all of this for you. + - [SDKs](sdks.md): official JavaScript and Python clients, in private preview (not on npm or PyPI). - Building with an AI agent? Give it `https://api.wandura.ai/v2/openapi.json`.
- 14 Oct 2026 · Page created