# 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 ## Quickstart TypeScript (`npm i @x402/fetch @x402/evm viem`), PRIVATE_KEY = a wallet with a little USDC on Base: ```ts import { wrapFetchWithPaymentFromConfig } from "@x402/fetch"; import { ExactEvmScheme } from "@x402/evm/exact/client"; import { privateKeyToAccount } from "viem/accounts"; const account = privateKeyToAccount(process.env.PRIVATE_KEY as `0x${string}`); const pay = wrapFetchWithPaymentFromConfig(fetch, { schemes: [{ network: "eip155:8453", client: new ExactEvmScheme(account) }] }); const res = await pay("https://rengi.dev/v1/sprite-tools/remove-bg", { method: "POST", headers: { "content-type": "application/json" }, body: JSON.stringify({ imageUrl: "https://rengi.dev/samples/prop-on-white.png" }), }); console.log(await res.json()); // { image: , mode, ... } ``` Python (`pip install "x402[httpx,evm]"`): ```python import asyncio, os from eth_account import Account from x402 import SchemeRegistration, x402ClientConfig from x402.http.clients import wrapHttpxWithPaymentFromConfig from x402.mechanisms.evm.exact import ExactEvmScheme signer = Account.from_key(os.environ["PRIVATE_KEY"]) config = x402ClientConfig(schemes=[SchemeRegistration(network="eip155:8453", client=ExactEvmScheme(signer=signer))]) async def main(): async with wrapHttpxWithPaymentFromConfig(config, timeout=180) as http: r = await http.post("https://rengi.dev/v1/sprite-tools/remove-bg", json={"imageUrl": "https://rengi.dev/samples/prop-on-white.png"}) print(r.json()) asyncio.run(main()) ``` ## 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 by instruction or structured zone edits: denser or sparser, other assets, remove a kind of prop; untouched zones keep their exact transforms. It cannot cut an empty area inside a zone or move one object: for that, add a keep-clear zone to the layout and place again. Price: $0.50 USDC. Time limit: 60 s. Example request: ```json { "jobId": "job_0123456789abcdef0123", "instruction": "make the market denser" } ``` 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 Render a GLB model to four PNG views (three-quarter, front, side, top) for thumbnails and previews, plus mesh stats and size. 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 Render a GLB model as a 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: cut sprites out of their background (exact for one-color backgrounds, AI for busy ones), turn animation videos into aligned sprite sheets, make normal maps for 2D lights, build 47-tile autotile sets with Tiled, Godot and Unity rules, slice a sheet into frames, 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" ] } ``` ### POST /v1/sprite-tools/remove-bg Cut a sprite, prop or character out of its background: exact keying for one-color backgrounds (text and holes too), AI segmentation for busy ones; clean edges with no halo, trimmed, with a pivot. AI mode handles one main subject, not text on photos. Price: $0.05 USDC. Time limit: 90 s. Example request: ```json { "imageUrl": "https://rengi.dev/samples/prop-on-white.png" } ``` Example response: ```json { "image": "https://rengi.dev/files//sprite.png", "mask": "https://rengi.dev/files//mask.png", "preview": "https://rengi.dev/files//preview.png", "mode": "flat", "backgroundColor": "#ffffff", "width": 420, "height": 610, "box": { "x": 302, "y": 140, "w": 416, "h": 606 }, "pivot": { "x": 0.5, "y": 0.0033 }, "pivotPx": { "x": 210, "y": 608 }, "warnings": [] } ``` ### POST /v1/sprite-tools/video-to-sheet Turn an animation video or GIF (from Kling, Veo, Sora or a capture) into a sprite sheet: frames at your fps, background removed, every frame aligned to one box and pivot so it does not jitter, the best loop point, TexturePacker JSON, Godot SpriteFrames and a GIF preview. Price: $0.15 USDC. Time limit: 170 s. Example request: ```json { "videoUrl": "https://rengi.dev/samples/slime-jump.mp4", "fps": 12 } ``` Example response: ```json { "sheet": "https://rengi.dev/files//sheet.png", "frames": "https://rengi.dev/files//frames.zip", "texturepacker": "https://rengi.dev/files//sheet.json", "godot": "https://rengi.dev/files//sheet.tres", "preview": "https://rengi.dev/files//preview.gif", "frameCount": 12, "frameWidth": 192, "frameHeight": 160, "columns": 4, "fps": 12, "background": "flat", "pivot": { "x": 0.5, "y": 0.0125 }, "loop": { "frames": 12, "difference": 0.012 }, "warnings": [] } ``` ### POST /v1/sprite-tools/normal-map Normal map for a sprite or sprite sheet, for 2D lights in Unity URP 2D and Godot: a rounded bevel from the silhouette plus surface detail, alpha kept, OpenGL or DirectX; a height map and a preview lit by a moving light. Price: $0.05 USDC. Time limit: 60 s. Example request: ```json { "imageUrl": "https://rengi.dev/samples/orb.png", "strength": 1 } ``` Example response: ```json { "normal": "https://rengi.dev/files//normal.png", "height": "https://rengi.dev/files//height.png", "preview": "https://rengi.dev/files//lit.gif", "width": 128, "height_px": 128, "bevel": 28, "convention": "opengl" } ``` ### POST /v1/sprite-tools/autotile Two terrain textures (grass over dirt, sand over water) to a full 47-tile autotile set with natural, seamless edges, outer and inner corners, plus ready rules: Tiled wang set, Godot 4 TileSet terrains, Unity Rule Tile (editor script), JSON, and a painted preview map. Price: $0.15 USDC. Time limit: 60 s. Example request: ```json { "baseUrl": "https://rengi.dev/samples/dirt.png", "topUrl": "https://rengi.dev/samples/grass.png", "tileSize": 32 } ``` Example response: ```json { "tileset": "https://rengi.dev/files//tileset.png", "preview": "https://rengi.dev/files//preview.png", "zip": "https://rengi.dev/files//autotile.zip", "json": "https://rengi.dev/files//autotile.json", "tiled": "https://rengi.dev/files//tileset.tsx", "godot": "https://rengi.dev/files//tileset.tres", "unityMeta": "https://rengi.dev/files//tileset.png.meta", "unityScript": "https://rengi.dev/files//RengiAutotile.cs", "tiles": 48, "tileSize": 32, "columns": 8, "madeSeamless": [], "howTo": { "tiled": "Add tileset.tsx to a map and paint with the Terrain brush (wang set 'terrain')." } } ``` ## 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 Shrink a GLB (up to 10 MB) for web or mobile: dedup, join draw calls, gentle simplify, textures to WebP at a max size, meshopt or Draco compression; before/after renders, size report and loader notes for three.js and Unity. 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 Shrink a large GLB (up to 50 MB) for web or mobile, same pipeline as optimize: dedup, join, simplify, WebP textures, meshopt or Draco. 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 Inspect a GLB without changing it: triangles, draw calls, materials, texture memory, animations, glTF validator errors, and concrete suggestions to make it lighter. 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": [] } } ``` ### POST /v1/glb-optimizer/convert Convert FBX, OBJ (zip with .mtl and textures), glTF (zip), STL, PLY, DAE or 3DS to one GLB: Y-up, in meters, materials and FBX animations kept. Returns the GLB, a report, a validator pass and a preview render. Price: $0.15 USDC. Time limit: 120 s. Example request: ```json { "fileUrl": "https://rengi.dev/samples/crate.fbx" } ``` Example response: ```json { "glb": "https://rengi.dev/files//model.glb", "preview": "https://rengi.dev/files//preview.png", "format": "fbx", "upAxis": "y", "unitScale": 1, "sizeMeters": [ 1, 2, 0.5 ], "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 }, "validation": { "errors": 0, "warnings": 0, "messages": [] }, "warnings": [] } ``` ### POST /v1/glb-optimizer/lod Generate a LOD chain from a GLB (default 100/50/25/10% of triangles) with locked borders so UV seams and silhouettes hold; one GLB per level, a side-by-side render and Unity LODGroup transition heights. Price: $0.20 USDC. Time limit: 120 s. Example request: ```json { "glbUrl": "https://rengi.dev/samples/castle.glb" } ``` Example response: ```json { "lods": [ { "level": 0, "ratio": 1, "triangles": 96000, "glb": "https://rengi.dev/files//lod0.glb" }, { "level": 1, "ratio": 0.5, "triangles": 48010, "glb": "https://rengi.dev/files//lod1.glb" } ], "sourceTriangles": 96000, "sheet": "https://rengi.dev/files//lods.png", "unityTransitions": [ 0.6, 0.3, 0.15, 0.02 ], "warnings": [] } ``` ### POST /v1/glb-optimizer/colliders Collision for a model: a set of convex hulls that hug the shape (V-HACD), ready for Godot (-convcolonly nodes), Unreal (UCX_ names) and Unity (convex MeshColliders via an editor script), plus hulls.json for any engine and a see-through overlay to check. Price: $0.15 USDC. Time limit: 150 s. Example request: ```json { "glbUrl": "https://rengi.dev/samples/table.glb", "maxHulls": 16 } ``` Example response: ```json { "overlay": "https://rengi.dev/files//overlay.glb", "godot": "https://rengi.dev/files//godot.glb", "unreal": "https://rengi.dev/files//unreal.glb", "unity": "https://rengi.dev/files//unity.glb", "unityScript": "https://rengi.dev/files//RengiColliders.cs", "hullsJson": "https://rengi.dev/files//hulls.json", "preview": "https://rengi.dev/files//preview.png", "hulls": 5, "hullTriangles": 60, "volumeRatio": 1.04, "simple": { "box": { "center": [ 0, 0.4, 0 ], "size": [ 1.2, 0.8, 0.7 ] } }, "howTo": { "godot": "Import godot.glb: nodes ending in -convcolonly become StaticBody3D convex shapes." } } ``` ## Texture tools (`texture-tools`) Turn a picture into a game-ready material: seamless tiling without visible seams or light bands, PBR maps (normal for Unity and Unreal, height, roughness, AO) from one image, channel packing for Unreal ORM and Unity masks, and texture atlases with mip-safe gutters. Works on generated or photographed textures; it does not generate images. Schemas: https://rengi.dev/v1/texture-tools/schema ### POST /v1/texture-tools/seamless Make a texture tile without visible seams: removes baked lighting, hides the seam along the path where the image already matches. Returns the tile and a 2x2 preview. Price: $0.10 USDC. Time limit: 60 s. Example request: ```json { "imageUrl": "https://rengi.dev/samples/stone.png", "delight": true } ``` Example response: ```json { "tile": "https://rengi.dev/files//tile.png", "preview": "https://rengi.dev/files//preview-2x2.png", "width": 450, "height": 450, "seamScore": 1.02 } ``` ### POST /v1/texture-tools/pbr PBR maps from one albedo image: normal (OpenGL for Unity/three.js and DirectX for Unreal), 16-bit height, roughness and ambient occlusion, plus a lit preview. Price: $0.15 USDC. Time limit: 90 s. Example request: ```json { "imageUrl": "https://rengi.dev/samples/stone-tile.png", "normalStrength": 2 } ``` Example response: ```json { "maps": { "albedo": "https://rengi.dev/files//albedo.png", "normal": "https://rengi.dev/files//normal-gl.png", "normalDx": "https://rengi.dev/files//normal-dx.png", "height": "https://rengi.dev/files//height.png", "roughness": "https://rengi.dev/files//roughness.png", "ao": "https://rengi.dev/files//ao.png" }, "preview": "https://rengi.dev/files//lit-preview.png", "width": 512, "height": 512, "notes": "normal is OpenGL (green up) for Unity and three.js; normalDx is for Unreal." } ``` ### POST /v1/texture-tools/pack Pack grayscale maps into one texture for an engine preset: Unreal ORM, Unity URP metallic/smoothness, Unity HDRP mask map. Missing maps get sensible constants. Price: $0.05 USDC. Time limit: 60 s. Example request: ```json { "preset": "unreal-orm", "roughness": { "imageUrl": "https://rengi.dev/samples/stone.png" } } ``` Example response: ```json { "image": "https://rengi.dev/files//packed-unreal-orm.png", "width": 512, "height": 512, "channels": { "r": "ao (constant 1)", "g": "roughness", "b": "metallic (constant 0)", "a": "unused" }, "notes": "Unreal ORM: R ambient occlusion, G roughness, B metallic." } ``` ### POST /v1/texture-tools/atlas Pack textures into one atlas with edge-filled gutters so mipmaps do not bleed; UV rects for bottom-left (Unity, OpenGL) and top-left (DirectX, Unreal) origins. Price: $0.05 USDC. Time limit: 90 s. Example request: ```json { "textures": [ { "name": "stone", "imageUrl": "https://rengi.dev/samples/stone-tile.png" }, { "name": "crate", "imageUrl": "https://rengi.dev/samples/crate.png" } ], "padding": 8 } ``` Example response: ```json { "atlas": "https://rengi.dev/files//atlas.png", "width": 1024, "height": 512, "rects": [ { "name": "stone", "x": 8, "y": 8, "w": 450, "h": 450, "uv": { "u0": 0.0078, "v0": 0.1094, "u1": 0.4473, "v1": 0.9844 }, "uvTopLeft": { "u0": 0.0078, "v0": 0.0156, "u1": 0.4473, "v1": 0.8906 } } ], "json": "https://rengi.dev/files//atlas.json" } ``` ## Audio tools (`audio-tools`) Make generated or recorded sounds game-ready: trim silence and match loudness (LUFS with a true-peak ceiling), seamless loops for music and ambience with loop points, and SFX variations. Outputs ogg, wav or mp3 with a waveform. It does not generate audio. Schemas: https://rengi.dev/v1/audio-tools/schema ### POST /v1/audio-tools/clean Trim silence, normalize loudness to a LUFS target with a -1 dBTP ceiling, add anti-click fades and convert (ogg, wav, mp3; mono for SFX). Returns the file, a waveform and measured stats. Price: $0.05 USDC. Time limit: 120 s. Example request: ```json { "audioUrl": "https://rengi.dev/samples/hit.wav", "kind": "sfx", "format": "ogg" } ``` Example response: ```json { "file": "https://rengi.dev/files//clean.ogg", "waveform": "https://rengi.dev/files//waveform.png", "stats": { "durationSec": 0.42, "sampleRate": 44100, "channels": 1, "integratedLufs": -16.1, "truePeakDb": -1.2 }, "before": { "durationSec": 1.5, "integratedLufs": -27.3 }, "limitedByPeak": false } ``` ### POST /v1/audio-tools/loop Turn music or ambience into a seamless loop: cuts at zero crossings and crossfades the end into the start with an equal-power curve. Returns the loop, a 3x preview and loop points in samples. Price: $0.10 USDC. Time limit: 120 s. Example request: ```json { "audioUrl": "https://rengi.dev/samples/ambience.wav", "crossfadeMs": 250 } ``` Example response: ```json { "file": "https://rengi.dev/files//loop.ogg", "preview": "https://rengi.dev/files//loop-x3.ogg", "waveform": "https://rengi.dev/files//waveform.png", "loopStartSample": 0, "loopEndSample": 211500, "sampleRate": 44100, "durationSec": 4.8 } ``` ### POST /v1/audio-tools/variations Make 2-12 variations of one sound effect with small pitch and volume changes, so repeated footsteps or hits do not sound copy-pasted. Returns each file and a ZIP. Price: $0.10 USDC. Time limit: 120 s. Example request: ```json { "audioUrl": "https://rengi.dev/samples/hit.wav", "count": 5 } ``` Example response: ```json { "variations": [ { "name": "hit_01", "file": "https://rengi.dev/files//hit_01.ogg", "semitones": -1.2, "gainDb": 0.8, "durationSec": 0.48 } ], "zip": "https://rengi.dev/files//variations.zip", "waveform": "https://rengi.dev/files//waveform.png" } ``` ### POST /v1/audio-tools/voice Make a voice recording or TTS take game-ready: rumble high-passed, noise reduced against the measured floor, sibilance tamed, dialogue loudness (-18 LUFS) with a -1 dBTP ceiling, and a long take split into one file per phrase with a CSV cue sheet. Price: $0.10 USDC. Time limit: 150 s. Example request: ```json { "audioUrl": "https://rengi.dev/samples/voice-take.wav" } ``` Example response: ```json { "file": "https://rengi.dev/files//voice.ogg", "lines": [ { "file": "https://rengi.dev/files//lines/line_001.ogg", "start": 0.54, "end": 1.76, "durationSec": 1.22 } ], "csv": "https://rengi.dev/files//lines.csv", "zip": "https://rengi.dev/files//voice.zip", "waveformBefore": "https://rengi.dev/files//waveform-before.png", "waveform": "https://rengi.dev/files//waveform.png", "stats": { "durationSec": 7, "sampleRate": 48000, "channels": 1, "integratedLufs": -18, "truePeakDb": -2.1 }, "noiseFloor": { "beforeDb": -52.3, "afterDb": -71.8 }, "limitedByPeak": false, "warnings": [] } ``` ## Store assets (`store-assets`) Release art from one key art: every Steam store and library capsule at the exact required size with your logo placed per Steam's rules (never on the Library Hero), and full icon sets for iOS, Android adaptive icons, Google Play and the web. Schemas: https://rengi.dev/v1/store-assets/schema ### POST /v1/store-assets/steam Every Steam store and library capsule from one key art at the exact required sizes: logo composited per Steam rules, Library Hero without logo, separate transparent Library Logo, page background, a contact sheet and a ZIP. Price: $0.20 USDC. Time limit: 120 s. Example request: ```json { "keyArt": { "imageUrl": "https://rengi.dev/samples/key-art.png" }, "logo": { "imageUrl": "https://rengi.dev/samples/logo.png" } } ``` Example response: ```json { "files": { "header": "https://rengi.dev/files//header_capsule.png", "small": "https://rengi.dev/files//small_capsule.png", "main": "https://rengi.dev/files//main_capsule.png", "vertical": "https://rengi.dev/files//vertical_capsule.png", "libraryCapsule": "https://rengi.dev/files//library_capsule.png", "libraryHeader": "https://rengi.dev/files//library_header.png", "libraryHero": "https://rengi.dev/files//library_hero.png", "pageBackground": "https://rengi.dev/files//page_background.png", "libraryLogo": "https://rengi.dev/files//library_logo.png" }, "contactSheet": "https://rengi.dev/files//contact_sheet.png", "zip": "https://rengi.dev/files//steam_assets.zip", "warnings": [] } ``` ### POST /v1/store-assets/icons App icons from one square art: iOS 1024 with Contents.json, Android adaptive icon layers at every density plus legacy and Play Store 512, and web favicons with a manifest snippet. Preview with the masks launchers apply. Price: $0.10 USDC. Time limit: 120 s. Example request: ```json { "art": { "imageUrl": "https://rengi.dev/samples/icon-art.png" }, "name": "My Game" } ``` Example response: ```json { "ios": { "icon": "https://rengi.dev/files//ios/AppIcon-1024.png", "contentsJson": "https://rengi.dev/files//ios/Contents.json" }, "android": { "playStore": "https://rengi.dev/files//android/play_store_512.png", "foreground": "https://rengi.dev/files//android/mipmap-xxxhdpi/ic_launcher_foreground.png", "background": "https://rengi.dev/files//android/mipmap-xxxhdpi/ic_launcher_background.png", "adaptiveXml": "https://rengi.dev/files//android/mipmap-anydpi-v26/ic_launcher.xml" }, "web": { "favicon32": "https://rengi.dev/files//web/favicon-32.png", "appleTouch": "https://rengi.dev/files//web/apple-touch-icon.png", "icon512": "https://rengi.dev/files//web/icon-512.png", "manifest": "https://rengi.dev/files//web/site.webmanifest" }, "preview": "https://rengi.dev/files//preview.png", "zip": "https://rengi.dev/files//icons.zip", "warnings": [] } ``` ### POST /v1/store-assets/stores One key art and logo to the store images beyond Steam: itch.io cover 630x500, Google Play feature graphic 1024x500, Epic landscape 2560x1440 and portrait 1200x1600; gameplay screenshots fitted to Google Play 1920x1080 and App Store iPhone 6.9", 6.3" and iPad 13" sizes without stretching, no alpha where stores reject it. Price: $0.20 USDC. Time limit: 120 s. Example request: ```json { "keyArt": { "imageUrl": "https://rengi.dev/samples/key-art.png" }, "logo": { "imageUrl": "https://rengi.dev/samples/logo.png" } } ``` Example response: ```json { "files": { "itch/cover.png": "https://rengi.dev/files//itch/cover.png", "googlePlay/feature_graphic.png": "https://rengi.dev/files//googlePlay/feature_graphic.png" }, "contactSheet": "https://rengi.dev/files//contact_sheet.png", "zip": "https://rengi.dev/files//stores.zip", "warnings": [] } ``` ## Font tools (`font-tools`) Turn a TTF/OTF font into a bitmap font for games: crisp pixel-perfect glyphs for pixel art or smooth antialiased ones, Latin and Cyrillic, optional outline, atlas PNG plus AngelCode BMFont .fnt with kerning (Unity, Godot, Phaser, LibGDX) and JSON. Schemas: https://rengi.dev/v1/font-tools/schema ### POST /v1/font-tools/bitmap Bitmap font from a TTF/OTF: atlas PNG, BMFont .fnt with kerning, JSON and a preview of a sample line. Pixel mode snaps glyphs to whole pixels with no antialiasing. Price: $0.10 USDC. Time limit: 90 s. Example request: ```json { "fontUrl": "https://rengi.dev/samples/DejaVuSans.ttf", "size": 16, "mode": "pixel", "charset": "cyrillic" } ``` Example response: ```json { "atlas": "https://rengi.dev/files//font.png", "fnt": "https://rengi.dev/files//font.fnt", "json": "https://rengi.dev/files//font.json", "preview": "https://rengi.dev/files//preview.png", "width": 256, "height": 128, "glyphs": 191, "missing": [], "lineHeight": 19, "base": 15 } ``` ## 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 } ```