Skip to main content
GET /render/album/{hash} Renders a set of cards in a rectangular grid and returns raw PNG bytes. The {hash} path segment encodes a FanRenderRequestData JSON object (the same struct used by the fan endpoint).

Path parameter

hash
string
required
Base64 standard alphabet, no-padding encoding of a FanRenderRequestData JSON object. Contains an array of cards and an optional top-level save_name. See Hash encoding.

Grid layout

Cards are rendered in parallel, then composited into a grid. Column count
cols = ceil(sqrt(1.35 × count))
The factor 1.35 biases the grid toward a wider-than-square aspect ratio, which suits the portrait orientation of cards. Row count
rows = ceil(count / cols)
Output dimensions
width  = cols × maxCardWidth  + (cols + 1) × 10
height = rows × maxCardHeight + (rows + 1) × 10
Padding of 10 pixels is applied between every card and around all edges. maxCardWidth and maxCardHeight are the largest dimensions among all rendered cards in the batch.
All card frames render at 550 × 800 pixels, so for a uniform batch the output size is fully predictable from the formula above.

Example: 6 cards

cols = ceil(sqrt(1.35 × 6)) = ceil(sqrt(8.1)) = ceil(2.85) = 3
rows = ceil(6 / 3) = 2

width  = 3 × 550  + 4  × 10 = 1650 + 40  = 1690 px
height = 2 × 800  + 3  × 10 = 1600 + 30  = 1630 px

Examples

# Six cards in a 3×2 grid
HASH=$(echo -n '{
  "cards": [
    {"id":1,"variant":0,"dye":7864319,"kindled":false,"frame_type":0},
    {"id":2,"variant":1,"dye":255,"kindled":true,"frame_type":1},
    {"id":3,"variant":0,"dye":65280,"kindled":false,"frame_type":2},
    {"id":4,"variant":0,"dye":16711680,"kindled":false,"frame_type":0},
    {"id":5,"variant":2,"dye":16776960,"kindled":true,"frame_type":0},
    {"id":6,"variant":0,"dye":8388607,"kindled":false,"frame_type":1}
  ],
  "save_name": "album-preview.png"
}' | tr -d '\n' | base64 -w0 | tr -d '=')

curl -o album.png "http://localhost:8899/render/album/$HASH"

Response

200 OK — Raw PNG bytes.
HeaderValue
Content-Typeimage/png
X-Sourcerendered on request or loaded from disk cache
X-Processing-Timee.g. 95.441ms

Errors

StatusBodyCause
400bad request - provided card hash is invalid{hash} failed base64 decoding
400bad request - provided card hash is a valid json but does not follow API structureJSON decoded but does not match FanRenderRequestData
500failed request - invalid frame type providedA card’s frame_type is not 0, 1, or 2
500failed request - missing main image asset.A character image file was not found
500failed request - failed to decode main image asset.A character image file could not be decoded
500server error - failed to copy characterError compositing a character layer
500server error - missing required asset: {key}A frame asset file is missing
500server error - cannot write card image to bufferPNG encoding failed
500gateway timeout - asset render took more than 5 secondsRender exceeded the 5-second timeout

Build docs developers (and LLMs) love