API reference

Full Sprite AI REST API reference: endpoints for generating sprites and animations, request and response formats, parameters, and example calls.

Every endpoint below takes a bearer key, sent as Authorization: Bearer sai_sk_.... Generate one here, or manage your existing keys on the API keys page.

API key

Working in Claude Code, Cursor or another MCP client? The same key connects it in one step, and you get these endpoints as tools instead of HTTP calls. See Sprite AI on MCP.

GET/api/me

Your account: plan, balance, and rate limit.

curl https://www.sprite-ai.art/api/me \
-H "Authorization: Bearer sai_sk_your_key_here"
200 OK
{
"user_id": "...",
"email": "you@example.com",
"plan": "studio",
"rate_limit_per_minute": 60,
"monthly_token_allotment": 1000,
"monthly_tokens_used": 340,
"purchased_token_balance": 0,
"total_token_balance": 660,
"monthly_renews_at": "2026-07-01T00:00:00.000Z",
"billing_period": "monthly"
}

GET/api/balance

Token balance only, a subset of /api/me.

curl https://www.sprite-ai.art/api/balance \
-H "Authorization: Bearer sai_sk_your_key_here"
200 OK
{
"plan": "studio",
"total_token_balance": 660,
"purchased_token_balance": 0,
"monthly_token_allotment": 1000,
"monthly_tokens_used": 340,
"monthly_renews_at": "2026-07-01T00:00:00.000Z",
"billing_period": "monthly"
}

GET/api/asset-types

Asset types with their token cost and size range.

curl https://www.sprite-ai.art/api/asset-types \
-H "Authorization: Bearer sai_sk_your_key_here"
TypeToken costSize
character132–400 px
item132–400 px
creature132–400 px
tile18–400 px
background18–400 px
ui18–400 px
effect18–400 px

GET/api/limits

Request bounds and token costs for your key.

curl https://www.sprite-ai.art/api/limits \
-H "Authorization: Bearer sai_sk_your_key_here"
200 OK
{
"rate_limit_per_minute": 60,
"sprite": { "min_size": 8, "max_size": 400, "prompt_max_length": 1500 },
"animation": { "min_frames": 4, "max_frames": 24, "frames_must_be_even": true }
}

POST/api/sprites

Generate a still sprite. Synchronous: the PNG comes back inline. Costs 1 token.

FieldTypeRequiredDescription
promptstringYesWhat to draw. 3–1500 chars.
asset_typestringNoInferred from the prompt when omitted.
widthintegerNo32–400 px. Default 64.
heightintegerNo32–400 px. Default 64.
directionstringNoFacing direction, e.g. south.
camera_perspectivestringNoe.g. side, top_down, isometric.
publicbooleanNoAdd to the public gallery. Default false.
reference_asset_idstringNoUUID of a sprite you own, used as a style reference.
palette_idstringNoA palette from your library (see Palettes). The sprite is drawn in it, held to it, and remembers it, so animations, restyles and combines keep the same colours.
curl https://www.sprite-ai.art/api/sprites \
-H "Authorization: Bearer sai_sk_your_key_here" \
-H "Content-Type: application/json" \
-d '{ "prompt": "a knight with a blue cape", "asset_type": "character" }'
201 Created
{
"id": "a1b2c3d4-...",
"status": "completed",
"width": 64,
"height": 64,
"assetType": "character",
"tokensSpent": 1,
"image": { "format": "png", "pngBase64": "iVBORw0KGgoAAAANS..." }
}

The PNG is inline in image.pngBase64. There is no hosted URL.

POST/api/sprites/import

Add a sprite you already have (a local PNG, or any pixel sprite) and get back an id you can animate (source_generation_id) or use as a style reference (reference_asset_id). Free: importing spends no tokens and runs no AI.

The image must be a single sprite (PNG, JPEG, or WebP), 16–256px per side, not a sprite sheet. Imported sprites are always private.

