# Generations (REST)

> The non-MCP path: create Kling video and Nano Banana 2 image jobs over REST, poll them to completion, list and delete them, and how credits are charged and refunded.

This is the **REST API** for generations — the non-MCP way to drive Figgshield from your own tools and scripts. In Claude or the Claude Code CLI you would use the [MCP tools](https://figgshield.ai/documentation/mcp.md) (`generate_video`, `generate_image`) instead; both paths run the same models against the same credit balance.

A generation is one video or image job. The lifecycle is asynchronous: you create a job, it moves through `queued → running`, and it ends as `succeeded` (with an `output_url`) or `failed` (credits refunded automatically).

## The generation object

```json
{
  "uuid": "0b8f6a2e-4c1d-4f7a-9b2e-6d3c8a1f5e90",
  "model": "kling-video",
  "model_name": "Kling",
  "kind": "video",
  "prompt": "A slow dolly shot across a quiet harbour at dawn",
  "params": { "duration": 5, "resolution": "720p", "audio": false, "aspect_ratio": "16:9" },
  "status": "succeeded",
  "output_url": "https://cdn.figgshield.ai/outputs/0b8f6a2e.mp4",
  "thumbnail_url": "https://cdn.figgshield.ai/thumbs/0b8f6a2e.jpg",
  "credits_charged": 35,
  "error_message": null,
  "created_at": "2026-07-06T09:00:00Z",
  "completed_at": "2026-07-06T09:00:48Z",
  "duration_ms": 48000,
  "is_watermarked": false
}
```

`status` is one of `queued`, `running`, `succeeded`, `failed`. `output_url` and `thumbnail_url` are `null` until the job succeeds; `error_message` is set only on failure. `is_watermarked` is always `false` — outputs are never watermarked.

## Create a generation

`POST /api/generations/create/`

```bash
# Kling video (35 credits)
curl https://api.figgshield.ai/api/generations/create/ \
  -X POST \
  -H "Authorization: Bearer $FIGGSHIELD_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "kling-video",
    "prompt": "A slow dolly shot across a quiet harbour at dawn",
    "params": { "duration": 5, "resolution": "720p", "audio": false }
  }'
```

```bash
# Nano Banana 2 image (8 credits)
curl https://api.figgshield.ai/api/generations/create/ \
  -X POST \
  -H "Authorization: Bearer $FIGGSHIELD_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "nano-banana-2",
    "prompt": "A paper boat on a still pond, top-down",
    "params": { "resolution": "2K" }
  }'
```

Returns `201` with the new generation (`status: "queued"`).

### Request body

| Field | Type | Notes |
| --- | --- | --- |
| `model` | string | `kling-video` or `nano-banana-2` (from [`GET /api/models/`](https://figgshield.ai/documentation/models.md)). |
| `prompt` | string | What to generate. |
| `params` | object | Optional settings; allowed keys depend on the model — see below. |

### Params by model

| Param | Applies to | Example | Notes |
| --- | --- | --- | --- |
| `duration` | Kling | `5` | 5 or 10 seconds. 10 doubles the cost. |
| `resolution` | Kling | `"720p"` | `720p` or `1080p`. |
| `audio` | Kling | `false` | Default off; `true` doubles the cost. |
| `resolution` | Nano Banana 2 | `"2K"` | `1K`, `2K` or `4K`. |
| `aspect_ratio` | both | `"16:9"` | Optional. |

Omitted params fall back to defaults. A value outside the model's schema returns `400 validation_error`.

### Credits: pre-flight check, charge, refund

- The credit cost is checked **before** dispatch. If your balance cannot cover it, the request fails with `402 insufficient_credits` and nothing is charged. Kling is 35 credits (70 for 10 seconds or with audio); Nano Banana 2 is 8.
- With [automatic top-ups](https://figgshield.ai/documentation/billing.md) enabled, the top-up runs first and the pre-flight check happens after it.
- On success the cost is recorded as `credits_charged` and appears in the [ledger](https://figgshield.ai/documentation/usage.md) as a `burn`.
- If the job **fails**, the charged credits are refunded automatically (ledger entry `refund`). You only pay for output.

### Error responses

| Status | Code | Meaning |
| --- | --- | --- |
| `400` | `validation_error` | Unknown model slug, bad prompt, or params outside the model's schema. |
| `402` | `insufficient_credits` | Balance cannot cover the cost (after any automatic top-up attempt). |
| `402` | `subscription_required` | The account has no active subscription. |
| `409` | `parallel_limit_reached` | As many jobs already in flight as your plan allows — wait for one to finish. |
| `503` | `model_unavailable` | The model is offline or its provider is not responding. Retry later. |

See [Errors](https://figgshield.ai/documentation/errors.md) for the full envelope and handling advice.

## Poll a generation

`GET /api/generations/{uuid}/` — **the polling endpoint.** Reading it refreshes the job's provider status; the backend throttles provider polls to at most one per 2 seconds per job, so poll at a **2-second interval or slower**.

```bash
while true; do
  BODY=$(curl -s "https://api.figgshield.ai/api/generations/$GENERATION_UUID/" \
    -H "Authorization: Bearer $FIGGSHIELD_API_KEY")
  STATUS=$(echo "$BODY" | jq -r .status)
  [ "$STATUS" = "succeeded" ] && { echo "$BODY" | jq -r .output_url; break; }
  [ "$STATUS" = "failed" ]    && { echo "$BODY" | jq -r .error_message >&2; exit 1; }
  sleep 2
done
```

Kling clips typically take tens of seconds; Nano Banana 2 images usually finish in seconds.

## List generations

`GET /api/generations/` — your own generations, newest first (`-created_at`), in the standard list envelope. Page through with `?page=N`.

```bash
curl "https://api.figgshield.ai/api/generations/?page=1" \
  -H "Authorization: Bearer $FIGGSHIELD_API_KEY"
```

## Delete a generation

`DELETE /api/generations/{uuid}/` — soft delete; the generation disappears from your list. Deleting does not refund credits (only failure does).

```bash
curl https://api.figgshield.ai/api/generations/$GENERATION_UUID/ \
  -X DELETE \
  -H "Authorization: Bearer $FIGGSHIELD_API_KEY"
```

Returns `204 No Content`.
