# Quickstart

> **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 as a job. Calls go from your server to `https://api.wandura.ai` with an API key.

## 1. Sign up
[Sign up](https://open.wandura.ai/login) with your email. You get a personal account, a **Test** product with a test key, and a **My app** product for live runs.

## 2. Get a key
Your test key (`wdr_test_…`) is shown once when you sign up. Test keys return a sample result for **$0**, so you can build the whole integration before adding money. Live keys (`wdr_live_…`) run for real and draw from the product wallet. Keep keys on your server:

```bash
export WANDURA_API_KEY=wdr_test_...
```

## 3. Pick a style
```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
```bash
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 '{"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"}
```

The same call from JavaScript (Node 18+) or Python, with no Wandura package to install:

```ts
const res = await fetch('https://api.wandura.ai/v2/jobs', {
  method: 'POST',
  headers: {
    Authorization: `Bearer ${process.env.WANDURA_API_KEY}`,
    'Content-Type': 'application/json',
    'Idempotency-Key': crypto.randomUUID(),
  },
  body: JSON.stringify({
    model: 'wandura-video-v1',
    style: 'twenty-four',
    image_urls: ['https://your-bucket.example.com/u/42/photo.jpg'],
    end_user_id: 'user_123',
  }),
});
const job = await res.json();
console.log(job.job_id, job.status);
```

```python
import os, uuid, requests

res = requests.post(
    "https://api.wandura.ai/v2/jobs",
    headers={
        "Authorization": f"Bearer {os.environ['WANDURA_API_KEY']}",
        "Idempotency-Key": str(uuid.uuid4()),
    },
    json={
        "model": "wandura-video-v1",
        "style": "twenty-four",
        "image_urls": ["https://your-bucket.example.com/u/42/photo.jpg"],
        "end_user_id": "user_123",
    },
)
job = res.json()
print(job["job_id"], job["status"])
```

- `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](https://docs.wandura.ai/developers/api-v2/jobs#validation)).
- Test keys return a sample file for $0; live keys run for real and are charged only when the job `succeeded`.

## 5. Get the result
Add `"webhook_url": "https://your-backend.example.com/hooks/wandura"` to the submit and Wandura POSTs the signed final job there (see [Webhooks](https://docs.wandura.ai/developers/api-v2/jobs#webhooks)). Or poll:

```bash
curl https://api.wandura.ai/v2/jobs/run_QVqsXwr7VGSP -H "Authorization: Bearer $WANDURA_API_KEY"
```

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](https://docs.wandura.ai/developers/api-v2/jobs#lane-and-inputs)).

## Runs (same engine)
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](https://docs.wandura.ai/developers/api-v2/concepts#runs).

## Next
- [Jobs API](https://docs.wandura.ai/developers/api-v2/jobs): every field, status, error, webhook and limit.
- [Concepts](https://docs.wandura.ai/developers/api-v2/concepts): lanes, free runs, webhooks, limits, idempotency, end-user ID.
- [Styles reference](https://docs.wandura.ai/developers/api-v2/styles): every style with its inputs and price.
- [SDKs](https://docs.wandura.ai/developers/api-v2/sdks): 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`.