FieldTypeRequiredDescription
imagestringYesThe sprite, as base64 or a data:image/...;base64 URL.
titlestringNoLabel for the sprite. Default "Imported sprite".
asset_typestringNoAsset-type tag (metadata only).
palette_idstringNoA palette from your library. The sprite is stamped with it so later tools hold to it; the pixels are not changed.
curl https://www.sprite-ai.art/api/sprites/import \
-H "Authorization: Bearer sai_sk_your_key_here" \
-H "Content-Type: application/json" \
-d '{ "image": "<png base64>", "title": "hero" }'
201 Created
{
"id": "a1b2c3d4-...",
"status": "completed",
"width": 64,
"height": 64,
"title": "hero"
}

GET/api/sprites/{id}

Fetch one of your past sprites.

curl https://www.sprite-ai.art/api/sprites/a1b2c3d4-... \
-H "Authorization: Bearer sai_sk_your_key_here"

GET/api/sprites

List your sprites and animations, newest first.

ParameterTypeDescription
limitinteger1–100. Default 20.
offsetintegerFor pagination. Default 0.
statusstringFilter by status.
asset_typestringFilter by type, e.g. animation.
curl "https://www.sprite-ai.art/api/sprites?limit=20" \
-H "Authorization: Bearer sai_sk_your_key_here"

POST/api/palettes/generate

A few palette options for a description, nothing saved. Show them to the person, let them pick one or ask again, then save the pick with POST /api/palettes. The prompt is read into a theme, a main colour and moods; a number in the text sets the colour count. Free.

FieldTypeRequiredDescription
promptstringYesWhat the palette is for, e.g. "mossy dungeon, 16 colours".
countintegerNoColours per option, 4-64. Default: the number in the prompt. With no number anywhere, the options come one per size, 8, 16, 24 and 32.
optionsintegerNoHow many options, 2-4. Default 4.
200 OK
{
"prompt": "mossy dungeon, 16 colours",
"read_as": "theme forest, main colour green, mood dark",
"options": [
  { "option": 1, "colors": ["#1a2a1c", "..."], "recipe": { "count": 16, "seed": 91827364, "theme": "forest", "primary": "green", "moods": ["dark"] } },
  { "option": 2, "colors": ["..."], "recipe": { "count": 16, "seed": 5550123, "theme": "forest", "primary": "green", "moods": ["dark"] } }
]
}

POST/api/palettes

Save the pick. Pass the chosen option's recipe exactly as returned, or explicit colors, and a name. A recipe is regenerated server-side, so the saved palette is exactly the option that was shown. The id that comes back is the palette_id for POST /api/sprites and POST /api/sprites/import. Free.

FieldTypeRequiredDescription
namestringYesA short name, up to 80 characters.
recipeobjectOne ofThe chosen option's recipe from /api/palettes/generate.
colorsstring[]One of2-256 #rrggbb colours instead of a recipe.
201 Created
{
"id": "5f0c2a7e-...",
"name": "Mossy dungeon",
"colors": ["#1a2a1c", "..."],
"count": 16,
"source": "generated",
"created_at": "2026-09-11T22:00:00.000Z"
}

GET/api/palettes

Your palettes, newest first, as { "palettes": [ ... ] } with the same shape as above. GET /api/palettes/{id} returns one. Every sprite object carries paletteId, null when the sprite has no palette.

POST/api/animations

Start an animation job from a source sprite. Asynchronous: returns an id immediately, then you poll until it finishes (~15s). Animations run one at a time per account, so a batch of N finishes in about N x 15s. The token cost scales with frame_count.

Reference the source by source_generation_id: the id of a sprite you own, from POST /api/sprites (generate) or POST /api/sprites/import. No image bytes travel through this call; we fetch them server-side. The source must be a single still sprite, no larger than 256px on either side, not a sprite sheet or an existing animation.

