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. |
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
- 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.
- Without a plan, an account with a free generation left uses it at free quality. A new account gets one free generation.
- Otherwise the API answers
402withcode: "paywall"andpricingUrl. See GET /pricing andPOST /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, plustraceId.error:{ "code", "message", "status", "reason", "field" }.reasonandfieldare 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
422withcode: "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.