# Rengi Forge > Pay-per-call tools for AI agents that build games. No account, no API key, no subscription: each paid call is paid on the spot with x402 in USDC. ## How to pay 1. Send the request as documented below. 2. A paid route answers HTTP 402. The `PAYMENT-REQUIRED` response header (base64 JSON) lists the accepted payment options. 3. Pick one (accepted networks: Base `eip155:8453`, Solana `solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp`; asset USDC, scheme `exact`), sign it with an x402 client such as @x402/fetch, and resend the same request with the `PAYMENT-SIGNATURE` header. 4. You are charged only when the call succeeds. If the service fails or times out, the payment is not settled. Machine-readable: https://rengi.dev/openapi.json ## Use via MCP Remote MCP server (streamable HTTP): https://rengi.dev/mcp - every paid route below is a tool named _ (for example level_design_place), paid per call with x402 inside MCP. Tool forge_help is free. ## Level design (`level-design`) Level dressing for 3D games. Send a layout (zones as polygons, or a color-legend sketch), your prop catalog (GLBs or bounds) and a brief; get back exact placements (asset id, position, rotation, scale) for Unity or three.js plus preview renders. A model plans like a level designer, a seeded solver places: no overlaps, nothing on roads or water, required points stay walkable on a navmesh, same seed gives the same result. Schemas: https://rengi.dev/v1/level-design/schema ### POST /v1/level-design/catalog Ingest your prop catalog: footprint, height, pivot and category computed from each GLB. Returns a catalogId for place. Price: $0.50 USDC. Time limit: 90 s. Example request: ```json { "assets": [ { "id": "house_small", "glbUrl": "https://rengi.dev/samples/house_small.glb" }, { "id": "pine", "bounds": { "min": [ -1.5, 0, -1.5 ], "max": [ 1.5, 6, 1.5 ] }, "category": "tree" } ] } ``` Example response: ```json { "catalogId": "cat_0123456789abcdef0123", "cached": false, "assets": [ { "id": "house_small", "category": "house", "footprint": [ [ -2.3, -2.8 ], [ 2.3, -2.8 ], [ 2.3, 2.8 ], [ -2.3, 2.8 ] ], "footprintRadius": 3.62, "height": 5, "pivotOffset": { "x": 0, "y": 0, "z": 0 }, "hasMesh": true, "tags": [] } ] } ``` ### POST /v1/level-design/place Dress a level: placements for every zone, previews and a 3D viewer link. Price: $1.00 USDC. Time limit: 120 s. Example request: ```json { "catalogId": "cat_0123456789abcdef0123", "layout": { "kind": "zones", "width": 100, "depth": 100, "zones": [ { "id": "road-ew", "kind": "road", "polyline": [ [ 0, 50 ], [ 100, 50 ] ], "width": 6 }, { "id": "market", "kind": "plaza", "polygon": [ [ 56, 30 ], [ 76, 30 ], [ 76, 46 ], [ 56, 46 ] ] }, { "id": "lot-1", "kind": "building-lot", "polygon": [ [ 80, 34 ], [ 92, 34 ], [ 92, 46 ], [ 80, 46 ] ] } ], "requiredPoints": [ { "id": "spawn", "x": 3, "z": 50 }, { "id": "market", "x": 66, "z": 38 } ] }, "brief": "Farming village, busy market square.", "seed": 7, "targetEngine": "unity" } ``` Example response: ```json { "jobId": "job_ac27f34abec846dc9130", "engine": "unity", "coordinates": "Unity (left-handed, Y up). Map spans x 0..width, z 0..-depth: the top-down map's z axis is flipped so north stays +Z. Rotation is yaw about Y; asset forward = local +Z.", "planner": "preset", "zones": [ { "id": "road-ew", "kind": "road", "polygon": [ [ 0, 53 ], [ 100, 53 ], [ 100, 47 ], [ 0, 47 ] ], "area": 564 }, { "id": "road-ns", "kind": "road", "polygon": [ [ 47, 0 ], [ 47, 100 ], [ 53, 100 ], [ 53, 0 ] ], "area": 600 }, { "id": "market", "kind": "plaza", "polygon": [ [ 56, 30 ], [ 76, 30 ], [ 76, 46 ], [ 56, 46 ] ], "area": 320 }, { "id": "forest-nw", "kind": "forest", "polygon": [ [ 2, 2 ], [ 44, 2 ], [ 44, 26 ], [ 30, 40 ], [ 2, 44 ] ], "area": 1529.6 }, { "id": "field-se", "kind": "field", "polygon": [ [ 60, 62 ], [ 96, 62 ], [ 96, 94 ], [ 60, 94 ] ], "area": 1152 }, { "id": "field-sw", "kind": "field", "polygon": [ [ 8, 62 ], [ 40, 62 ], [ 40, 90 ], [ 8, 90 ] ], "area": 888 }, { "id": "lot-1", "kind": "building-lot", "polygon": [ [ 80, 34 ], [ 92, 34 ], [ 92, 46 ], [ 80, 46 ] ], "area": 144 }, { "id": "lot-2", "kind": "building-lot", "polygon": [ [ 56, 6 ], [ 68, 6 ], [ 68, 18 ], [ 56, 18 ] ], "area": 144 }, { "id": "lot-3", "kind": "building-lot", "polygon": [ [ 36, 54 ], [ 46, 54 ], [ 46, 64 ], [ 36, 64 ] ], "area": 100 }, { "id": "lot-4", "kind": "building-lot", "polygon": [ [ 54, 54 ], [ 64, 54 ], [ 64, 60 ], [ 54, 60 ] ], "area": 60 }, { "id": "lot-5", "kind": "building-lot", "polygon": [ [ 22, 38 ], [ 34, 38 ], [ 34, 46 ], [ 22, 46 ] ], "area": 96 }, { "id": "spawn-w", "kind": "spawn", "polygon": [ [ 0, 44 ], [ 8, 44 ], [ 8, 56 ], [ 0, 56 ] ], "area": 48 } ], "plan": { "zones": [ { "zoneId": "market", "rules": [ { "kind": "anchor", "asset": "well", "at": "centroid" }, { "kind": "ring", "assets": [ "market_stall" ], "center": "centroid", "radius": 4.4, "count": 5, "facing": "inward" }, { "kind": "along", "assets": [ "lamp_post" ], "offset": [ 0.6, 1.2 ], "spacing": [ 9, 12 ], "facing": "toward" } ] }, { "zoneId": "forest-nw", "rules": [ { "kind": "scatter", "assets": [ "oak", "pine" ], "density": 0.6, "falloff": { "from": "edge", "strength": 0.5 } }, { "kind": "scatter", "assets": [ "bush" ], "density": 0.12 }, { "kind": "cluster", "assets": [ "rock" ], "clusters": 2, "count": 3, "radius": 3, "center": "random" } ] }, { "zoneId": "field-se", "rules": [ { "kind": "along", "assets": [ "fence" ], "offset": [ 0.35, 0.35 ], "spacing": [ 2.08, 2.08 ], "facing": "toward" }, { "kind": "scatter", "assets": [ "bush" ], "density": 0.04 } ] }, { "zoneId": "field-sw", "rules": [ { "kind": "along", "assets": [ "fence" ], "offset": [ 0.35, 0.35 ], "spacing": [ 2.08, 2.08 ], "facing": "toward" }, { "kind": "scatter", "assets": [ "bush" ], "density": 0.04 } ] }, { "zoneId": "lot-1", "rules": [ { "kind": "lot", "assets": [ "house_large", "house_small", "tavern" ] } ] }, { "zoneId": "lot-2", "rules": [ { "kind": "lot", "assets": [ "house_large", "house_small", "tavern" ] } ] }, { "zoneId": "lot-3", "rules": [ { "kind": "lot", "assets": [ "house_large", "house_small", "tavern" ] } ] }, { "zoneId": "lot-4", "rules": [ { "kind": "lot", "assets": [ "house_large", "house_small", "tavern" ] } ] }, { "zoneId": "lot-5", "rules": [ { "kind": "lot", "assets": [ "house_large", "house_small", "tavern" ] } ] }, { "zoneId": "spawn-w", "rules": [ { "kind": "ring", "assets": [ "lamp_post" ], "center": "centroid", "radius": 2, "count": 2, "facing": "inward" } ] }, { "zoneId": "open", "rules": [ { "kind": "scatter", "assets": [ "oak", "pine" ], "density": 0.1 }, { "kind": "scatter", "assets": [ "bush" ], "density": 0.07 }, { "kind": "scatter", "assets": [ "rock" ], "density": 0.03 } ] } ], "notes": "preset plan: fantasy-village" }, "placements": [ { "assetId": "well", "zoneId": "market", "position": { "x": 66.4794, "y": 0, "z": -40.7875 }, "rotation": { "quaternion": [ 0, 0, 0, 1 ], "eulerDeg": { "x": 0, "y": 0, "z": 0 } }, "scale": 1 }, { "assetId": "house_small", "zoneId": "lot-1", "position": { "x": 86, "y": 0, "z": -40 }, "rotation": { "quaternion": [ 0, 0, 0, 1 ], "eulerDeg": { "x": 0, "y": 0, "z": 0 } }, "scale": 1 }, { "assetId": "house_large", "zoneId": "lot-2", "position": { "x": 62, "y": 0, "z": -12 }, "rotation": { "quaternion": [ 0, 0.707107, 0, 0.707107 ], "eulerDeg": { "x": 0, "y": 90, "z": 0 } }, "scale": 1 }, { "assetId": "tavern", "zoneId": "lot-3", "position": { "x": 41, "y": 0, "z": -59 }, "rotation": { "quaternion": [ 0, -0.707107, 0, 0.707107 ], "eulerDeg": { "x": 0, "y": -90, "z": 0 } }, "scale": 1 }, { "assetId": "house_small", "zoneId": "lot-4", "position": { "x": 59, "y": 0, "z": -57 }, "rotation": { "quaternion": [ 0, 0.707107, 0, 0.707107 ], "eulerDeg": { "x": 0, "y": 90, "z": 0 } }, "scale": 1 } ], "stats": { "total": 295, "byCategory": { "prop": 5, "house": 5, "light": 7, "fence": 116, "rock": 10, "tree": 43, "bush": 109 }, "overlaps": 0, "reachable": true, "removedForReachability": [] }, "previews": { "topDown": "https://rengi.dev/files/example/top-down.png", "perspective": "https://rengi.dev/files/example/perspective.png", "ground": "https://rengi.dev/files/example/ground.png" }, "viewer": "https://rengi.dev/files/example/viewer.html", "sceneJson": "https://rengi.dev/files/example/scene.json", "note": "placements trimmed to 5 of 295 for the example" } ``` ### POST /v1/level-design/revise Change a placed level with an instruction or structured zone edits; untouched zones keep their exact transforms. Price: $0.50 USDC. Time limit: 60 s. Example request: ```json { "jobId": "job_0123456789abcdef0123", "instruction": "denser forest on the north edge" } ``` Example response: ```json { "jobId": "job_fedcba9876543210fedc", "engine": "unity", "coordinates": "Unity (left-handed, Y up). Map spans x 0..width, z 0..-depth: the top-down map's z axis is flipped so north stays +Z. Rotation is yaw about Y; asset forward = local +Z.", "planner": "preset", "zones": [ { "id": "road-ew", "kind": "road", "polygon": [ [ 0, 53 ], [ 100, 53 ], [ 100, 47 ], [ 0, 47 ] ], "area": 564 }, { "id": "road-ns", "kind": "road", "polygon": [ [ 47, 0 ], [ 47, 100 ], [ 53, 100 ], [ 53, 0 ] ], "area": 600 }, { "id": "market", "kind": "plaza", "polygon": [ [ 56, 30 ], [ 76, 30 ], [ 76, 46 ], [ 56, 46 ] ], "area": 320 }, { "id": "forest-nw", "kind": "forest", "polygon": [ [ 2, 2 ], [ 44, 2 ], [ 44, 26 ], [ 30, 40 ], [ 2, 44 ] ], "area": 1529.6 }, { "id": "field-se", "kind": "field", "polygon": [ [ 60, 62 ], [ 96, 62 ], [ 96, 94 ], [ 60, 94 ] ], "area": 1152 }, { "id": "field-sw", "kind": "field", "polygon": [ [ 8, 62 ], [ 40, 62 ], [ 40, 90 ], [ 8, 90 ] ], "area": 888 }, { "id": "lot-1", "kind": "building-lot", "polygon": [ [ 80, 34 ], [ 92, 34 ], [ 92, 46 ], [ 80, 46 ] ], "area": 144 }, { "id": "lot-2", "kind": "building-lot", "polygon": [ [ 56, 6 ], [ 68, 6 ], [ 68, 18 ], [ 56, 18 ] ], "area": 144 }, { "id": "lot-3", "kind": "building-lot", "polygon": [ [ 36, 54 ], [ 46, 54 ], [ 46, 64 ], [ 36, 64 ] ], "area": 100 }, { "id": "lot-4", "kind": "building-lot", "polygon": [ [ 54, 54 ], [ 64, 54 ], [ 64, 60 ], [ 54, 60 ] ], "area": 60 }, { "id": "lot-5", "kind": "building-lot", "polygon": [ [ 22, 38 ], [ 34, 38 ], [ 34, 46 ], [ 22, 46 ] ], "area": 96 }, { "id": "spawn-w", "kind": "spawn", "polygon": [ [ 0, 44 ], [ 8, 44 ], [ 8, 56 ], [ 0, 56 ] ], "area": 48 } ], "plan": { "zones": [ { "zoneId": "market", "rules": [ { "kind": "anchor", "asset": "well", "at": "centroid" }, { "kind": "ring", "assets": [ "market_stall" ], "center": "centroid", "radius": 4.4, "count": 5, "facing": "inward" }, { "kind": "along", "assets": [ "lamp_post" ], "offset": [ 0.6, 1.2 ], "spacing": [ 9, 12 ], "facing": "toward" } ] }, { "zoneId": "forest-nw", "rules": [ { "kind": "scatter", "assets": [ "oak", "pine" ], "density": 0.6, "falloff": { "from": "edge", "strength": 0.5 } }, { "kind": "scatter", "assets": [ "bush" ], "density": 0.12 }, { "kind": "cluster", "assets": [ "rock" ], "clusters": 2, "count": 3, "radius": 3, "center": "random" } ] }, { "zoneId": "field-se", "rules": [ { "kind": "along", "assets": [ "fence" ], "offset": [ 0.35, 0.35 ], "spacing": [ 2.08, 2.08 ], "facing": "toward" }, { "kind": "scatter", "assets": [ "bush" ], "density": 0.04 } ] }, { "zoneId": "field-sw", "rules": [ { "kind": "along", "assets": [ "fence" ], "offset": [ 0.35, 0.35 ], "spacing": [ 2.08, 2.08 ], "facing": "toward" }, { "kind": "scatter", "assets": [ "bush" ], "density": 0.04 } ] }, { "zoneId": "lot-1", "rules": [ { "kind": "lot", "assets": [ "house_large", "house_small", "tavern" ] } ] }, { "zoneId": "lot-2", "rules": [ { "kind": "lot", "assets": [ "house_large", "house_small", "tavern" ] } ] }, { "zoneId": "lot-3", "rules": [ { "kind": "lot", "assets": [ "house_large", "house_small", "tavern" ] } ] }, { "zoneId": "lot-4", "rules": [ { "kind": "lot", "assets": [ "house_large", "house_small", "tavern" ] } ] }, { "zoneId": "lot-5", "rules": [ { "kind": "lot", "assets": [ "house_large", "house_small", "tavern" ] } ] }, { "zoneId": "spawn-w", "rules": [ { "kind": "ring", "assets": [ "lamp_post" ], "center": "centroid", "radius": 2, "count": 2, "facing": "inward" } ] }, { "zoneId": "open", "rules": [ { "kind": "scatter", "assets": [ "oak", "pine" ], "density": 0.1 }, { "kind": "scatter", "assets": [ "bush" ], "density": 0.07 }, { "kind": "scatter", "assets": [ "rock" ], "density": 0.03 } ] } ], "notes": "preset plan: fantasy-village" }, "placements": [ { "assetId": "well", "zoneId": "market", "position": { "x": 66.4794, "y": 0, "z": -40.7875 }, "rotation": { "quaternion": [ 0, 0, 0, 1 ], "eulerDeg": { "x": 0, "y": 0, "z": 0 } }, "scale": 1 }, { "assetId": "house_small", "zoneId": "lot-1", "position": { "x": 86, "y": 0, "z": -40 }, "rotation": { "quaternion": [ 0, 0, 0, 1 ], "eulerDeg": { "x": 0, "y": 0, "z": 0 } }, "scale": 1 }, { "assetId": "house_large", "zoneId": "lot-2", "position": { "x": 62, "y": 0, "z": -12 }, "rotation": { "quaternion": [ 0, 0.707107, 0, 0.707107 ], "eulerDeg": { "x": 0, "y": 90, "z": 0 } }, "scale": 1 }, { "assetId": "tavern", "zoneId": "lot-3", "position": { "x": 41, "y": 0, "z": -59 }, "rotation": { "quaternion": [ 0, -0.707107, 0, 0.707107 ], "eulerDeg": { "x": 0, "y": -90, "z": 0 } }, "scale": 1 }, { "assetId": "house_small", "zoneId": "lot-4", "position": { "x": 59, "y": 0, "z": -57 }, "rotation": { "quaternion": [ 0, 0.707107, 0, 0.707107 ], "eulerDeg": { "x": 0, "y": 90, "z": 0 } }, "scale": 1 } ], "stats": { "total": 295, "byCategory": { "prop": 5, "house": 5, "light": 7, "fence": 116, "rock": 10, "tree": 43, "bush": 109 }, "overlaps": 0, "reachable": true, "removedForReachability": [] }, "previews": { "topDown": "https://rengi.dev/files/example/top-down.png", "perspective": "https://rengi.dev/files/example/perspective.png", "ground": "https://rengi.dev/files/example/ground.png" }, "viewer": "https://rengi.dev/files/example/viewer.html", "sceneJson": "https://rengi.dev/files/example/scene.json", "note": "placements trimmed to 5 of 295 for the example", "diff": { "added": 14, "removed": 3, "moved": 0, "kept": 120 } } ``` ### POST /v1/level-design/place-2d Fill a 2D tilemap: terrain with proper corner transitions, decorations, obstacles and multi-tile stamps; Tiled .tmj, Unity Tilemap JSON and a preview. Price: $1.00 USDC. Time limit: 90 s. Example request: ```json { "tileset": { "imageUrl": "https://rengi.dev/samples/tileset.png", "tileWidth": 16, "tileHeight": 16 }, "tileRoles": { "terrains": [ { "name": "grass", "tiles": [ { "id": 0, "weight": 4 }, { "id": 1, "weight": 1 } ] }, { "name": "dirt", "tiles": [ { "id": 2 } ] } ], "sets": [ { "kind": "corner16", "over": "dirt", "under": "grass", "firstTile": 8 } ], "decorations": [ { "id": 59, "name": "tree", "layer": "obstacle", "tags": [ "tree" ] } ], "stamps": [ { "name": "house", "width": 2, "height": 2, "tiles": [ 62, 63, 70, 71 ], "tags": [ "house" ] } ], "terrainFor": { "road": "dirt", "default": "grass" } }, "layout": { "kind": "zones", "width": 48, "height": 32, "zones": [ { "id": "road", "kind": "road", "polyline": [ [ 0, 16 ], [ 48, 16 ] ], "width": 3 }, { "id": "woods", "kind": "forest", "polygon": [ [ 0, 0 ], [ 20, 0 ], [ 20, 12 ], [ 0, 12 ] ] } ], "requiredPoints": [] }, "seed": 1 } ``` Example response: ```json { "jobId": "job2d_0123456789abcdef0123", "width": 48, "height": 32, "tiled": "https://rengi.dev/files//map.tmj", "unity": "https://rengi.dev/files//map.unity.json", "preview": "https://rengi.dev/files//preview.png" } ``` ### POST /v1/level-design/revise-2d Change a 2D map by instruction or zone edits; untouched zones keep their tiles. Price: $0.30 USDC. Time limit: 60 s. Example request: ```json { "jobId": "job2d_0123456789abcdef0123", "instruction": "denser forest" } ``` Example response: ```json { "jobId": "job2d_fedcba9876543210fedc", "diff": { "changedCells": 41 } } ``` ### GET /v1/level-design/example A full worked request and response from the bundled fixtures, free. Price: free. Time limit: 5 s. Example request: ``` GET https://rengi.dev/v1/level-design/example ``` Example response: ```json { "request": "...", "response": "..." } ``` ## Asset render (`asset-render`) Pictures of a 3D model for agents that cannot see: catalog views, a turntable GIF, and isometric sprite sheets for 2.5D games. Send a GLB; the model is auto-framed from its real bounds, and every answer includes mesh stats (triangles, materials, bounds, up axis). Schemas: https://rengi.dev/v1/asset-render/schema ### POST /v1/asset-render/views Four PNG views (three-quarter, front, side, top) plus mesh stats. Price: $0.10 USDC. Time limit: 60 s. Example request: ```json { "glbUrl": "https://rengi.dev/samples/house.glb", "size": 512 } ``` Example response: ```json { "views": { "threeQuarter": "https://rengi.dev/files//three-quarter.png", "front": "...", "side": "...", "top": "..." }, "stats": { "triangles": 172, "vertices": 516, "primitives": 3, "materials": 3, "bounds": { "min": [ -2.6, 0, -3.1 ], "max": [ 2.6, 5, 3.1 ] }, "height": 5, "footprintRadius": 3.62, "upAxis": "y", "upAxisGuessed": true } } ``` ### POST /v1/asset-render/turntable Looping turntable GIF, one full revolution, plus mesh stats. Price: $0.25 USDC. Time limit: 90 s. Example request: ```json { "glbUrl": "https://rengi.dev/samples/house.glb", "frames": 36 } ``` Example response: ```json { "gif": "https://rengi.dev/files//turntable.gif", "frames": 36, "stats": { "triangles": 172, "vertices": 516, "primitives": 3, "materials": 3, "bounds": { "min": [ -2.6, 0, -3.1 ], "max": [ 2.6, 5, 3.1 ] }, "height": 5, "footprintRadius": 3.62, "upAxis": "y", "upAxisGuessed": true } } ``` ### POST /v1/asset-render/sprites Transparent isometric sprite sheet, 4 or 8 directions in one row (south first, clockwise), with frame JSON. Price: $0.40 USDC. Time limit: 60 s. Example request: ```json { "glbUrl": "https://rengi.dev/samples/knight.glb", "directions": 8, "cellSize": 128 } ``` Example response: ```json { "sheet": "https://rengi.dev/files//sprites.png", "json": "https://rengi.dev/files//sprites.json", "cellSize": 128, "frames": [ { "direction": "south", "x": 0, "y": 0, "w": 128, "h": 128 } ], "stats": { "triangles": 172, "vertices": 516, "primitives": 3, "materials": 3, "bounds": { "min": [ -2.6, 0, -3.1 ], "max": [ 2.6, 5, 3.1 ] }, "height": 5, "footprintRadius": 3.62, "upAxis": "y", "upAxisGuessed": true } } ``` ## Sprite tools (`sprite-tools`) 2D sprite jobs for games, deterministic and cheap: slice a sheet into frames (grid or automatic by transparency), pack frames into an atlas with TexturePacker and Unity metadata, and turn upscaled or AI-generated pixel art into real pixel art on its true grid with a limited palette. Schemas: https://rengi.dev/v1/sprite-tools/schema ### POST /v1/sprite-tools/slice Cut a sprite sheet into frames by grid or by transparent gaps; frame PNGs plus a ZIP. Price: $0.05 USDC. Time limit: 45 s. Example request: ```json { "imageUrl": "https://rengi.dev/samples/sheet.png", "mode": "grid", "cols": 8, "rows": 4 } ``` Example response: ```json { "frames": [ { "name": "frame_000", "rect": { "x": 0, "y": 0, "w": 64, "h": 64 }, "trim": { "x": 0, "y": 0, "sourceW": 64, "sourceH": 64 }, "url": "https://rengi.dev/files//frames/frame_000.png" } ], "zip": "https://rengi.dev/files//frames.zip" } ``` ### POST /v1/sprite-tools/pack Pack frames into one atlas (MaxRects) with padding and edge extrusion; TexturePacker JSON and Unity JSON. Price: $0.05 USDC. Time limit: 45 s. Example request: ```json { "frames": [ { "name": "run_0", "imageUrl": "https://rengi.dev/samples/run_0.png" }, { "name": "run_1", "imageUrl": "https://rengi.dev/samples/run_1.png" } ], "padding": 2, "extrude": 1 } ``` Example response: ```json { "atlas": "https://rengi.dev/files//atlas.png", "width": 136, "height": 68, "texturepacker": "https://rengi.dev/files//atlas.json", "unity": "https://rengi.dev/files//atlas.unity.json", "rects": [ { "name": "run_0", "x": 2, "y": 2, "w": 64, "h": 64, "trim": { "x": 0, "y": 0, "sourceW": 64, "sourceH": 64 } } ] } ``` ### POST /v1/sprite-tools/pixelate Clean pixel art: find the true pixel grid, downscale to it, snap to a palette, hard alpha. Price: $0.10 USDC. Time limit: 45 s. Example request: ```json { "imageUrl": "https://rengi.dev/samples/ai-knight.png", "colors": 16 } ``` Example response: ```json { "image": "https://rengi.dev/files//pixel.png", "preview": "https://rengi.dev/files//preview.png", "width": 32, "height": 32, "scale": 8, "scaleDetected": true, "offset": { "x": 0, "y": 0 }, "palette": [ "#1a1c2c", "#5d275d" ] } ``` ## GLB optimizer (`glb-optimizer`) Make a GLB small and fast for the web or mobile: dedup, instance, join, weld, simplify, resize and re-encode textures, meshopt or draco compression. Returns the new file plus before/after numbers, a validator pass and a visual difference score from renders of both files. Animations, skins and morph targets are kept. Schemas: https://rengi.dev/v1/glb-optimizer/schema ### POST /v1/glb-optimizer/optimize Optimize a GLB up to 10 MB with a preset (web, mobile, preview). Price: $0.20 USDC. Time limit: 90 s. Example request: ```json { "glbUrl": "https://rengi.dev/samples/castle.glb", "preset": "web" } ``` Example response: ```json { "glb": "https://rengi.dev/files//optimized.glb", "before": { "fileBytes": 18400000, "triangles": 420000, "vertices": 260000, "primitives": 84, "drawCalls": 84, "meshes": 84, "materials": 12, "textures": 9, "textureMemoryBytes": 600000000, "animations": 0, "skins": 0, "morphTargets": 0 }, "after": { "fileBytes": 2100000, "triangles": 180000, "vertices": 260000, "primitives": 84, "drawCalls": 14, "meshes": 14, "materials": 12, "textures": 9, "textureMemoryBytes": 150000000, "animations": 0, "skins": 0, "morphTargets": 0 }, "savedPercent": 88.6, "steps": { "applied": [ "dedup", "prune", "instance", "join", "weld", "simplify (error 0.001)", "textures (max 2048, webp)", "meshopt compression" ], "skipped": [] }, "visual": { "difference": 0.012, "ok": true, "beforeUrl": "https://rengi.dev/files//before.png", "afterUrl": "https://rengi.dev/files//after.png" }, "validation": { "errors": 0, "warnings": 0, "messages": [] }, "loaderNote": "Uses EXT_meshopt_compression: ..." } ``` ### POST /v1/glb-optimizer/optimize-large Same as optimize, for GLBs up to 50 MB. Price: $0.50 USDC. Time limit: 120 s. Example request: ```json { "glbUrl": "https://rengi.dev/samples/castle.glb", "preset": "web" } ``` Example response: ```json { "glb": "https://rengi.dev/files//optimized.glb", "before": { "fileBytes": 18400000, "triangles": 420000, "vertices": 260000, "primitives": 84, "drawCalls": 84, "meshes": 84, "materials": 12, "textures": 9, "textureMemoryBytes": 600000000, "animations": 0, "skins": 0, "morphTargets": 0 }, "after": { "fileBytes": 2100000, "triangles": 180000, "vertices": 260000, "primitives": 84, "drawCalls": 14, "meshes": 14, "materials": 12, "textures": 9, "textureMemoryBytes": 150000000, "animations": 0, "skins": 0, "morphTargets": 0 }, "savedPercent": 88.6, "steps": { "applied": [ "dedup", "prune", "instance", "join", "weld", "simplify (error 0.001)", "textures (max 2048, webp)", "meshopt compression" ], "skipped": [] }, "visual": { "difference": 0.012, "ok": true, "beforeUrl": "https://rengi.dev/files//before.png", "afterUrl": "https://rengi.dev/files//after.png" }, "validation": { "errors": 0, "warnings": 0, "messages": [] }, "loaderNote": "Uses EXT_meshopt_compression: ..." } ``` ### POST /v1/glb-optimizer/inspect Report on a GLB without changing it, with concrete suggestions. Price: $0.05 USDC. Time limit: 45 s. Example request: ```json { "glbUrl": "https://rengi.dev/samples/castle.glb" } ``` Example response: ```json { "report": { "fileBytes": 18400000, "triangles": 420000, "vertices": 260000, "primitives": 84, "drawCalls": 84, "meshes": 84, "materials": 12, "textures": 9, "textureMemoryBytes": 600000000, "animations": 0, "skins": 0, "morphTargets": 0 }, "suggestions": [ "Textures take about 572 MB of GPU memory; resize to 2048 or less (1024 on mobile).", "420,000 triangles is heavy for the web; simplify or add LODs.", "84 draw calls; join meshes that share a material or instance repeated ones.", "Many separate meshes; check for repeated geometry that could be instanced.", "No mesh compression; meshopt usually cuts geometry size by 3-10x." ], "validation": { "errors": 0, "warnings": 3, "messages": [] } } ``` ## Leaderboard (`leaderboard`) A leaderboard backend for a game in one paid call, no signup: buy a board (100,000 submissions, 1 year), get a board id, a submit key for the game client and an admin key. The game then submits and reads scores with plain free HTTP (CORS open). Keeps each player's best per period (all-time, daily, weekly), ranks any player, rejects out-of-bounds and spammy scores, optional HMAC-signed submissions. Schemas: https://rengi.dev/v1/leaderboard/schema ### POST /v1/leaderboard/boards Create a board with 100,000 submissions and 365 days; returns keys and a ready JS snippet. Price: $1.00 USDC. Time limit: 10 s. Example request: ```json { "name": "Endless Runner", "sort": "desc", "minScore": 0, "maxScore": 1000000, "periods": [ "alltime", "daily" ] } ``` Example response: ```json { "boardId": "lb_0123456789abcdef", "submitKey": "sk_...", "adminKey": "ak_...", "quota": 100000, "expiresAt": "2027-10-20T00:00:00.000Z", "periods": [ "alltime", "daily" ], "snippet": "const LB = { ... }", "note": "The admin key is shown once. Ship only the submit key in the game." } ``` ### POST /v1/leaderboard/topup Add 100,000 submissions and 365 days to a board. Price: $1.00 USDC. Time limit: 10 s. Example request: ```json { "boardId": "lb_0123456789abcdef", "adminKey": "ak_..." } ``` Example response: ```json { "boardId": "lb_0123456789abcdef", "quota": 200000, "used": 91234, "expiresAt": "2028-10-20T00:00:00.000Z" } ``` ### POST /v1/leaderboard/submit Submit a score from the game (free, needs the submit key). Returns the player's rank per period. Price: free. Time limit: 5 s. Example request: ```json { "boardId": "lb_0123456789abcdef", "submitKey": "sk_...", "playerId": "p-42", "playerName": "Ana", "score": 1234 } ``` Example response: ```json { "ranks": { "alltime": { "rank": 7, "best": 1234 } }, "remainingQuota": 99812 } ``` ### GET /v1/leaderboard/top Top entries for a period (free). Price: free. Time limit: 5 s. Example request: ``` GET https://rengi.dev/v1/leaderboard/top?boardId=lb_0123456789abcdef&period=alltime&limit=10 ``` Example response: ```json { "board": "Endless Runner", "period": "alltime", "entries": [ { "rank": 1, "playerId": "p-1", "playerName": "Kim", "score": 99120 } ] } ``` ### GET /v1/leaderboard/rank One player's rank and the five entries around them (free). Price: free. Time limit: 5 s. Example request: ``` GET https://rengi.dev/v1/leaderboard/rank?boardId=lb_0123456789abcdef&period=alltime&playerId=p-42 ``` Example response: ```json { "rank": 7, "score": 1234, "around": [] } ``` ### POST /v1/leaderboard/admin Admin actions with the admin key: reset a period, delete a player, rotate the submit key, read the signing secret (free). Price: free. Time limit: 5 s. Example request: ```json { "boardId": "lb_0123456789abcdef", "adminKey": "ak_...", "action": "delete-player", "playerId": "cheater-1" } ``` Example response: ```json { "ok": true } ```