Bản lưu ngày / Snapshot of 2026-10-16 · Xem bản mới nhất / See the latest version
WanduraDocsBeta
BetaThese docs are in beta and change often. Something wrong, unclear or missing? Tell us.
Image and video API (v2)

Concepts

Markdown
On this page

TL;DR — A run is one call to one style. Priority is on time or free; Relax waits in line with no deadline and is never priced above Priority. A run that did not deliver is free. Webhooks are signed; submits are idempotent; end_user_id is required.

These concepts hold for both doors. New integrations start with the Jobs API, which uses the job words (processing, succeeded, cancelled, timeout); this page also describes runs, which stay supported.

Runs

A run is one call to one style that makes one result. You submit it, it is queued, then running, then final.

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.

A run carries its price and a charge: held while it runs, charged when it completes, released when it is free, none for test keys. Cancel a queued run with POST to its cancel_url; the hold is released.

Rate a result

Rolling out, optional. Tell Wandura whether a result was good:

curl -X POST https://api.wandura.ai/v2/runs/run_Qk2m9XaB7Lc4/feedback \
  -H "Authorization: Bearer $WANDURA_KEY" -H "Content-Type: application/json" \
  -d '{"rating": "down", "reason": "Face does not match"}'
  • rating: up or down. reason: optional, at most 280 characters.
  • The id is a run's id or a job's job_id, made with a key of the same product.
  • One rating per run per API key. Calling again replaces it.
  • The answer is the stored rating: object run_feedback, run, rating, reason, created_at, updated_at.
  • Errors: 400 invalid_request (bad rating or reason), 404 run_not_found.

Wandura reads the ratings to improve styles. They are not shown publicly, and nothing else depends on them. In the console, Runs and the Playground have the same thumbs up and down.

Styles and lanes

A style is a ready-made result (for example a portrait look or a motion clip). You never pick a model: Wandura keeps the providers behind each style and can switch them without changing your code. Each style has a schema of inputs, at /v2/public/styles/{style}/openapi.json.

Every run picks a lane:

  • Priority: done within the style's promise (shown in the styles reference) or the run is free.
  • Relax: waits in line with no deadline, one active run per end user; never priced above Priority.

POST /v2/quote takes the same body as a run and returns the price and ETA without charging.

Free runs

You never pay for a run that did not deliver. A free run ends with free_run.reason:

free_run.reason When
priority_late Priority did not finish within its promise.
provider_error The run failed on our side.
bad_input An input could not be used (for example a URL that is not http(s)).
content_blocked The input or output was blocked by the content filter (status nsfw).

Webhooks

Set one webhook URL per product in the console. Each run status change is POSTed as an event, signed:

Wandura-Signature: t=1791600000,v1=5f2b…

v1 is the hex HMAC-SHA256 of t + "." + raw body with your webhook secret. Verify it on the raw body, reject a t more than 5 minutes from now, then answer 2xx quickly. Non-2xx is retried (30 s, 2 min, 10 min, 1 h, 6 h, 24 h). Deliveries can repeat: dedupe on Wandura-Event-Id, and keep the highest sequence per run. The SDKs include a verify helper.

Event types: run.running, run.completed, run.failed, run.nsfw, run.canceled. Output links are kept 72 h.

Your product can also opt in to congestion events, queue.congestion_started and queue.congestion_ended: see Queue and congestion.

Limits

Limit Default What happens
Runs per end user per day 20 Over it: 429 end_user_cap_reached with Retry-After (resets 00:00 UTC). Your org can change its cap.
Runs at once per product 20 More runs wait in line (queued); Priority goes first. As many priority runs can wait as you have slots; past that, a new priority run gets 429 product_busy with Retry-After. Submit answers show the numbers: see Queue and congestion.
Active Relax runs per end user 1 The next Relax run of that end user starts when the last one ends.
Webhook signature window 300 s Reject a webhook whose timestamp is older or newer than this.

Need more? Tell us your volume and we raise your org's limits.

Runs at once by spend

Rolling out: spend tiers are built but not switched on yet. Until they are, every account has the default above.

Once they are on, a product on the default limit gets more runs at once as your org adds money by card. What counts is card top-ups credited in the last 28 days, minus refunds. The limit only goes up: no tier is below the default, and a limit we set for your product by agreement stays as set. The current tier table is on open.wandura.ai/pricing. Your tier, what you added and what the next tier needs show in GET /v2/queue (field spend_tier) and on the console's Limits page.

Idempotency

Every submit (POST /v2/styles/{style} or POST /v2/runs) must send an Idempotency-Key header, any unique string up to 255 characters. If the network drops and you retry with the same key and body, you get the first run back (200, header Idempotent-Replayed: true): it never runs or charges twice. The same key with a different body is 409 idempotency_key_reused. Use a new key for each new run.

End-user ID

end_user_id is required on every run: the id of the person in your app the run is for (any string you choose, up to 255 characters; do not send emails or names). Daily caps and the Relax rule count per end user, so one heavy user cannot use up your whole product. Use it in the console to answer a user's complaint.

Uploads

No storage of your own? POST /v2/uploads with {content_type, size_bytes} returns a presigned upload_url. PUT the bytes there, then pass file_url in inputs. Files are kept 24–48 hours.

API keys

Rolling out: the permission, allowed styles and tags below reach api.wandura.ai and the console with the next release.

A key belongs to one product. When you create one in the console under Keys, you can narrow it to one app or one person:

Setting What it does When a call is refused
Permission Run styles (default): submit runs and jobs, read runs and styles. Read only: read runs and styles. A Read only key that submits, cancels, shares or uploads gets 403 insufficient_scope (Jobs API: 403 FORBIDDEN). Nothing is created or charged.
Allowed styles The styles this key may run. Leave it empty for every style your org can run. Any other style gets 403 style_not_allowed on runs and quotes (Jobs API: 403 FORBIDDEN).
Tags Labels for your own sorting, for example android or a teammate's name. Never: tags change nothing.
Expires 1 day to 1 year, or never. The list shows Expires soon from 7 days before. After it: 401 api_key_expired.

If your org can run only some styles, a key's allowed styles stay inside that set. A key made without these settings works as keys always have and never gets a 403. Rotating a key keeps its settings; to change them, create a new key and revoke the old one. The key object and the key.expiring / key.revoked webhooks show preset (run_styles or read_only), allowed_styles and tags only on keys that have them.

Test and live

Test keys (wdr_test_…) return a sample result for $0 and follow the same rules (idempotency, end-user ID, webhooks), so the code you test is the code you ship. Live keys run for real.

Updated 16 Oct 2026 · Change history (7)

↑↓ selectEnter openEsc close

Send feedback

Your message goes straight to the Wandura team. It includes the address of this page.

0 / 4000