FieldTypeRequiredDescription
source_generation_idstringYesUUID of a sprite you generated or imported.
presetstringYesMotion preset (Walk, Run, Idle, ...) or Custom.
frame_countintegerNoEven, 4–16. Default 8. Drives the token cost.
custom_promptstringCustom onlyFree-form motion. Required when preset is Custom.
palette_extrasintegerNoColours the animation may add beyond the source sprite's own, 0-256. 0 keeps its palette exact. Raise it only when the motion brings colours the sprite lacks (fire, magic glow, sparks). Omit for the preset's tuned default: Attack 12, Custom 12, every other preset 0.
framing_marginintegerNoPercentage the canvas grows by before animating, 0-25, so a jump or a projected effect has room instead of being cropped at the sprite's edge. The result comes back at the grown size. Omit for in-place motion like walks and idles. Default 0.
framing_anchorstringNoWhere the sprite sits in that grown canvas: top-left, top, top-right, left, center, right, bottom-left, bottom or bottom-right. bottom keeps feet grounded in a jump; a bottom corner opposite the way the sprite faces opens room in front for a projected effect. Default center.
publicbooleanNoAdd to the public gallery. Default false.
curl https://www.sprite-ai.art/api/animations \
-H "Authorization: Bearer sai_sk_your_key_here" \
-H "Content-Type: application/json" \
-d '{ "source_generation_id": "a1b2c3d4-...", "preset": "Walk", "frame_count": 8 }'
202 Accepted
{ "id": "a1b2c3d4-...", "status": "processing" }

GET/api/animations/{id}

Poll an animation job. While running it returns processing with an optional progress (0–1). When status is completed, the sheet is in image.spritesheetBase64. On failed, tokens are refunded automatically. Poll about every 5 seconds.

# poll every ~5s until status is completed or failed
curl https://www.sprite-ai.art/api/animations/a1b2c3d4-... \
-H "Authorization: Bearer sai_sk_your_key_here"
200 OK (completed)
{
"id": "a1b2c3d4-...",
"status": "completed",
"frameWidth": 64,
"frameHeight": 64,
"frameCount": 8,
"fps": 12,
"image": { "format": "png", "spritesheetBase64": "iVBORw0KGgoAAAANS..." }
}

A single horizontal-strip PNG. Slice it with frameCount, frameWidth, frameHeight.

POST/api/animations/{id}/cancel

Cancel a running job and refund its tokens. If the job already completed or failed, it returns an error since there is nothing to cancel.

curl -X POST https://www.sprite-ai.art/api/animations/a1b2c3d4-.../cancel \
-H "Authorization: Bearer sai_sk_your_key_here"
200 OK
{ "id": "a1b2c3d4-...", "status": "cancelled" }

POST/api/restyles

Change a sprite you own and keep the character. Restyle its look, put it in a new pose, or swap the item it holds — mode says which. Asynchronous like animations: returns an id immediately, then you poll until it finishes (~15s on the normal tier, up to a minute on pro). Cost depends on the tier: 2 tokens on normal, 9 on pro. Presets and custom prompts cost the same.

Reference the source by source_generation_id: the id of a sprite you own, from POST /api/sprites (generate) or POST /api/sprites/import. No image bytes travel through this call; we fetch them server-side. The source must be 32-256px on each side; the result comes back at the source's size, unless framing_margin grows the canvas first.

FieldTypeRequiredDescription
source_generation_idstringYesUUID of a sprite you generated or imported, 32-256px per side.
presetstringOne of preset / custom_promptLocked style: fire, ice, gold, zombie, holy, cursed, poison, royal, shadow, steampunk. A preset always means mode restyle.
custom_promptstringOne of preset / custom_promptWhat to change, in your own words, up to 500 chars. Read together with mode.
modestringNorestyle (repaint, colours may change), pose (move the character, keep everything else), item (swap one named object), custom. Default restyle.
tierstringNonormal or pro. Pro holds the character closer and wins item swaps; normal wins poses. CHANGES THE PRICE. Default normal.
palette_extrasnumberNoColours the edit may use beyond the sprite's own, 0-256. 0 keeps its palette exact. Defaults per mode: restyle 16, pose 0, item 12, custom 12.
framing_marginnumberNoPercentage the canvas grows by before the edit, 0-25, so a pose has room. The result comes back at the grown size. Default 0.
framing_anchorstringNoWhere the sprite sits in that grown canvas, e.g. bottom to keep a character's feet planted. Default center.
publicbooleanNoAdd to the public gallery. Default false.
curl https://www.sprite-ai.art/api/restyles \
-H "Authorization: Bearer sai_sk_your_key_here" \
-H "Content-Type: application/json" \
-d '{ "source_generation_id": "a1b2c3d4-...", "preset": "gold" }'
202 Accepted
{ "id": "a1b2c3d4-...", "status": "processing" }

