---
title: Quickstart
description: Run your first Clipia API image generation in four steps — from creating a key to fetching the finished result.
---

To generate your first image with the Clipia API, follow four steps: create an API key in your dashboard, submit the generation with `POST /v1/models/{model}`, wait for it to finish (via a webhook or status polling), and fetch the result. The base URL is `https://api.clipia.ai`, and every request runs asynchronously through a queue.

<Steps>
<Step>
### Get an API key

Create a key in your clipia.ai dashboard: **Developer Console** (`/developer`) → **API Keys** tab → **Create key**. The full key is shown **once** — copy it somewhere safe right away.

```bash
export CLIPIA_KEY=clipia_live_xxxxxxxxxxxxxxxxxxxxxx
```

<Callout type="warn" title="The key is a server-side secret">
Never embed the key in a browser, mobile app, or public repository. Use it only from a trusted server environment.
</Callout>
</Step>

<Step>
### Submit a generation

Send `POST /v1/models/{model}` with an `input` body. Get the model slug from `GET /v1/models`. The `Idempotency-Key` header (a UUID v4) makes retries safe after network failures.

<Tabs items={['cURL', 'TypeScript', 'Python']}>
<Tab value="cURL">

```bash
curl -X POST https://api.clipia.ai/v1/models/nano-banana-2 \
  -H "Authorization: Bearer $CLIPIA_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: 8f3a1c7e-2b41-4d2a-9c0e-1200304cf45b" \
  -d '{
    "input": { "prompt": "a sunset over mountains, cinematic" },
    "webhook_url": "https://your-server.com/clipia/webhook"
  }'
```

</Tab>
<Tab value="TypeScript">

```ts
import { Clipia } from "clipia-ai";

const clipia = new Clipia({ apiKey: process.env.CLIPIA_KEY });

const request = await clipia.models.submit("nano-banana-2", {
  input: { prompt: "a sunset over mountains, cinematic" },
  webhookUrl: "https://your-server.com/clipia/webhook",
});

console.log(request.requestId, request.status);
```

</Tab>
<Tab value="Python">

```python
import os
from clipia import Clipia

clipia = Clipia(api_key=os.environ["CLIPIA_API_KEY"])

request = clipia.models.submit(
    "nano-banana-2",
    input={"prompt": "a sunset over mountains, cinematic"},
    webhook_url="https://your-server.com/clipia/webhook",
)

print(request.request_id, request.status)
```

</Tab>
</Tabs>

The response returns a `request_id` and polling URLs:

```json
{
  "request_id": "764cabcf-b745-4b3e-ae38-1200304cf45b",
  "status": "IN_QUEUE",
  "queue_position": 0,
  "status_url":   "https://api.clipia.ai/v1/requests/764cabcf-.../status",
  "response_url": "https://api.clipia.ai/v1/requests/764cabcf-...",
  "cost": 12
}
```

The `cost` field is the fixed price of the operation in **credits**, known up front. Credits are reserved on submit and only charged in full on success; on failure they are refunded entirely.
</Step>

<Step>
### Wait for completion

There are two ways to learn that a generation is ready.

**Option A — webhook (recommended).** If you pass a `webhook_url` on submit, Clipia sends a `POST` to your server when the job finishes — no polling needed. Every delivery is signed with HMAC-SHA256.

**Option B — status polling.** Periodically query the `status_url`:

<Tabs items={['cURL', 'TypeScript', 'Python']}>
<Tab value="cURL">

```bash
curl https://api.clipia.ai/v1/requests/764cabcf-.../status \
  -H "Authorization: Bearer $CLIPIA_KEY"
```

</Tab>
<Tab value="TypeScript">

```ts
const result = await clipia.requests.wait(request.requestId);
console.log(result.status); // "COMPLETED"
```

</Tab>
<Tab value="Python">

```python
result = clipia.requests.wait(request.request_id)
print(result.status)  # "COMPLETED"
```

</Tab>
</Tabs>

```json
{ "request_id": "764cabcf-...", "status": "IN_PROGRESS", "progress": 45 }
```

| Status | Meaning |
|--------|---------|
| `IN_QUEUE` | queued |
| `IN_PROGRESS` | running (`progress` 0–100) |
| `COMPLETED` | done — fetch the result |
| `FAILED` | error, credits refunded |
| `CANCELED` | canceled outside the public API (terminal status) |
</Step>

<Step>
### Fetch the result

Once `status == COMPLETED`, request the result via `response_url`:

```bash
curl https://api.clipia.ai/v1/requests/764cabcf-... \
  -H "Authorization: Bearer $CLIPIA_KEY"
```

```json
{
  "request_id": "764cabcf-...",
  "status": "COMPLETED",
  "model": "nano-banana-2",
  "output": {
    "images": [
      { "url": "https://media.clipia.ai/works/....png", "width": 1024, "height": 1024 }
    ]
  },
  "cost": 12,
  "created_at": "2026-06-01T12:00:00Z",
  "completed_at": "2026-06-01T12:00:18Z"
}
```

For video models, `output` contains `video: { url, width, height, duration }`. All media URLs point to the `media.clipia.ai` CDN.
</Step>
</Steps>

<Callout type="info" title="Next">
Want to test your integration without spending credits? Use a `clipia_test_*` key — see the "Sandbox" page. Before going live, review the "Best practices" guide.
</Callout>
