One prompt in, one cleaned sprite out: transparent background, quantised palette, crisp 1px outline. Then iterate for free with /resize.
Returns raw image/png bytes. The result is also saved to your SpriteLab history.
| Field | Type | Notes |
|---|---|---|
| prompt | string, required | What to draw. Max 500 chars. Subject description only; the pixel art style scaffolding is added server-side |
| quality | string | epic (default, 1 credit) or mythic (6 credits, finer detail and cleaner shapes) |
| height | int | 16 to 512, default 128. Send height ONLY: the sprite is exactly this tall and width follows its natural proportions, no squishing |
| width | int | Legacy: width plus a matching height forces an exact square canvas (stretches non-square subjects). Kept for existing clients; skip it for characters |
| size_mode | string | exact (default), native or crisp. See Pixel size and cleanup |
| cleanup | string | advanced (default) or classic. See Pixel size and cleanup |
| direction | string | auto, front, left, right, back, top, angled. Default right. auto picks front for tiny sprites, side for larger. Ignored when style_reference_id is set |
| detail | int | 1 to 3 shading richness: 1 flat, 2 some shading, 3 rich detail. Default 1 |
| isometric | bool | Isometric prop: exact 2:1 angle, real-world height on the iso tileset grid. Pivot in X-SpriteLab-Pivot-X/Y |
| iso_tile | int | Isometric only: 64 (default) or 32 |
| iso_footprint | string | Isometric only: auto, 1x1, 2x1, 1x2, 2x2, 3x3 |
| iso_height | string | Isometric only: auto, short, medium, tall, very_tall or metres |
| style_notes | string | Free-text style direction appended to the prompt, e.g. "muted earthy palette, thick outline". Max 500 chars |
| style_reference_id | string | Sprite id of an earlier generation to anchor style on (see Style reference) |
| …plus any of the tuning parameters below | ||
curl:
curl -X POST https://spritelab.dev/api/v1/generate \
-H "Authorization: Bearer sl_live_YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{"prompt": "red health potion in a round glass bottle", "height": 64}' \
--output potion.png
Python:
import requests
r = requests.post(
"https://spritelab.dev/api/v1/generate",
headers={"Authorization": "Bearer sl_live_YOUR_KEY"},
json={
"prompt": "armoured knight with tower shield",
"quality": "mythic",
"height": 128,
"max_colours": 16,
"palette_lock": "pico8",
},
)
r.raise_for_status()
open("knight.png", "wb").write(r.content)
print("sprite id:", r.headers["X-SpriteLab-Sprite-Id"])
print("credits left:", r.headers["X-SpriteLab-Credits-Remaining"])
Response headers: X-SpriteLab-Sprite-Id (use it with /resize), X-SpriteLab-Credits-Remaining, and the pixel size headers below.
Every sprite is drawn on its own pixel grid. A sprite delivered at that size, or at a whole multiple of it, keeps every pixel the same size and a 1px outline. Any other height is resampled to fit, which is fine for most uses but softer up close.
| size_mode | Result |
|---|---|
| exact | Default. The sprite is exactly height tall |
| native | The model's own pixel size, the crispest result. height is ignored |
| crisp | The model's pixel size times the whole number closest to height, e.g. a 40 px drawing asked at 128 comes back at 120 |
native and crisp need height only (no width), otherwise 400 size_mode_needs_height. If a sprite has no clean pixel grid it comes back at height instead, with a scale of 0.
cleanup: advanced (default) keeps the model's own pixels, so thin lines and 1px details like eyes survive. classic is the previous cleanup, if you prefer its look or need results to match older sprites. Requests with colour tuning (contrast, saturation, brightness), palette_lock, dithering or the legacy width+height always use classic.
Response headers on /generate and /resize (the same fields are in the JSON of /convert):
| Header | Notes |
|---|---|
| X-SpriteLab-Cleanup | advanced or classic: the cleanup that ran |
| X-SpriteLab-Native-Height / -Width | The model's pixel size as a sprite size, i.e. the native result. 0 when unknown |
| X-SpriteLab-Scale | The whole-number multiple of the native size the sprite was delivered at. 0 = an exact height, not a multiple |
To get a crisp sprite at double size, generate with native, then /resize with size_mode: "crisp" and twice the native height. Free, no new generation.
curl -X POST https://spritelab.dev/api/v1/generate \
-H "Authorization: Bearer sl_live_YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{"prompt": "hooded rogue with twin daggers", "size_mode": "native"}' \
-D headers.txt --output rogue.png
Re-run the cleanup pipeline on a sprite you already generated, at new dimensions and/or with new tuning. No model call, so it's free and fast (typically under a second). This is the iteration endpoint: generate once, then resize and retune as many times as you like. Works on /generate and /convert results.
| Field | Type | Notes |
|---|---|---|
| sprite_id | string, required | From the X-SpriteLab-Sprite-Id header or the JSON id field of a previous generation. Owner-only |
| height | int | 16 to 512. Required unless size_mode is native. Height only = natural proportions; adding a matching width = legacy exact square |
| size_mode | string | exact (default), native or crisp, as on /generate |
| cleanup | string | advanced or classic. Defaults to the cleanup the sprite was made with (API sprites from before this option existed: classic, so they keep their look) |
| …plus any of the tuning parameters below | ||
curl -X POST https://spritelab.dev/api/v1/resize \
-H "Authorization: Bearer sl_live_YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{"sprite_id": "SPRITE_ID", "height": 32, "max_colours": 8}' \
--output potion_32.png
Sprites from other modes (micro, backgrounds, animation) can't go through this pipeline and return 409 not_resizable.
Rewrites a rough prompt into a richer sprite description (the same enhancement the app's prompt-improve button uses). Useful as a pre-processing step before /generate.
curl -X POST https://spritelab.dev/api/v1/enhance-prompt \
-H "Authorization: Bearer sl_live_YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{"prompt": "cool sword"}'
# → {"enhanced": "ornate longsword with a jewelled crossguard, ..."}
Your API-spendable balance (the top-up bucket) and account tier.
curl https://spritelab.dev/api/v1/credits \
-H "Authorization: Bearer sl_live_YOUR_KEY"
# → {"credits": 380, "tier": "knight"}
Generate one hero asset first. Pass its id as style_reference_id to everything after: palette, proportions and rendering match automatically, so a whole cast reads as one game. Same price as a plain generate.
hero = requests.post(f"{BASE}/generate", headers=KEY,
json={"prompt": "knight hero, blue cloak"})
hero_id = hero.headers["X-SpriteLab-Sprite-Id"]
goblin = requests.post(f"{BASE}/generate", headers=KEY,
json={"prompt": "goblin enemy, crooked dagger",
"style_reference_id": hero_id})
Accepted on /generate, /resize and /convert. All optional; anything you omit uses the pipeline default. Anything not listed here is ignored.
| Param | Type / range | What it does |
|---|---|---|
| max_colours | int, 2 to 64 | Palette size after quantisation |
| outline_thickness | int, 0 to 4 | Outline width in pixels. 0 disables the outline entirely |
| outline_colour | hex, #RGB or #RRGGBB | Outline colour (default black) |
| palette_lock | string | Snap to a preset palette: gameboy, demichrome, cga, slso8, pico8, sweetie16, nes, endesga16, endesga32, apollo. Or pass your own space-separated hex list ("#1a1c2c #5d275d #b13e53"). "none" or omit to disable |
| dithering | bool | Dither against the palette. Only meaningful with palette_lock |
| dither_style | string | edges (default) dithers only where two palette colours meet over a real gradient, so flat areas stay flat. fs is classic Floyd-Steinberg across the whole sprite |
| contrast | float, 0.0 to 3.0 | 1.0 = unchanged |
| saturation | float, 0.0 to 3.0 | 1.0 = unchanged |
| brightness | float, 0.0 to 3.0 | 1.0 = unchanged |