Skip to main content

Developers / Docs

Generate tattoo designs

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

Markdown version

Request

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

FieldTypeDefaultNotes
promptstring, required1 to 4000 characters.
stylestringminimalA style id from GET /styles. An unknown id answers 400.
colorbooleanfalseColor ink. Black-only styles ignore it.
background"white" or "skin"whiteskin shows the design on skin.
negativePromptstringThings to leave out, up to 1000 characters.
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

{
  "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 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.