GET/api/restyles/{id}

Poll a restyle job. While running it returns processing; when status is completed, the sprite is in image.pngBase64 at native resolution. On failed, tokens are refunded automatically. Poll about every 3 seconds.

# poll every ~3s until status is completed or failed
curl https://www.sprite-ai.art/api/restyles/a1b2c3d4-... \
-H "Authorization: Bearer sai_sk_your_key_here"
200 OK (completed)
{
"id": "a1b2c3d4-...",
"status": "completed",
"width": 64,
"height": 64,
"isPublic": false,
"slug": null,
"image": { "format": "png", "pngBase64": "iVBORw0KGgoAAAANS..." }
}

POST/api/restyles/{id}/cancel

Cancel a running restyle and refund its tokens. If the job already completed or failed, it returns an error since there is nothing to cancel.

curl -X POST https://www.sprite-ai.art/api/restyles/a1b2c3d4-.../cancel \
-H "Authorization: Bearer sai_sk_your_key_here"
200 OK
{ "id": "a1b2c3d4-...", "status": "cancelled" }

POST/api/combines

Put an item from one sprite you own into another sprite you own. The first sprite keeps its identity and its exact dimensions; the second is where the item is copied from, so its shape and its colours are what you get. The result is locked to both sprites' palettes, so an item never comes back repainted in the character's colours. Asynchronous like restyles: returns an id immediately, then you poll until it finishes (~20s on normal, 3-4 minutes on pro). Cost depends on the tier: 3 tokens on normal, 9 on pro.

Reach for this when the item exists as a sprite. To swap for something you only have words for, use POST /api/restyles with mode: "item" instead.

Both sprites are referenced by id, from POST /api/sprites (generate) or POST /api/sprites/import. No image bytes travel through this call; we fetch them server-side, which also means both sprites must be yours. Each must be 32-256px on each side, and the two ids must differ. The result comes back at the first sprite's size even when framing_margin grows the canvas first.

FieldTypeRequiredDescription
source_generation_idstringYesUUID of the sprite that keeps its identity. Its dimensions are the output's.
item_generation_idstringYesUUID of the sprite the item is copied from. Must differ from source_generation_id.
promptstringYesWhere the item goes, up to 500 chars. Say the placement, not the item: the item comes from the image.
tierstringNonormal or pro. Normal puts the item in the character's hands and is the default. Pro holds the character closer but places the item worse. CHANGES THE PRICE.
palette_extrasnumberNoColours the combine may use beyond the two sprites' union, 0-256. 0 locks it to exactly their palettes. Default 4.
framing_marginnumberNoPercentage the canvas grows by before the edit, 0-25, so a reaching item has room. The sprite still returns at the first sprite's size. Default 0.
framing_anchorstringNoWhere the sprite sits in that grown canvas, e.g. bottom to keep a character's feet planted. Default center.
publicbooleanNoAdd to the public gallery. Default false.
curl https://www.sprite-ai.art/api/combines \
-H "Authorization: Bearer sai_sk_your_key_here" \
-H "Content-Type: application/json" \
-d '{ "source_generation_id": "a1b2c3d4-...", "item_generation_id": "e5f6a7b8-...", "prompt": "holding this shield in his free hand" }'
202 Accepted
{ "id": "a1b2c3d4-...", "status": "processing" }

GET/api/combines/{id}

Poll a combine job. While running it returns processing; when status is completed, the sprite is in image.pngBase64 at the first sprite's size. On failed, tokens are refunded automatically. Poll about every 3 seconds. A normal-tier run is usually done on the first or second poll; pro takes minutes.

curl https://www.sprite-ai.art/api/combines/a1b2c3d4-... \
-H "Authorization: Bearer sai_sk_your_key_here"
200 OK
{
"id": "a1b2c3d4-...",
"status": "completed",
"width": 64,
"height": 64,
"isPublic": false,
"slug": null,
"image": { "format": "png", "pngBase64": "iVBORw0KGgo..." }
}

POST/api/combines/{id}/cancel

Cancel a running combine and refund its tokens. If the job already completed or failed, it returns an error since there is nothing to cancel.

