Tilesets: schema only, not yet measured
Called out separately because these are the most capable endpoints for level art and they are relevant to the disc-golf game. Costs below are unmeasured.
POST /tilesets (top-down) and /tilesets-sidescroller are the current
versions; /create-tileset* are the older aliases with identical schemas.
They take lower_description + upper_description (+ optional
transition_description). You describe two terrains and the transition between
them, and get a tileset that blends them. Distinctively, they accept both
color_image and per-layer reference images (lower_reference_image,
upper_reference_image, transition_reference_image). They are the only
family that combines palette forcing with style anchoring.
Useful knobs: tile_size, tileset_adherence / tileset_adherence_freedom
(how strictly tiles must fit together), raggedness and slope_size for edge
character, plus the usual outline / shading / detail.
create-tiles-pro is a different shape, a single description plus
style_images, tile_view, building_* fields for structures.
Its style_images is a fourth convention, and not the one two lines up:
TilesProStyleImage is flat, with all three fields required.
// create-tiles-pro
{ "style_images": [ { "base64": "...", "width": 32, "height": 32 } ] }
Sending generate-with-style-v2's nested {image: {...}} here is rejected as
an extra field. Passing style images at all makes the endpoint ignore
tile_type and tile_view and copy the reference's tile geometry instead.
That is the only way to land new art on an existing sheet's ground plane.
GET /tiles-pro/{id} carries no status field. It answers 423 while the set
is still drawing and 200 with storage_urls when it is done, so the HTTP code
is the status. Cost is reported at submit time and lands on the same 20/25/40
canvas tiers as 1dir, but the canvas is tile size x variation count, not one
sprite. A small tile in a large set still reaches the top tier.
All response shapes used by the client are validated at runtime. The TypeScript
interfaces alone are not trusted at the HTTP boundary: missing ids, invalid
object geometry, malformed tile URL maps, or balance fields with changed types
produce an Invalid PixelLab response error before pipeline state is updated.
outline_mode defaults to outline, which draws a dark border around every
tile. For ground tiles that is wrong: laid on a grid the borders read as
quilting, with a seam at every cell edge. segmentation omits them and the
same set tiles seamlessly, measured on a fairway-to-rough terrain set, where
it was the difference between usable and unusable.
tile_feature and style_images are mutually exclusive. The API says
"Connectable features (roads/tileset/building) cannot be combined with style
tiles". So the
geometry-anchoring trick above is unavailable for a connectable set, and its
tiles land on whatever ground plane the view angle implies (measured: 32x24
with the diamond midline at y=7, against a 32x32 sheet wanting y=15).
tile_feature turns it from independent variations into a connectable set:
roads (18-configuration path set), tileset (16-tile Wang corner set for a
terrain transition; describe it as the transition, not one terrain), and
building (floor/wall/doorway kit). These are sliced by index, so the returned
order is load-bearing. They are structural multi-output results, not candidates
to choose between: PixelKiln persists every URL in numeric order and labels the
downloaded outputs tile-00, tile-01, … .
The completed response also carries tile_rules for connectable sets. Its
placement contract is rule_type (edge, corner, or outline), arity (4
for square/isometric edges or corners, 6 for hex edges), connectivity
(same/other), two terrain labels, and a tiles map of provider tile key to
bitmask. Four-edge masks use N/E/S/W as bits 0/1/2/3. Four-corner masks use
NW/NE/SW/SE as bits 3/2/1/0. Tiles absent from that map are stamp-only. PixelKiln
stores the complete object in providerMetadata.pixellab.tileRules; exporters
normalize the documented subset but retain the raw object in the generic file.
Given that color_image is honoured on pixflux but silently ignored on
resize, verify the palette actually holds on a single tileset before
committing to a set.