# Generate tattoo designs

> For the complete documentation index, see [llms.txt](https://inkstudioai.com/developers/llms.txt). Every page has a markdown version: add `.md` to its URL.

Create a tattoo design from a text prompt with POST /generations, as JSON or as a stream of progress events.

## Request

`POST https://inkstudioai.com/api/v1/generations` needs an API key. Send a JSON body:

| Field | Type | Default | Notes |
| --- | --- | --- | --- |
| `prompt` | string, required | | 1 to 4000 characters. |
| `style` | string | `minimal` | A style id from `GET /styles`. An unknown id answers `400`. |
| `color` | boolean | `false` | Color ink. Black-only styles ignore it. |
| `background` | `"white"` or `"skin"` | `white` | `skin` shows the design on skin. |
| `negativePrompt` | string | | Things to leave out, up to 1000 characters. |

```bash
curl https://inkstudioai.com/api/v1/generations \
  -H "Authorization: Bearer $INKSTUDIO_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "prompt": "a fox curled inside a crescent moon",
    "style": "fine-line",
    "color": false,
    "background": "white"
  }'
```

## Response

```json
{
  "id": "6718f0c2a1b2c3d4e5f60718",
  "imageUrl": "https://cdn.inkstudioai.com/free-tattoo-designs/6718f0c2a1b2c3d4e5f60718.webp",
  "prompt": "a fox curled inside a crescent moon",
  "style": "fine-line",
  "color": false,
  "background": "white",
  "tier": "free",
  "provider": "openai",
  "model": "gpt-image-2.5-flare",
  "freeGenerationsRemaining": 0,
  "createdAt": "2026-10-24T09:00:00.000Z",
  "latencySeconds": 9.4
}
```

The design is saved privately to the design history of the account. It is not added to the public gallery. `id` is the saved design id, or `null` if the save failed (the image still exists). `freeGenerationsRemaining` is present only when `tier` is `"free"`. Style aliases from the website, for example `fineline`, `blackwork`, and `lettering`, are accepted.

## Access rules

1. An account with an active plan generates at paid quality. Plan generations use no credits. The API allows 50 generations per account per UTC day.
2. Without a plan, an account with a free generation left uses it at free quality. A new account gets one free generation.
3. Otherwise the API answers `402` with `code: "paywall"` and `pricingUrl`. See [GET /pricing](https://inkstudioai.com/developers/api-reference.md) and `POST /checkout`.

## Stream progress events

Send `Accept: text/event-stream` to get Server-Sent Events while the design is made:

- `status`: a progress message.
- `partial_image`: an early preview of the image.
- `heartbeat`: keeps the connection open.
- `complete`: the same fields as the JSON response, plus `traceId`.
- `error`: `{ "code", "message", "status", "reason", "field" }`. `reason` and `field` are optional.

Stream `error` events use the generation codes `paywall`, `moderation`, `provider`, `timeout`, `upload`, and `unknown`. `status` is the HTTP status of the matching JSON error. Errors before the stream starts (`400`, `401`, `402`, `429`, `500`) are plain JSON.

## Failures and charges

- When the image provider or the upload fails, the free generation and the daily count are given back.
- A prompt that the content check blocks answers `422` with `code: "moderation"` and never uses a generation.
- When the client closes a stream, the daily count stays used. The free generation is given back unless a partial image was already sent.

All error codes are in [Errors and limits](https://inkstudioai.com/developers/errors.md).