curl -X POST https://www.sprite-ai.art/api/combines/a1b2c3d4-.../cancel \
-H "Authorization: Bearer sai_sk_your_key_here"
200 OK
{ "id": "a1b2c3d4-...", "status": "cancelled" }

POST/api/touch-ups

Repair one part of a sprite you own and leave every other pixel alone. Give it a region and a sentence, and the selected area is redrawn in the sprite's own colors while everything outside it comes back byte-identical. The result is saved as a new sprite id you can animate, rotate or restyle. Synchronous, about 15 to 30 seconds. Cost: 1 token.

This repairs a detail. It is not an item-swap tool: asked to change a weapon it drew the new one once in four tries, while POST /api/restyles with the item preset did it every time. Use touch-ups for eyes, a face, a hand, a dent in a helmet. The sprite comes back at its original size, and the price is the same whether it is 64px or 512px.

FieldTypeRequiredDescription
source_generation_idstringYesUUID of a still sprite you own, 32-1024px per side.
promptstringYesWhat to fix, 1-300 characters. E.g. "glowing red eyes in the visor".
regionobjectYesThe area to repair, in sprite pixels: { x, y, width, height }, origin top-left.
publicbooleanNoOpt the result into the public gallery. Default false.

The region is clipped to the sprite, and the clipped box is echoed back in the response so you can draw it over the result. Roughly 200x200 pixels is the ceiling on the region, whatever the sprite's own size: a window is cropped around it and composited back, so a large sprite is fine but a large region is refused. To change a whole sprite, use POST /api/restyles.

curl https://www.sprite-ai.art/api/touch-ups \
-H "Authorization: Bearer sai_sk_your_key_here" \
-H "Content-Type: application/json" \
-d '{
  "source_generation_id": "a1b2c3d4-...",
  "prompt": "glowing red eyes in the visor",
  "region": { "x": 32, "y": 10, "width": 12, "height": 11 }
}'
201 Created
{
"id": "f7a8b9c0-...",
"status": "completed",
"width": 64,
"height": 64,
"region": { "x": 32, "y": 10, "width": 12, "height": 11 },
"isPublic": false,
"slug": null,
"image": { "format": "png", "pngBase64": "iVBORw0KGgoAAAANS..." }
}

POST/api/rotations

Turn one still sprite you own into a full 8-direction set: S, SE, E, NE, N, NW, W, SW, same character and same palette. Returns a horizontal strip of 8 equal frames in that spin order plus a fidelity score: the sheet is calibrated against the source and a low-scoring roll is redone automatically. Synchronous: one request, the finished strip inline, about a minute and up to 2.5 minutes when the quality gate forces a second roll. Cost: 12 tokens.

The source must be a still sprite, 32-256px per side, not an animation. The result is saved as an animation row, so GET /api/sprites/{id} and the download URL treat the strip like a spritesheet. Slice it every frameWidth pixels for the individual directions.

FieldTypeRequiredDescription
source_generation_idstringYesUUID of a still sprite you own, 32-256px per side.
publicbooleanNoOpt the set into the public gallery. Default false.
curl https://www.sprite-ai.art/api/rotations \
-H "Authorization: Bearer sai_sk_your_key_here" \
-H "Content-Type: application/json" \
-d '{ "source_generation_id": "a1b2c3d4-..." }'
201 Created
{
"id": "c9d0e1f2-...",
"status": "completed",
"frameWidth": 64,
"frameHeight": 64,
"frameCount": 8,
"fps": 6,
"directions": ["s", "se", "e", "ne", "n", "nw", "w", "sw"],
"calibrationScore": 0.94,
"isPublic": false,
"image": { "format": "png", "spritesheetBase64": "iVBORw0KGgoAAAANS..." }
}

POST/api/normal-maps

Generate a tangent-space normal map for a sprite or animation you own, for dynamic lighting in a game engine. Our own model, trained on real 3D geometry rather than edge-detect heuristics: the output encodes the subject's actual form, and its alpha channel is a pixel-exact copy of the source silhouette. Synchronous: the finished PNG comes back inline in a few seconds, no job to poll. Cost: 1 token per frame.

