API DOCS OPEN APP
← API OVERVIEW

Animate

A sprite plus a motion prompt in, an animated spritesheet and GIF out. Runs asynchronously: submit, get a job id, poll until it lands (typically 60 to 120 seconds).

POST /animate

POST /api/v1/animate Standard 20 CR / Pro 30 CR
FieldTypeNotes
image_b64string, requiredThe sprite to animate. Standard max 256x256; Pro max 320x320. Min 8x8, aspect ratio between 1:2 and 2:1. Transparent PNG works best
promptstring, requiredThe motion, e.g. "walking cycle, side view" or "gentle idle bounce". Max 2000 chars
enginestringstandard (default, 20 CR) or pro (30 CR). Inputs over 256 on either axis that fit within 320x320 automatically use Pro. Above 320 on either axis returns 400
framesintDefault 8. Standard: even integers 2 to 16. Pro, including auto-routed inputs: any integer 3 to 16. Invalid counts return 400

Returns 202:

{"job_id": "e17b…", "status": "queued", "engine": "standard", "cost": 20, "credits_remaining": 346}

GET /jobs/{job_id}

GET /api/v1/jobs/{job_id} FREE

Poll every few seconds. Statuses: queuedprocessing (with progress) → succeeded or failed. A failed job refunds the reserved amount (20 or 30 credits) automatically and the response says "refunded": true.

On success:

{
  "job_id": "e17b…",
  "status": "succeeded",
  "sheet_b64": "…",           # horizontal spritesheet PNG, transparent
  "gif_b64": "…",             # animated GIF with transparency
  "engine": "standard",
  "frame_count": 8,
  "frame_w": 96, "frame_h": 96,
  "fps": 8,
  "id": "f28a…"               # history row id (also viewable in the app)
}

Full example

import base64, time, requests

KEY = {"Authorization": "Bearer sl_live_YOUR_KEY"}
BASE = "https://spritelab.dev/api/v1"

sprite = base64.b64encode(open("slime_64.png", "rb").read()).decode()
r = requests.post(f"{BASE}/animate", headers=KEY, json={
    "image_b64": sprite,
    "prompt": "gentle idle bounce with squash and stretch",
    "frames": 8,
    "engine": "standard",
})
r.raise_for_status()
job_id = r.json()["job_id"]

while True:
    time.sleep(4)
    j = requests.get(f"{BASE}/jobs/{job_id}", headers=KEY).json()
    print(j["status"], j.get("progress", ""))
    if j["status"] in ("succeeded", "failed"):
        break

if j["status"] == "succeeded":
    open("slime_sheet.png", "wb").write(base64.b64decode(j["sheet_b64"]))
    open("slime.gif", "wb").write(base64.b64decode(j["gif_b64"]))
else:
    print("failed:", j.get("error"), "| refunded:", j.get("refunded"))

Notes