# OkayPic API

One REST API for MiniMax H3, Seedance, Veo 3.1, GPT Image, Seedream and Gemini image models. Same prices as the web app; failed tasks are refunded automatically. Human-friendly docs: https://okaypic.com/api-docs

## Authentication

Create a key on https://okaypic.com/developer and send it on every request:

```
Authorization: Bearer okpk_your_api_key
```

Base URL: `https://api.okaypic.com`

## Flow: submit, then poll

1. `POST /api/video/generate` (video models) or `POST /api/image/generate` (image models) → `{ "taskId": "…", "status": "pending" }`. Some image models answer `"status": "completed"` with `resultUrls` right away.
2. `GET /api/video/tasks/{taskId}` (or `/api/image/tasks/{taskId}`) every 5–10 s until `status` is `completed` (then `resultUrls`) or `failed` (then `errorCode`, `retryable`, `errorMessage`).

```bash
curl -X POST https://api.okaypic.com/api/video/generate \
  -H "Authorization: Bearer $OKAYPIC_KEY" -H "Content-Type: application/json" \
  -d '{"model": "minimax-h3", "prompt": "A cat playing piano in a jazz club", "duration": 5, "ratio": "16:9", "resolution": "768p"}'

curl https://api.okaypic.com/api/video/tasks/TASK_ID -H "Authorization: Bearer $OKAYPIC_KEY"
```

## Request body (video)

| Field | Type | Notes |
|---|---|---|
| `model` | string | required — see Video models |
| `prompt` | string | required |
| `duration` | integer | seconds, per model |
| `ratio` | string | e.g. `16:9`, `9:16`, `1:1` (per model) |
| `resolution` | string | H3: `480p` / `768p` / `1080p`; Seedance: per version |
| `media` | array | `[{ "type": "image" \| "video" \| "audio", "url": "https://… or data URI" }]` |
| `ref_mode` | string | H3 only: `omni` / `first-last` / `okay` / `lip-sync` |
| `first_frame`, `last_frame` | string | H3 `first-last` / `okay` |
| `tier` | string | Seedance: `third-party` / `official` |
| `variant` | string | Veo 3.1: `veo3.1-fast` / `veo3.1-components` / `veo3.1-pro` |
| `client_request_id` | string | optional idempotency key (or the `Idempotency-Key` header) |

## Video models

### `minimax-h3` — MiniMax H3 (from $0.007/s)

- `duration`: 1–15 s (1080p: up to 10 s) · `ratio`: 16:9, 9:16 · `resolution`: 480p / 768p / 1080p
- `ref_mode`:
  - `omni` (default): `media` with up to 9 images and 3 audio clips; refer to them in the prompt as `<Picture 1>`, `<Audio 1>`.
  - `first-last`: `first_frame` (required) and `last_frame` (optional) image URLs; `media` is not accepted; 480p / 768p.
  - `okay`: `first_frame` / `last_frame` plus `media`, all optional — locks the opening / closing frame while still using the references. With frames and media: 480p / 768p, 5–15 s.
  - `lip-sync`: `media` with exactly 1 image and 1 audio clip; the video is as long as the audio (up to 15 s).
- `optimize_prompt` (boolean, default false): let the model expand short prompts. `seed` (integer, H3 only).

### `seedance-2.5` — Seedance 2.5 (from $0.116/s)

- `duration`: 4–30 s · `ratio`: 16:9, 9:16, 1:1 · `resolution`: 480p / 720p · `tier`: official / third-party
- `media`: images, video and audio references (up to 30 images). Reference-video seconds are billed too.

### `seedance-2.0` — Seedance 2.0 (from $0.161/s)

- `duration`: 4–15 s · `ratio`: 16:9, 9:16, 1:1 · `resolution`: 720p · `tier`: third-party
- `media`: images, video and audio references (up to 9 images). Reference-video seconds are billed too.

### `seedance-2.0-mini` — Seedance 2.0 Mini (from $0.089/s)

- `duration`: 4–15 s · `ratio`: 16:9, 9:16, 1:1 · `resolution`: 720p · `tier`: official
- `media`: images, video and audio references (up to 9 images). Reference-video seconds are billed too.

### `veo3.1` — Veo 3.1 (from $0.10 / video)

- `ratio`: 16:9, 9:16 · `variant`: `veo3.1-fast`, `veo3.1-components`, `veo3.1-pro` · up to 3 reference images in `media`

## Image models

Body: `model`, `prompt`, `ratio`, `resolution` (where listed), `images` (reference image URLs or data URIs).

- `doubao-seedream-5.0` — Seedream 5.0, $0.20 / image · `ratio`: 1:1, 16:9, 9:16, 4:3, 3:4, 3:2, 2:3, 21:9 · `resolution`: 1k / 2k / 4k · up to 6 reference `images`
- `gpt-image-2.5` — GPT Image 2.5, $0.03 / image · `ratio`: 1:1, 16:9, 9:16, 4:3, 3:4, 3:2, 2:3 · `resolution`: 1k / 2k / 4k · up to 6 reference `images`
- `nano-banana-2.1` — Nano Banana 2.1, $0.03 / image · `ratio`: 1:1, 16:9, 9:16, 4:3, 3:4, 3:2, 2:3 · up to 6 reference `images`
- `gpt-image-2` — GPT Image 2, $0.03 / image · `ratio`: 1:1, 16:9, 9:16, 4:3, 3:4, 3:2, 2:3 · up to 6 reference `images`
- `gemini-3-pro-image-preview` — Gemini 3 Pro Image, $0.03 / image · `ratio`: 1:1, 16:9, 9:16, 4:3, 3:4, 3:2, 2:3, 21:9 · up to 6 reference `images`
- `gemini-3.1-flash-image-preview` — Gemini 3.1 Flash Image, $0.02 / image · `ratio`: 1:1, 16:9, 9:16, 4:3, 3:4, 3:2, 2:3, 21:9 · up to 6 reference `images`
- `gemini-2.5-flash-image` — Gemini 2.5 Flash Image, $0.02 / image · `ratio`: 1:1, 16:9, 9:16, 4:3, 3:4, 3:2, 2:3 · up to 6 reference `images`

## Task responses

```json
{ "status": "processing", "progress": 50, "type": "video" }
{ "status": "completed", "resultUrls": ["https://okaypic.b-cdn.net/…/result_0.mp4"], "type": "video" }
{ "status": "failed", "errorCode": "content_violation", "retryable": false, "errorMessage": "…", "type": "video" }
```

| errorCode | retryable | Meaning |
|---|---|---|
| `content_violation` | false | The provider flagged the prompt or media; the same input will fail again. |
| `generation_failed` | true | The provider failed for another reason; retrying may succeed. |
| `no_result` | true | The provider reported success but returned no file. |
| `timeout` | true | No result within 6 hours. |

Failed tasks are always refunded. HTTP errors on submit: `400` invalid input, `401` bad key, `402` balance too low, `409` same idempotency key still processing, `429` too many concurrent tasks.

A `402` body is `{ "error": "Insufficient balance", "code": "insufficient_balance", "costCents": 10, "balanceCents": 3, "topUpUrl": "https://okaypic.com/billing" }`. `GET /api/balance` returns `{ "balanceCents": 4876, "topUpUrl": "https://okaypic.com/billing" }` for the key, so a client can check before a batch.

## Idempotency

Send a unique id per task as the `Idempotency-Key` header or `client_request_id` (1–255 characters). Retrying with the same id returns the original task instead of creating and billing a second one.