An animation source is normal-mapped per frame automatically (the model is deterministic, so frames never flicker) and comes back as the same-layout horizontal strip. Load it in your engine exactly like the animation itself.

FieldTypeRequiredDescription
source_generation_idstringYesUUID of a sprite or animation you own. Frames must be 32-256px per side.
strengthnumberNoDetail injection, 0-5, default 0. 0 is truest to the geometry; ~2.5 re-adds the sprite's drawn shading for a hand-crafted look.
flip_greenbooleanNoFlip green for DirectX / +Y-down engines (Unreal). Default false = OpenGL / +Y-up (Godot, Unity, WebGL).
columnsnumberNoOnly for a still that is really a sprite sheet: its column count. Ignored for animations (layout is known). columns x rows <= 24.
rowsnumberNoSheet row count, with columns. Default 1.
curl https://www.sprite-ai.art/api/normal-maps \
-H "Authorization: Bearer sai_sk_your_key_here" \
-H "Content-Type: application/json" \
-d '{ "source_generation_id": "a1b2c3d4-..." }'
201 Created
{
"id": "e5f6a7b8-...",
"status": "completed",
"width": 64,
"height": 64,
"frameCount": 1,
"tokensSpent": 1,
"image": { "format": "png", "pngBase64": "iVBORw0KGgoAAAANS..." }
}

POST/api/background-removals

Remove a flat, single-color background from a sprite or animation you own and get back a transparent PNG, saved as a new sprite id you can animate, restyle or normal-map. Two methods, the same two the studio's Remove background tool runs: standard is a chroma key and is free, refined is palette matting against the sprite's own colors and costs 1 token. Refined gives the cleaner edge on AI-generated pixel art. The background color is sampled from the four corners unless you pass matte_color. Synchronous, well under a second.

Sprites generated here already have transparent backgrounds. This endpoint is for imported screenshots and renders on a flat color, and a source whose corners are already transparent is refused. An animation is keyed as one strip and comes back as an animation. Cutouts are always private.

FieldTypeRequiredDescription
source_generation_idstringYesUUID of a sprite or animation you own.
methodstringNostandard (free, chroma key) or refined (1 token, palette matting). Default standard.
matte_colorstringNoBackground color to remove, as #rrggbb. Default: sampled from the corners.
tolerancenumberNostandard only. How far from the background color a pixel may be and still be removed, 0-300. Default 200.
palette_sizenumberNorefined only. Cap on the sprite colors used for matting, 16-256. Default 64.
alpha_thresholdnumberNorefined only. Coverage above which an edge pixel stays opaque, 0.3-0.9. Default 0.7.
curl https://www.sprite-ai.art/api/background-removals \
-H "Authorization: Bearer sai_sk_your_key_here" \
-H "Content-Type: application/json" \
-d '{ "source_generation_id": "a1b2c3d4-...", "method": "refined" }'
201 Created
{
"id": "f7a8b9c0-...",
"status": "completed",
"method": "refined",
"width": 64,
"height": 64,
"frameCount": null,
"matteColor": "#ff00ff",
"tokensSpent": 1,
"image": { "format": "png", "pngBase64": "iVBORw0KGgoAAAANS..." }
}

Errors

Every error returns the same JSON shape. Branch on code, not message.

{ "code": "invalid_request", "message": "...", "details": {} }
HTTPCodeCause
400invalid_requestBody failed validation.
401invalid_api_keyKey missing or not recognized.
402insufficient_tokensNot enough tokens.
402upgrade_requiredNeeds a paid plan.
403api_key_revokedThe key was revoked.
404not_foundNot found, or not yours.
422nsfw_promptPrompt rejected by the filter.
429rate_limitedToo many requests.
500provider_failureRender failed. Tokens refunded.

Asset packs

One prompt can plan a whole pack: the anchor sprite, its facing directions, an animation per direction, restyles and lighting maps, priced step by step and run only after you approve the total. The four endpoints (POST /api/agent, POST /api/agent/{id}/run, GET /api/agent/{id}, POST /api/agent/{id}/cancel) are on the Sprite Agent page.

Last updated October 9, 2026

We use cookies to enhance your experience. Essential cookies are required for the site to function. You can choose to accept all cookies or only essential ones.

Cookie policy