Servidor MCP

spriteship

com.spriteship/spriteship

Qué hace este MCP

Generates and manages 2D game characters, assets, animations, tilesets, UI packs, maps, and engine-ready exports for multiple game engines.

animate_asset
Animate an asset
PAID (image-to-video; Wan 3.0 costs 150 credits/second, so each default 2-second pair is 300 credits; total cost scales with duration × pair count). Animate ANY asset type — the animation lands on the source asset and its still image is preserved. For grid assets (tileset/staged) pass pairs of tile indices; a self-loop { from: n, to: n } makes one tile loop seamlessly. ASK THE USER WHICH STAGES FIRST. Call get_asset, describe the tiles you can see, and get an explicit answer on which is the START and which is the END before you spend. "Animate the treasure box" does not tell you whether they mean closed→open, open→closed, or the lid alone, and guessing wrong bills them for a clip they cannot use. The server rejects a grid animate with no pairs (400) precisely so that this choice is always made deliberately — do not satisfy it by defaulting to 0→last. Confirmed background-removal provider failures already fall back automatically on the server, without a new user charge. There is no daily removal retry lockout; honor reported cooldowns and unknown-task safeguards if recovery still fails. For already-authorized generation, automatically execute a zero-credit recovery quote and poll it; no renewed approval or refund. Never duplicate a running recovery. Limit automatic retries to two per failed job per session; stop on recurring failure or any paid quote. DEFAULTS TO A COST PREVIEW — see the dryRun argument. Returns { jobId } — poll get_job.
Acceso externo
Esquema de entrada
{'type': 'object', 'required': ['assetId', 'iterationId'], 'properties': {'pairs': {'type': 'array', 'items': {'type': 'object', 'required': ['from', 'to'], 'properties': {'to': {'anyOf': [{'type': 'integer', 'minimum': 0}, {'type': 'null'}], 'description': 'End tile index, or null for prompt-driven motion.'}, 'from': {'type': 'integer', 'minimum': 0, 'description': 'Start tile index.'}}, 'additionalProperties': False}, 'description': 'Grid assets only — which tile transitions to animate. Omit for single-image assets.'}, 'dryRun': {'type': 'boolean', 'default': True, 'description': "DEFAULTS TO TRUE. While true this returns only a cost quote ({ estimatedCredits, balance, spendCapDaily, spentLast24h, capRemaining }) and executes nothing. Show the user estimatedCredits, then ask a normal confirmation question. Prefer the client's native question UI with Approve / Decline / Discuss choices when available; otherwise accept any unambiguous conversational approval. Never require a fixed phrase or ask the user to type a magic word. Only after approval, re-call with dryRun:false to actually spend."}, 'assetId': {'type': 'string', 'description': 'Asset id or slug.'}, 'closeLoop': {'type': 'boolean', 'description': 'Single-image assets — reuse the start frame as the end frame so the clip loops.'}, 'motionHint': {'type': 'string', 'description': 'Extra motion guidance folded into the prompt.'}, 'videoModel': {'type': 'string', 'description': 'Override the video model.'}, 'iterationId': {'type': 'string', 'description': 'Revision (iteration) id to animate.'}, 'idempotencyKey': {'type': 'string', 'minLength': 1, 'description': 'Optional Idempotency-Key for the real (dryRun:false) call. Omit and one is minted per call. Reuse the SAME value when retrying a call that failed with ENTITY_BUSY / 402 / 429 so the retry cannot double-dispatch.'}, 'durationSeconds': {'type': 'number', 'maximum': 10, 'minimum': 2, 'description': 'Clip length, clamped server-side to 2-10s.'}}, 'additionalProperties': False}
approve_automatic_pose_fallback
Approve an automatic pose decision
Successful automatic poses now continue without review, including imports. Four-direction setup stays automatic and eight-direction keeps its existing selection. Imported generation preserves source rendering rather than project style. Use this tool only when get_job returns a pending automaticPoseFallback. If poseReview is present, this is a historical imported-pose checkpoint from an earlier flow: show originalUrl and poseUrl side by side and ask the user to check style, complete head/body and unwanted ground/scenery. Submit choice="generated" only after they accept that exact pose, or choice="original" to use their original character; include poseVersion from poseReview.version. Use cancel_job to cancel. Without poseReview, pose creation failed: ask whether to continue with the default pose or cancel, and use choice="original" to continue. Never approve automatically. Both choices resume the original approved animation request at normal video cost. Accepted generated poses are reused without another review until regenerated.
Acceso externo
Esquema de entrada
{'type': 'object', 'required': ['jobId'], 'properties': {'jobId': {'type': 'string', 'description': 'Job waiting for an automatic pose decision.'}, 'choice': {'enum': ['generated', 'original'], 'type': 'string', 'description': 'Required for an imported-pose review. Technical-failure fallback defaults to original.'}, 'poseVersion': {'type': 'string', 'description': 'Exact poseReview.version shown to and approved by the user; required for an imported-pose review.'}}, 'additionalProperties': False}
approve_directional_poses
Approve directional poses
FREE approval checkpoint. Use only when get_job returns status:"waiting_approval", wizardPhase:"waiting-directional-pose-approval", and directionalPoseReview. Present every returned previewUrls to the user and let them adjust or review the proposed frameIndices and poseScales. If any remain unreviewed, get explicit confirmation to use those candidates as shown before submitting the complete returned index and scale maps. When directions is present, review only those four poses, choose unique indices 0–3, keep scale 100 and preserve unused map entries. Absent directions means eight poses. Closing or declining means do not call this tool: the job remains paused and no dependent animation credits are spent. The server rechecks the live credit balance immediately before resuming paid dependent animations.
Acceso externo
Esquema de entrada
{'type': 'object', 'required': ['jobId', 'frameIndices'], 'properties': {'jobId': {'type': 'string', 'description': 'Waiting job id from get_job.'}, 'poseScales': {'type': 'object', 'required': ['s', 'se', 'e', 'ne', 'n', 'nw', 'w', 'sw'], 'properties': {'e': {'type': 'integer', 'maximum': 115, 'minimum': 70}, 'n': {'type': 'integer', 'maximum': 115, 'minimum': 70}, 's': {'type': 'integer', 'maximum': 115, 'minimum': 70}, 'w': {'type': 'integer', 'maximum': 115, 'minimum': 70}, 'ne': {'type': 'integer', 'maximum': 115, 'minimum': 70}, 'nw': {'type': 'integer', 'maximum': 115, 'minimum': 70}, 'se': {'type': 'integer', 'maximum': 115, 'minimum': 70}, 'sw': {'type': 'integer', 'maximum': 115, 'minimum': 70}}, 'description': 'Approved percent scale for every compass direction (70–115). Omit to keep the review values.', 'additionalProperties': False}, 'frameIndices': {'type': 'object', 'required': ['s', 'se', 'e', 'ne', 'n', 'nw', 'w', 'sw'], 'properties': {'e': {'type': 'integer', 'minimum': 0}, 'n': {'type': 'integer', 'minimum': 0}, 's': {'type': 'integer', 'minimum': 0}, 'w': {'type': 'integer', 'minimum': 0}, 'ne': {'type': 'integer', 'minimum': 0}, 'nw': {'type': 'integer', 'minimum': 0}, 'se': {'type': 'integer', 'minimum': 0}, 'sw': {'type': 'integer', 'minimum': 0}}, 'description': 'Approved source-frame index for every compass direction.', 'additionalProperties': False}}, 'additionalProperties': False}
cancel_job
Cancel a job
FREE. Abort a running job. Failed/incomplete provider work is refunded automatically. If the job is waiting for directional-pose approval, its successful reusable 360 and pose charges are retained; no dependent animation has started. Use this when a generation is clearly going wrong rather than letting it run to completion.
Acceso externo
Esquema de entrada
{'type': 'object', 'required': ['jobId'], 'properties': {'jobId': {'type': 'string', 'description': 'Job id to cancel.'}}, 'additionalProperties': False}
commit_map_draft
Save a validated map draft
FREE. Commit the exact draftHash as a recoverable revision. The existing map must still match its expectedRevision; conflicts require re-reading and merging the user’s changes. Reuse requestId for retry. The map immediately opens in the normal editor.
Acceso externo
Esquema de entrada
{'type': 'object', 'required': ['draftId', 'draftHash', 'requestId'], 'properties': {'draftId': {'type': 'string', 'format': 'uuid'}, 'draftHash': {'type': 'string'}, 'requestId': {'type': 'string', 'maxLength': 128, 'minLength': 8}}, 'additionalProperties': False}
convert_texture_to_material
Convert a legacy texture to a Material
FREE and SYNCHRONOUS, no AI. Copies a legacy repeat-xy texture into a new immutable Brushable Material revision; the original revision is preserved. Topdown/isometric conversions can be ready immediately when the legacy seam check passed. Platformer conversions are marked needs-review because the old texture has no paired surface ribbon. Legacy strip-only textures cannot be converted because they have no interior fill. Returns the new iteration and quality status; call get_asset afterwards.
Acceso externo
Esquema de entrada
{'type': 'object', 'required': ['assetId', 'iterationId', 'projection'], 'properties': {'assetId': {'type': 'string', 'description': 'Legacy texture asset id or slug.'}, 'projection': {'enum': ['platformer', 'topdown', 'isometric'], 'type': 'string', 'description': 'Map projection this Material will paint.'}, 'iterationId': {'type': 'string', 'description': 'Legacy texture revision to preserve and convert.'}}, 'additionalProperties': False}
create_animation_from_pose
Create a 1-frame animation from a pose
FREE, no AI. Promote a pose into a real 1-frame animation (a still/idle) that is scaled to match the character's other animations and exports to every engine. Pass poseId "__idle__" to use the character's default image when it has no poses. Returns a jobId — poll get_job.
Acceso externo
Esquema de entrada
{'type': 'object', 'required': ['characterId', 'poseId'], 'properties': {'fps': {'type': 'integer', 'maximum': 60, 'minimum': 1, 'description': 'Playback fps.'}, 'newId': {'type': 'string', 'description': 'Slug for the new animation ([A-Za-z0-9_-]).'}, 'poseId': {'type': 'string', 'description': 'Pose id, or "__idle__" for the character\'s default image.'}, 'characterId': {'type': 'string', 'description': 'Character id.'}, 'displayName': {'type': 'string', 'maxLength': 120, 'description': 'Human-facing label.'}}, 'additionalProperties': False}
create_asset
Create an asset
PAID (one image call). Creates a NEW asset from a prompt in any of the six types. The default dry run now returns a strictly text-free artwork brief: no captions, labels, lettering, digits or pseudo-writing unless the user explicitly requests specific intrinsic writing on an object. Environment Kit overlays must not have die-cut sticker borders or backing. It returns both the exact semantic plan (`plan.preview`, item count/list, camera, project-derived look) and `planToken`. SHOW that preview to the user. A real call requires the same request plus that planToken; changing the prompt, project settings, type, model, or output settings invalidates it and requires a new dry run. Standard models cost 60 credits at 1K, 100 at 2K, or 150 at 4K per image/sheet, including automatic background removal and fallback; use the dry-run quote. Object (`assetType: "static"`, formerly Static Asset) defaults to four separately editable design alternatives of the requested object, not a state sequence. All four share project style and one of five world cameras; explicitly requested flat inventory/UI icons use front/content_type. Explicit one remains supported. Clean cutouts omit incidental scenery and sticker backing, not real outlines or integral bases. Never automatically reroute asset types. Object States (`staged`) is one object in exactly four ordered states on a 2×2 sheet; no filler or automatic animation. Preserve identity, shared physical scale and real size changes. Object Collection (`tileset`) and Environment Kit (`terrain`) propose 1–25 useful pieces when no count is specified; explicit lists/counts are preserved without grid-filler extras. Object Collections contain independently editable mixed items, variants, matching families, icons/symbols or cards/tokens—not automatic animation stages. World props follow project camera; flat icons/cards use front-facing presentation even in isometric projects, unless the user explicitly requests another view. Preserve requested intrinsic symbols/text, never external captions. Material uses one transparent 1K donor sheet through the configured Material provider route and yields two platformer fill+surface families or four topdown/isometric fills, and background to one image when the user did not specify a count. Explicit counts/semantic sets override defaults, and non-square counts for other grid types are filled to the smallest supported 2×2–5×5 square with disclosed supplemental items. Environment Kit camera follows the project; request a different camera explicitly in the prompt. Kit pieces are placed over Materials, not used as deterministic terrain donors or guaranteed seamless brushes. projectId is REQUIRED — the project supplies gameType, which decides how the art is drawn, and keeps the asset findable in the web app. A fan-out create returns one jobId — the asset ids appear in get_job as gridAssetIds once the job finishes. Environment Kit has NO per-tile edit path: revising a terrain asset regenerates the whole sheet. DEFAULTS TO A PLAN + COST PREVIEW — see dryRun. Returns { jobId, assetId } — poll get_job, then call get_asset. Generated atlases are cut by logical foreground objects, not trusted row geometry; get_asset exposes extraction status/warnings.
Acceso externo
Esquema de entrada
{'type': 'object', 'required': ['projectId', 'assetType', 'prompt'], 'properties': {'name': {'type': 'string', 'description': 'Display name (defaults to the prompt).'}, 'slug': {'type': 'string', 'description': 'Stable handle used by every /assets/:id call ([a-z0-9-]). Auto-derived from the name when omitted.'}, 'style': {'type': 'string', 'description': "Override the project's art style for this asset only."}, 'bgType': {'enum': ['scene', 'distant_backdrop', 'depth_layer', 'foreground_overlay', 'parallax_far', 'parallax_mid', 'parallax_near', 'platform_scene', 'static_backdrop', 'scrolling_backdrop', 'ground_fill', 'overhead_map', 'functional_map', 'scrolling_floor', 'parallax_underlay', 'iso_ground', 'iso_scene', 'iso_far', 'iso_platform_surface', 'full_scene', 'room_stage', 'parallax_strip', 'platform_scene_front', 'vista_backdrop'], 'type': 'string', 'description': 'REQUIRED for assetType "background" — prefer scene (one opaque full scene), distant_backdrop (one opaque far vista), depth_layer (one scenery layer with transparent gaps), or foreground_overlay (transparent edge framing). All four support every camera. One image per call, no automatic parallax pack, collision/navigation or verified seamless repeat. Angled top-down and strict overhead stay distinct; atmospheric vistas need no forced isometric geometry. Preserve project style. Legacy values remain view-specific: platformer → parallax_far/parallax_mid/parallax_near/platform_scene/static_backdrop/scrolling_backdrop; topdown + topdown_overhead → ground_fill/overhead_map/functional_map/scrolling_floor/parallax_underlay; isometric → iso_ground/iso_scene/iso_far/iso_platform_surface; point_and_click → full_scene/room_stage/parallax_strip/platform_scene_front/vista_backdrop. A mismatch, or omitting it, is rejected with 400. Each sub-type runs a different tuned prompt, so this decides what KIND of image you get — a far parallax sky and a functional platform scene are not interchangeable. Ask the user which layer they want if their request does not make it obvious.'}, 'dryRun': {'type': 'boolean', 'default': True, 'description': "DEFAULTS TO TRUE. While true this returns only a cost quote ({ estimatedCredits, balance, spendCapDaily, spentLast24h, capRemaining }) and executes nothing. Show the user estimatedCredits, then ask a normal confirmation question. Prefer the client's native question UI with Approve / Decline / Discuss choices when available; otherwise accept any unambiguous conversational approval. Never require a fixed phrase or ask the user to type a magic word. Only after approval, re-call with dryRun:false to actually spend."}, 'prompt': {'type': 'string', 'maxLength': 20000, 'minLength': 1, 'description': 'What to generate. Describe the subject, not the art style — style comes from the project.'}, 'gridCols': {'type': 'integer', 'maximum': 16, 'minimum': 1, 'description': 'Legacy compatibility only; the confirmed plan decides columns.'}, 'gridRows': {'type': 'integer', 'maximum': 16, 'minimum': 1, 'description': 'Legacy compatibility only. The confirmed semantic plan owns layout. Object Collection and Environment Kit never add items just to fill cells.'}, 'tileSize': {'enum': [64, 128, 256], 'type': 'number', 'description': 'TERRAIN only — output tile size in px (64, 128 or 256).'}, 'assetType': {'enum': ['static', 'tileset', 'staged', 'background', 'terrain', 'texture'], 'type': 'string', 'description': '`static` = Object (formerly Static Asset), four separately editable design alternatives by default (explicit one supported); each may also be animated; tileset = Object Collection, one coordinated set of independently editable items; staged = one subject in N progressive stages (the input animate_asset expects); background = scenery, never a game object; terrain = Environment Kit, individually placed props, surface details or connecting modules; texture = Terrain Material, brushable fill/surface donors (wire names unchanged; editor topology is deterministic).'}, 'planToken': {'type': 'string', 'description': 'REQUIRED when dryRun=false. Copy unchanged from the immediately preceding dry-run response.'}, 'projectId': {'type': 'string', 'description': 'REQUIRED. Owning project (create_project / list_projects). Supplies gameType + default style.'}, 'bgViewType': {'enum': ['platformer', 'topdown', 'topdown_overhead', 'isometric', 'point_and_click'], 'type': 'string', 'description': 'BACKGROUND only — which view the background is drawn for. Defaults to the project gameType.'}, 'imageModel': {'type': 'string', 'description': 'Override the image model for non-Material assets. Materials use the server-owned MATERIAL_IMAGE_PRIMARY provider route.'}, 'runtimeUse': {'enum': ['plain_image', 'particle_emitter', 'deformable_strip', 'repeat_fill', 'nine_slice', 'shader_effect', 'path_follow'], 'type': 'string', 'description': 'OBJECT only (`assetType: "static"`; formerly Static Asset). Material is locked to deterministic brush rendering server-side. Declares how the art is meant to be rendered — particle_emitter, deformable_strip, nine_slice or shader_effect — which changes the prompt AND the export metadata. Anything other than plain_image on a non-Object type is rejected. path_follow remains accepted for legacy clients but must not be used for new assets; path motion is configured per placement in the level editor. It can also be set later with set_asset_runtime_intent, for free.'}, 'aspectRatio': {'enum': ['16:9', '4:3', '1:1', '9:16', '21:9'], 'type': 'string', 'description': 'BACKGROUND only — OPTIONAL, and best left unset: the server applies the recommended ratio for the chosen sub-type (e.g. 21:9 for a parallax layer, 1:1 for a ground fill), which is what the web wizard preselects. Only pass a value if the user asked for a specific shape. 21:9 is the widest and 9:16 the tallest the image model accepts.'}, 'perspective': {'enum': ['orthogonal', 'isometric', 'platformer'], 'type': 'string', 'description': 'Environment Kit only — legacy three-value camera override. Omit to retain the project’s distinct side, angled top-down, overhead, isometric or adventure camera; request finer camera changes in the prompt.'}, 'textureKind': {'enum': ['fill', 'strip'], 'type': 'string', 'description': 'LEGACY compatibility only. New Materials derive platformer/topdown/isometric projection from the project gameType; this value does not change their donor contract.'}, 'idempotencyKey': {'type': 'string', 'minLength': 1, 'description': 'Optional Idempotency-Key for the real (dryRun:false) call. Omit and one is minted per call. Reuse the SAME value when retrying a call that failed with ENTITY_BUSY / 402 / 429 so the retry cannot double-dispatch.'}, 'targetTileSize': {'type': 'integer', 'maximum': 512, 'minimum': 16, 'description': 'Output tile side in px (16-512).'}, 'referenceAssetUrls': {'type': 'array', 'items': {'type': 'string'}, 'maxItems': 4, 'description': 'Up to 4 reference image URLs to condition the generation. URLs only — raw base64 is rejected on this surface.'}, 'backgroundResolution': {'enum': ['1K', '2K', '4K'], 'type': 'string', 'description': 'BACKGROUND only — output tier (default 2K). 4K costs more.'}}, 'additionalProperties': False}
create_character
Create a character
PAID (standard 1K: 60 credits; 2K: 100; 4K: 150; premium models may differ). Generate a NEW character from a text prompt. This is the entry point for building art from nothing — call create_project first if the user has no project. Artwork is strictly text-free by default: no labels, captions, lettering or pseudo-text; only specific intrinsic writing explicitly requested by the user is permitted. IMAGE ONLY: it produces the character still, not animations. Animation is a separate explicit step (generate_character_animation for a walk cycle, generate_character_turn for the 360 rotation), because animating costs several times more and the user should choose it. BY DEFAULT it requests FOUR DESIGN VARIATIONS FOR THE SAME PRICE, matching the dashboard. Set generateFourVariations:false only when the user explicitly wants one character. gridRows:2 + gridCols:2 remain the legacy trigger for the same four-character mode; one image call is split by complete character silhouettes, never fixed cells. Four is the expected count, but any result with at least two separate silhouettes succeeds; every clearly separated full character is preserved whether two, three, or more than four are found. Zero or one means the sheet was not extractable and refunds. Show the user every result and let them pick. Returns { jobId, expectedCharacterCount } — poll get_job; on status:"done" its characterIds and characterPreviews tell you which characters exist and what they look like. gameType defaults from the project but can be overridden for this character. Use topdown for the Top-Down Angled character pipeline, including characters intended for isometric projects. Passing isometric is accepted as an alias and creates a topdown character because that is the measured working directional pipeline. The STORED CHARACTER gameType — not the project gameType — controls every later animation and whether a user-facing 360 turn is available. A topdown character inside a platformer project therefore keeps the top-down directional pipeline and supports generate_character_turn. DEFAULTS TO A COST PREVIEW — see the dryRun argument.
Acceso externo
Esquema de entrada
{'type': 'object', 'required': ['projectId', 'prompt'], 'properties': {'style': {'type': 'string', 'description': "Art-style override. Omit to inherit the project's style — usually correct, since a project should look consistent."}, 'dryRun': {'type': 'boolean', 'default': True, 'description': "DEFAULTS TO TRUE. While true this returns only a cost quote ({ estimatedCredits, balance, spendCapDaily, spentLast24h, capRemaining }) and executes nothing. Show the user estimatedCredits, then ask a normal confirmation question. Prefer the client's native question UI with Approve / Decline / Discuss choices when available; otherwise accept any unambiguous conversational approval. Never require a fixed phrase or ask the user to type a magic word. Only after approval, re-call with dryRun:false to actually spend."}, 'prompt': {'type': 'string', 'maxLength': 20000, 'minLength': 1, 'description': 'What the character is, e.g. "a plague doctor with a lantern". Describe the subject, not the art style.'}, 'gameType': {'enum': ['platformer', 'topdown', 'topdown_overhead', 'isometric', 'point_and_click'], 'type': 'string', 'description': 'Character perspective override. Omit to inherit the project. Use topdown for Top-Down Angled and isometric projects; isometric is mapped to topdown. The stored value controls later animation behavior and 360-turn eligibility.'}, 'gridCols': {'type': 'number', 'const': 2, 'description': 'Legacy equivalent of the default four-variation mode: set to 2 together with gridRows:2; extraction follows complete silhouettes.'}, 'gridRows': {'type': 'number', 'const': 2, 'description': 'Legacy equivalent of the default four-variation mode: set to 2 together with gridCols:2. This is not cut geometry.'}, 'projectId': {'type': 'string', 'description': 'REQUIRED. The project the character belongs to — it supplies the default gameType and style.'}, 'imageModel': {'type': 'string', 'description': 'Override the image model. Omit unless the user asked for a specific one.'}, 'cameraAngle': {'type': 'number', 'maximum': 80, 'minimum': 30, 'description': 'Camera elevation in degrees — only meaningful for angled top-down projects.'}, 'idempotencyKey': {'type': 'string', 'minLength': 1, 'description': 'Optional Idempotency-Key for the real (dryRun:false) call. Omit and one is minted per call. Reuse the SAME value when retrying a call that failed with ENTITY_BUSY / 402 / 429 so the retry cannot double-dispatch.'}, 'characterImageSize': {'enum': ['2:3', '1:1', '3:2'], 'type': 'string', 'description': 'Aspect ratio of the generated image. Omit for the game-type default.'}, 'referenceAssetUrls': {'type': 'array', 'items': {'type': 'string', 'format': 'uri'}, 'description': 'URLs of existing images to steer the design. URLs only — base64 is rejected by the API.'}, 'generateFourVariations': {'type': 'boolean', 'description': 'Defaults to true, matching the dashboard: one image call produces four design variations for the cost of one. Set false only when the user explicitly requests a single character.'}}, 'additionalProperties': False}
create_project
Create a project
FREE and SYNCHRONOUS (no jobId — do not poll). Creates the container everything else needs: characters and assets are created INSIDE a project, and the project's gameType is what decides how they are drawn and animated. Also seeds a starter level map, so the game preview has something real to render immediately. Call list_projects first — reuse an existing project rather than making a near-duplicate.
Acceso externo
Esquema de entrada
{'type': 'object', 'required': ['name', 'gameType'], 'properties': {'name': {'type': 'string', 'description': 'Project name shown in the dashboard.'}, 'style': {'type': 'string', 'description': 'Optional art-style id applied as the default for generations in this project.'}, 'gameType': {'enum': ['platformer', 'topdown', 'topdown_overhead', 'isometric', 'point_and_click'], 'type': 'string', 'description': 'REQUIRED and permanent for everything in the project. platformer = side view with gravity; topdown = 4/8-direction overhead-ish (Zelda-like); topdown_overhead = straight down; isometric = 2:1 diamond; point_and_click = straight-on adventure scenes. Ask the user if it is not obvious — it changes every prompt downstream.'}, 'styleGuide': {'type': 'object', 'required': ['version', 'direction', 'palette', 'shapeLanguage', 'rendering', 'headingFont', 'bodyFont', 'camera', 'references', 'lockedColors'], 'properties': {'camera': {'enum': ['platformer', 'topdown', 'topdown_overhead', 'isometric', 'point_and_click'], 'type': 'string'}, 'palette': {'type': 'object', 'propertyNames': {'pattern': '^[a-zA-Z][a-zA-Z0-9_-]{0,39}$'}, 'additionalProperties': {'type': 'string', 'pattern': '^#[0-9a-fA-F]{6}$'}}, 'version': {'type': 'number', 'const': 1}, 'bodyFont': {'type': 'object', 'required': ['family', 'fontId', 'weight', 'size', 'lineHeight', 'color'], 'properties': {'size': {'type': 'number', 'maximum': 160, 'minimum': 8}, 'color': {'type': 'string', 'pattern': '^#[0-9a-fA-F]{6}$'}, 'family': {'type': 'string', 'maxLength': 100, 'minLength': 1}, 'fontId': {'type': 'string', 'maxLength': 100, 'minLength': 1}, 'sha256': {'type': 'string', 'pattern': '^[a-f0-9]{64}$'}, 'weight': {'type': 'integer', 'maximum': 900, 'minimum': 100}, 'version': {'type': 'string', 'maxLength': 100, 'minLength': 1}, 'lineHeight': {'type': 'number', 'maximum': 3, 'minimum': 1}}, 'additionalProperties': False}, 'direction': {'type': 'string', 'maxLength': 2000}, 'rendering': {'type': 'string', 'maxLength': 500}, 'references': {'type': 'array', 'items': {'type': 'object', 'required': ['key', 'target'], 'properties': {'key': {'type': 'string', 'maxLength': 1500, 'minLength': 1}, 'target': {'enum': ['overall_style', 'ui', 'world_indicators', 'characters', 'backgrounds'], 'type': 'string'}}, 'additionalProperties': False}, 'maxItems': 12}, 'headingFont': {'type': 'object', 'required': ['family', 'fontId', 'weight', 'size', 'lineHeight', 'color'], 'properties': {'size': {'type': 'number', 'maximum': 160, 'minimum': 8}, 'color': {'type': 'string', 'pattern': '^#[0-9a-fA-F]{6}$'}, 'family': {'type': 'string', 'maxLength': 100, 'minLength': 1}, 'fontId': {'type': 'string', 'maxLength': 100, 'minLength': 1}, 'sha256': {'type': 'string', 'pattern': '^[a-f0-9]{64}$'}, 'weight': {'type': 'integer', 'maximum': 900, 'minimum': 100}, 'version': {'type': 'string', 'maxLength': 100, 'minLength': 1}, 'lineHeight': {'type': 'number', 'maximum': 3, 'minimum': 1}}, 'additionalProperties': False}, 'lockedColors': {'type': 'array', 'items': {'type': 'string', 'pattern': '^#[0-9a-fA-F]{6}$'}, 'maxItems': 24}, 'shapeLanguage': {'type': 'string', 'maxLength': 500}}, 'description': 'Reviewed palette, rendering and typography. Saved as active revision 1 for future generations; font IDs must belong to the available catalog. Omit to create without a guide.', 'additionalProperties': False}, 'description': {'type': 'string', 'description': 'Optional project description. Feeds the prompt context for later generations.'}}, 'additionalProperties': False}
create_ui_composition
Assemble UI components
Create a free static composition of existing icon/frame revisions; indicators and functional widgets remain independent. No new image generation.
Acceso externo
Esquema de entrada
{'type': 'object', 'required': ['packId', 'name', 'width', 'height', 'children'], 'properties': {'name': {'type': 'string', 'maxLength': 120, 'minLength': 1}, 'width': {'type': 'integer', 'maximum': 2048, 'minimum': 8}, 'height': {'type': 'integer', 'maximum': 2048, 'minimum': 8}, 'packId': {'type': 'string', 'format': 'uuid', 'description': 'Owned UI Pack ID.'}, 'children': {'type': 'array', 'items': {'type': 'object', 'required': ['componentId', 'revisionId', 'bounds'], 'properties': {'bounds': {'type': 'object', 'required': ['x', 'y', 'width', 'height'], 'properties': {'x': {'type': 'number'}, 'y': {'type': 'number'}, 'width': {'type': 'number'}, 'height': {'type': 'number'}}, 'additionalProperties': False}, 'revisionId': {'type': 'string', 'format': 'uuid'}, 'componentId': {'type': 'string', 'format': 'uuid', 'description': 'Owned component ID within this pack.'}}, 'additionalProperties': False}, 'maxItems': 8, 'minItems': 1}}, 'additionalProperties': False}
create_ui_pack
Create UI Pack
Create an empty project-owned UI Pack with its guide snapshot. Free; generation is a separate quoted action.
Acceso externo
Esquema de entrada
{'type': 'object', 'required': ['projectId', 'name'], 'properties': {'name': {'type': 'string', 'maxLength': 120, 'minLength': 1}, 'projectId': {'type': 'string'}}, 'additionalProperties': False}
duplicate_animation
Duplicate an animation
FREE, synchronous, no AI. Make an exact copy of the CURRENT saved animation under a new slug, preserving its selected frame order, loop/hold settings, compositing, mounts, and rendered pixels. The original is untouched. Returns { jobId: null, animation }; do not poll a job.
Acceso externo
Esquema de entrada
{'type': 'object', 'required': ['characterId', 'animation'], 'properties': {'newId': {'type': 'string', 'description': 'Slug for the copy ([A-Za-z0-9_-], default "<source>_copy").'}, 'animation': {'type': 'string', 'description': 'Source animation slug.'}, 'characterId': {'type': 'string', 'description': 'Character id.'}}, 'additionalProperties': False}
export_map
Export map (JSON)
Engine-ready map JSON built from the SAVED level data, preserving placement name/gameplayId and baking custom-field values. Every engine retains materialRendering and materialRenderingResolved when present. Bundles include material-rendering.json and bake styled terrain/areas into PNGs: never apply shading twice or replace baked art with raw donor tiles. Pixel materials require nearest filtering without mipmaps; keep semantic terrain for gameplay. GameMaker uses the supplied tizo_draw_tile Draw helper; Tiled consumers configure filtering from metadata. All engine JSON exports retain materialAreas; bundles also retain semantic outlines in material-areas.json, alongside clipped artwork. Never render both as duplicate visuals. Phaser JSON materialAreaSource needs mask/blend rendering in URL mode, not the raw donor rectangle. For the zip bundle (per-tile PNGs, loader scripts, tileset files) use get_export_command instead.
Solo lectura Acceso externo Idempotente
Esquema de entrada
{'type': 'object', 'required': ['mapId'], 'properties': {'mapId': {'type': 'string', 'description': 'Map id.'}, 'engine': {'enum': ['tiled', 'phaser', 'godot', 'unity', 'gamemaker', 'unreal'], 'type': 'string', 'description': 'Target engine (default tiled). Unreal is a beta Paper2D artwork importer; native verification and gameplay integration remain pending.'}}, 'additionalProperties': False}
fix_asset_seams
Fix a legacy texture's seams
LEGACY ONLY; new Brushable Materials reject this operation because they use world-space sampling. PAID (60 credits per standard-model edit attempt; use the dry-run quote). Make an old texture tile seamless. Legacy textures were created as raw grid cells, so CHECK get_asset first: metadata.seamless.seamMetric.pass is a FREE verdict on whether this cell already tiles cleanly, and metadata.seamless.fixed tells you if it was already fixed. Do not spend on a cell that passes. The fix lands as a new current revision. Confirmed background-removal provider failures already fall back automatically on the server, without a new user charge. There is no daily removal retry lockout; honor reported cooldowns and unknown-task safeguards if recovery still fails. For already-authorized generation, automatically execute a zero-credit recovery quote and poll it; no renewed approval or refund. Never duplicate a running recovery. Limit automatic retries to two per failed job per session; stop on recurring failure or any paid quote. DEFAULTS TO A COST PREVIEW — see the dryRun argument. Returns { jobId } — poll get_job.
Acceso externo
Esquema de entrada
{'type': 'object', 'required': ['assetId', 'iterationId'], 'properties': {'dryRun': {'type': 'boolean', 'default': True, 'description': "DEFAULTS TO TRUE. While true this returns only a cost quote ({ estimatedCredits, balance, spendCapDaily, spentLast24h, capRemaining }) and executes nothing. Show the user estimatedCredits, then ask a normal confirmation question. Prefer the client's native question UI with Approve / Decline / Discuss choices when available; otherwise accept any unambiguous conversational approval. Never require a fixed phrase or ask the user to type a magic word. Only after approval, re-call with dryRun:false to actually spend."}, 'assetId': {'type': 'string', 'description': 'Legacy texture asset id or slug (not a Material with a material recipe).'}, 'iterationId': {'type': 'string', 'description': 'Revision (iteration) id to fix.'}, 'idempotencyKey': {'type': 'string', 'minLength': 1, 'description': 'Optional Idempotency-Key for the real (dryRun:false) call. Omit and one is minted per call. Reuse the SAME value when retrying a call that failed with ENTITY_BUSY / 402 / 429 so the retry cannot double-dispatch.'}}, 'additionalProperties': False}
frame_animation
Animate a grid asset from its own tiles
FREE, and NO AI AT ALL — no video model, no credits, nothing to approve. The tiles of a tileset/staged asset ARE the frames: give the tile indices in playback order (repeats allowed) and they are composited into a real spritesheet animation on that asset, exportable to every engine. This is how you animate a coin flip, a flickering torch or a chest opening WITHOUT paying for image-to-video. Try this before animate_asset whenever the motion already exists across the tiles. Returns a jobId — poll get_job.
Acceso externo
Esquema de entrada
{'type': 'object', 'required': ['assetId', 'iterationId', 'frameIndices'], 'properties': {'fps': {'type': 'integer', 'maximum': 30, 'minimum': 1, 'description': 'Playback fps (1-30, default 12).'}, 'name': {'type': 'string', 'maxLength': 60, 'description': 'Label for the animation (default "Frames").'}, 'assetId': {'type': 'string', 'description': 'Asset id or slug (must be a grid asset: tileset or staged).'}, 'iterationId': {'type': 'string', 'description': 'Revision (iteration) id whose tiles are the frames.'}, 'frameIndices': {'type': 'array', 'items': {'type': 'integer', 'minimum': 0}, 'maxItems': 120, 'minItems': 2, 'description': 'Tile indices in playback order, e.g. [0,1,2,3,2,1]. At least 2, at most 120. Repeats are allowed — that is how you hold or ping-pong a frame.'}}, 'additionalProperties': False}
generate_character_animation
Generate character animations
PAID, and the cost MULTIPLIES BY THE NUMBER OF ANIMATIONS (each is its own image-to-video call; Wan 3.0 costs 150 credits/second, so its default 2-second clip is 300 credits). All frames are text-free by default: no subtitles, captions or invented writing. This is real motion — a walk cycle, an attack, an idle bob — not the 1-frame still that create_animation_from_pose produces. Read the character's gameType and use the standard animation names for it (get_character shows what already exists); the project gameType is irrelevant after character creation. A topdown character inside a platformer project still uses top-down prompts and directional behavior. A name that already exists is NEVER replaced: the server allocates the next numeric slug (walk → walk_2 → walk_3), and the returned animations list contains the resolved names. Ask the user which animations they want before spending: 4 animations cost 4x. For a topdown character, resolve the animation direction mode BEFORE choosing those animation names. Read animationDirection from get_character and preselect its Luna-classified mode; let the user override it. Pass animationDirectionMode on both the dry run and confirmed request: overhead uses one engine-rotated sprite with base action names and no 360; four_direction uses S/N/E/W rows with FREE four-pose image setup; eight_direction also uses diagonals and keeps the regular 360 video setup (+200 credits when newly needed). Overhead setup is free; animation videos are priced separately. Setup and Luna run only after animation generation is confirmed; the server creates the poses and automatically assigns matching facings without pose approval for four_direction, then continues animation generation. Poll all operation jobs while queued or running; an approved directionalPoseReview is a completion record, not a user checkpoint. The chosen mode is saved on the character. A missing classification is not permission to guess silently. Every animation defaults to 2 seconds, including walks, runs, attacks, and loops. Omit animDurations and customAnims[*].duration unless the user explicitly asks for a different clip length; never infer a longer duration from the motion or from the fact that it loops. If the character came from a successful 2x2 create, there may be two, three, four, or more siblings and animating is per-character: show the user the characterPreviews from get_job and have them pick one before you spend. For multi-direction sets, mirrorAnims gives you FREE flipped copies of a direction generated in the same call (walk_left from walk_right) — prefer a real generation when the character is asymmetric, because a held item switches sides under a mirror. The server uses the standard pose-aware animation pipeline for new requests; there is no flag argument to set. When the user wants stored poses as the actual video endpoints, call list_character_poses and pass their ids through poseFirstFrameIds / poseLastFrameIds. Omit those maps to let the server plan anchors automatically; never pass a pose URL. Before each new clip the server classifies the effective anchor as empty-handed, held, or unclear and adds the matching inventory-preservation lock automatically; there is no inventory argument to send. For platformer walk/run, the server-created cached mid-walk anchor pose is FREE; explicit pose generation remains paid. For eight-direction and legacy video-based topdown/isometric clips with targetFacings, automatic planning uses one cached standing internal 360 rotation for every action, including custom actions; its one-time surcharge is included in the dry-run quote. Do NOT call generate_character_turn merely to prepare an animation — that explicit visible turn is a separate action. When that internal 360 is needed, the job pauses at waiting_approval before any animation video starts. Present directionalPoseReview from get_job and call approve_directional_poses only after the user accepts the full set, including explicit confirmation to use any candidates they did not review individually. The dry-run response includes animationPipelineAssignmentToken; copy it verbatim into the confirmed call so the quoted pipeline decision cannot change while the user is deciding. If it expires, run the same dry-run again. The same response includes preflight with per-animation resolved names, durations and credits; setup and total credits; model resolution; runtime frame size; and explicit unknown-until-generated frame count/FPS/ETA. Show that structured preview instead of inventing precision. API-key calls can use the account's full wallet balance; the dashboard-only 600-credit limit and its first-animation exception do not apply. The independent key spend cap, paid-attempt ceiling, and ordinary wallet balance still apply. Returns { jobId, animations, operations, rejectedOperations? }; jobId is the first operation only for backward compatibility. Poll, retry, or cancel every operations[].jobId independently. When an operation reaches done, it returns an animationQualityGate requiring get_character; finish that review/repair loop before exporting or saying the animation is ready. A prompt that composes too long for the model is rejected with PROMPT_TOO_LONG before anything is charged, and the response names the animation. Check isTemplate on that entry: false means YOUR text is what is long, so shorten it; true means the shipped template is over the ceiling and no prompt you send can fix it — report it rather than retrying. DEFAULTS TO A COST PREVIEW — see the dryRun argument.
Acceso externo
Esquema de entrada
{'type': 'object', 'required': ['characterId', 'animations'], 'properties': {'dryRun': {'type': 'boolean', 'default': True, 'description': "DEFAULTS TO TRUE. While true this returns only a cost quote ({ estimatedCredits, balance, spendCapDaily, spentLast24h, capRemaining }) and executes nothing. Show the user estimatedCredits, then ask a normal confirmation question. Prefer the client's native question UI with Approve / Decline / Discuss choices when available; otherwise accept any unambiguous conversational approval. Never require a fixed phrase or ask the user to type a magic word. Only after approval, re-call with dryRun:false to actually spend."}, 'animations': {'type': 'array', 'items': {'type': 'string', 'minLength': 1}, 'maxItems': 16, 'minItems': 1, 'description': 'Animation slugs to generate, e.g. ["walk_right","idle"]. REQUIRED — each one is a separate paid video call.'}, 'videoModel': {'type': 'string', 'description': 'Override the video model.'}, 'animPrompts': {'type': 'object', 'description': "Per-animation extra guidance, keyed by animation slug. Folded into that animation's composed prompt.", 'additionalProperties': {'type': 'string'}}, 'characterId': {'type': 'string', 'description': 'Character id.'}, 'customAnims': {'type': 'object', 'description': "Define animations that are NOT part of the game type's standard set, keyed by the new slug.", 'additionalProperties': {'type': 'object', 'required': ['prompt'], 'properties': {'loop': {'type': 'boolean', 'description': 'Should it loop seamlessly.'}, 'prompt': {'type': 'string', 'minLength': 1, 'description': 'What the motion is.'}, 'duration': {'type': 'number', 'maximum': 10, 'minimum': 2, 'description': 'USER-REQUESTED OVERRIDE ONLY. Omit for the 2s default, even for a looping animation.'}, 'keepDirection': {'type': 'boolean', 'description': 'Lock the facing direction of the start frame.'}, 'anchorToGround': {'type': 'boolean', 'description': 'Pin each output frame to its visible feet so game physics owns vertical movement.'}}, 'additionalProperties': False}}, 'mirrorAnims': {'type': 'object', 'description': 'FREE mirrored copies, keyed newName → sourceName (e.g. { "walk_left": "walk_right" }). The source must be in this call\'s animations list; its fresh frames are flipped in the same job at no extra cost.', 'additionalProperties': {'type': 'string', 'minLength': 1}}, 'animDurations': {'type': 'object', 'description': 'USER-REQUESTED OVERRIDES ONLY (2-10s). Omit this field by default: every animation, including walks and loops, defaults to 2s. Never choose a longer clip unless the user explicitly requested that duration. Longer clips cost more.', 'additionalProperties': {'type': 'number', 'maximum': 10, 'minimum': 2}}, 'targetFacings': {'type': 'object', 'description': 'Camera-relative facing per animation slug (n, ne, e, se, s, sw, w, nw). Omit for overhead; four_direction accepts only n/e/s/w. Use this for custom actions and any standard action whose slug does not itself encode the intended direction.', 'additionalProperties': {'enum': ['s', 'se', 'e', 'ne', 'n', 'nw', 'w', 'sw'], 'type': 'string'}}, 'idempotencyKey': {'type': 'string', 'minLength': 1, 'description': 'Optional Idempotency-Key for the real (dryRun:false) call. Omit and one is minted per call. Reuse the SAME value when retrying a call that failed with ENTITY_BUSY / 402 / 429 so the retry cannot double-dispatch.'}, 'poseLastFrameIds': {'type': 'object', 'description': 'Optional per-animation END anchor pose ids, keyed by animation slug. Resolve ids with list_character_poses and use only status:"done" poses. The same pose id may be used for both endpoints of a loop.', 'additionalProperties': {'type': 'string', 'minLength': 1}}, 'poseFirstFrameIds': {'type': 'object', 'description': 'Optional per-animation START anchor pose ids, keyed by animation slug. Resolve ids with list_character_poses and use only status:"done" poses. Omit an entry to let the server choose/generate its anchor.', 'additionalProperties': {'type': 'string', 'minLength': 1}}, 'animationDirectionMode': {'enum': ['overhead', 'four_direction', 'eight_direction'], 'type': 'string', 'description': 'Choose this BEFORE selecting animations for a topdown character and pass it on dry-run plus confirmation. Preselect get_character.animationDirection.mode when present (Luna suggestion; user may override). overhead uses one rotatable true-overhead sprite, base action names, and no 360; four_direction uses S/N/E/W animations; eight_direction also uses NE/SE/SW/NW. The confirmed choice is saved on the character.'}, 'animationPipelineAssignmentToken': {'type': 'string', 'description': "Opaque server proof returned by this tool's dry-run. Copy it verbatim into the confirmed dryRun:false call; never create or edit it. If the server reports ANIMATION_PIPELINE_ASSIGNMENT_EXPIRED, preview again."}}, 'additionalProperties': False}
generate_character_turn
Generate a 360 turn animation
PAID (200 credits — ONE 2-second rotation video), except retrying the exact failed job is FREE while its provider task/result or validated stored source survives. The default dry run reports 0 credits and recovery:"stored_artifact" in that case; confirmation revives the same job and never starts another paid provider task. Spins the character through a full 360 so the sprite exists from every side; its frames are also what the directional-pose extractor reads, which is what makes top-down characters usable in more than one facing (isometric projects use top-down characters). ONLY topdown and isometric characters are supported — any other game type errors 400 TURN_NOT_SUPPORTED (topdown_overhead: the engine rotates the sprite image; platformer/point_and_click: side/front views, mirror instead). Eligibility reads the STORED CHARACTER gameType, not its project: a topdown character inside a platformer project is supported. This explicit visible turn is separate from the internal mid-walk rotation that generate_character_animation may plan for eligible directional walk/run clips; do not call it as mandatory setup for every animation. Lands as the animation "turn", or "turn_<seedPoseId>" when seeded from a pose. An existing turn is NEVER replaced: an occupied name becomes turn_2, turn_3, and so on. It 409s (ENTITY_BUSY) while ANY other job is running on the character, because it rebuilds the spritesheet: poll that job first. Returns { jobId, animation, resumed } — poll get_job. A successful standalone 360 finishes at done after its animation is rebuilt; it does not open the directional-pose approval checkpoint. Only an internal 360 planned by generate_character_animation pauses for directionalPoseReview before dependent animation videos start. If a retained provider URL is repeatedly proven expired, support may set discardPendingResult:true and preview again; that explicit escape abandons the stale result and is a new paid generation. DEFAULTS TO A COST PREVIEW — see the dryRun argument.
Acceso externo
Esquema de entrada
{'type': 'object', 'required': ['characterId'], 'properties': {'dryRun': {'type': 'boolean', 'default': True, 'description': "DEFAULTS TO TRUE. While true this returns only a cost quote ({ estimatedCredits, balance, spendCapDaily, spentLast24h, capRemaining }) and executes nothing. Show the user estimatedCredits, then ask a normal confirmation question. Prefer the client's native question UI with Approve / Decline / Discuss choices when available; otherwise accept any unambiguous conversational approval. Never require a fixed phrase or ask the user to type a magic word. Only after approval, re-call with dryRun:false to actually spend."}, 'seedPoseId': {'type': 'string', 'description': 'Rotate a specific DONE pose instead of the character\'s default image. Lands as "turn_<poseId>".'}, 'characterId': {'type': 'string', 'description': 'Character id.'}, 'idempotencyKey': {'type': 'string', 'minLength': 1, 'description': 'Optional Idempotency-Key for the real (dryRun:false) call. Omit and one is minted per call. Reuse the SAME value when retrying a call that failed with ENTITY_BUSY / 402 / 429 so the retry cannot double-dispatch.'}, 'discardPendingResult': {'type': 'boolean', 'description': 'Support escape hatch only: true abandons a repeatedly expired/unusable failed provider result and previews/starts a new paid turn. Omit for normal free recovery.'}}, 'additionalProperties': False}
generate_pose
Generate a character pose
PAID (standard 1K: 60 credits; 2K: 100; 4K: 150; premium models may differ). Generate a new pose for a character from a text description. DEFAULTS TO A COST PREVIEW — see the dryRun argument. Returns { poseId } once executed; poses have no jobId, so poll list_character_poses until status is done or error.
Acceso externo
Esquema de entrada
{'type': 'object', 'required': ['characterId', 'name', 'poseDescription'], 'properties': {'name': {'type': 'string', 'minLength': 1, 'description': 'Short pose name, e.g. "casting".'}, 'dryRun': {'type': 'boolean', 'default': True, 'description': "DEFAULTS TO TRUE. While true this returns only a cost quote ({ estimatedCredits, balance, spendCapDaily, spentLast24h, capRemaining }) and executes nothing. Show the user estimatedCredits, then ask a normal confirmation question. Prefer the client's native question UI with Approve / Decline / Discuss choices when available; otherwise accept any unambiguous conversational approval. Never require a fixed phrase or ask the user to type a magic word. Only after approval, re-call with dryRun:false to actually spend."}, 'imageModel': {'type': 'string', 'description': 'Override the image model.'}, 'characterId': {'type': 'string', 'description': 'Character id.'}, 'idempotencyKey': {'type': 'string', 'minLength': 1, 'description': 'Optional Idempotency-Key for the real (dryRun:false) call. Omit and one is minted per call. Reuse the SAME value when retrying a call that failed with ENTITY_BUSY / 402 / 429 so the retry cannot double-dispatch.'}, 'poseDescription': {'type': 'string', 'minLength': 1, 'description': 'What the character should be doing, e.g. "kneeling, shield raised".'}, 'referencePoseId': {'type': 'string', 'description': 'Seed from an existing DONE pose instead of the base image.'}}, 'additionalProperties': False}
generate_project_intake
Turn a game idea into a project foundation
PAID but very cheap and SYNCHRONOUS. Use this for a broad game vision, story, or mood before create_project. Returns a proposed project name, game type, art style, world description, creative guidance, and a validated styleGuide object ready to pass unchanged to create_project. It stores nothing and does not create assets. Afterward, inspect the game repository and propose an MVP art plan before any image or animation spend. Skip this tool when the user already supplied a complete project/style guide or asked for one specific asset. DEFAULTS TO A COST PREVIEW — see the dryRun argument.
Acceso externo
Esquema de entrada
{'type': 'object', 'required': ['description'], 'properties': {'dryRun': {'type': 'boolean', 'default': True, 'description': "DEFAULTS TO TRUE. While true this returns only a cost quote ({ estimatedCredits, balance, spendCapDaily, spentLast24h, capRemaining }) and executes nothing. Show the user estimatedCredits, then ask a normal confirmation question. Prefer the client's native question UI with Approve / Decline / Discuss choices when available; otherwise accept any unambiguous conversational approval. Never require a fixed phrase or ask the user to type a magic word. Only after approval, re-call with dryRun:false to actually spend."}, 'nameHint': {'type': 'string', 'description': 'Optional working title. Explicit user choices win over inference.'}, 'styleHint': {'type': 'string', 'description': 'Optional locked art direction.'}, 'references': {'type': 'array', 'items': {'type': 'object', 'required': ['url', 'tag'], 'properties': {'tag': {'type': 'string', 'description': 'What this reference controls, such as palette, character, or environment.'}, 'url': {'type': 'string', 'description': 'Reference image URL.'}, 'name': {'type': 'string', 'description': 'Optional label.'}}, 'additionalProperties': False}, 'maxItems': 6}, 'description': {'type': 'string', 'minLength': 1, 'description': "The game vision in the user's own words: story, mechanics, setting, mood, and audience."}, 'gameTypeHint': {'enum': ['platformer', 'topdown', 'topdown_overhead', 'isometric', 'point_and_click'], 'type': 'string', 'description': 'Optional locked gameplay camera/type.'}, 'idempotencyKey': {'type': 'string', 'minLength': 1, 'description': 'Optional Idempotency-Key for the real (dryRun:false) call. Omit and one is minted per call. Reuse the SAME value when retrying a call that failed with ENTITY_BUSY / 402 / 429 so the retry cannot double-dispatch.'}}, 'additionalProperties': False}
generate_project_vision
Generate a project creative brief
PAID but very cheap (one configured text-model call) and SYNCHRONOUS — the result comes back in this response, there is no jobId to poll. Turns a rough game idea into { aiVision, aiPromptGuidance, aiNegativeGuidance }: a written creative direction plus the positive/negative guidance to reuse in later prompts, which is what keeps a whole project visually consistent instead of every asset drifting. Stores NOTHING — feed the wording into create_project (description/style) and into your own prompts. DEFAULTS TO A COST PREVIEW — see the dryRun argument.
Acceso externo
Esquema de entrada
{'type': 'object', 'required': ['name', 'gameType'], 'properties': {'name': {'type': 'string', 'minLength': 1, 'description': 'Working title of the game.'}, 'style': {'type': 'string', 'description': 'Art style, if the user already has one in mind.'}, 'dryRun': {'type': 'boolean', 'default': True, 'description': "DEFAULTS TO TRUE. While true this returns only a cost quote ({ estimatedCredits, balance, spendCapDaily, spentLast24h, capRemaining }) and executes nothing. Show the user estimatedCredits, then ask a normal confirmation question. Prefer the client's native question UI with Approve / Decline / Discuss choices when available; otherwise accept any unambiguous conversational approval. Never require a fixed phrase or ask the user to type a magic word. Only after approval, re-call with dryRun:false to actually spend."}, 'gameType': {'enum': ['platformer', 'topdown', 'topdown_overhead', 'isometric', 'point_and_click'], 'type': 'string', 'description': 'The view the game is played in — the brief is written for it.'}, 'references': {'type': 'array', 'items': {'type': 'object', 'required': ['url', 'tag'], 'properties': {'tag': {'type': 'string', 'description': 'What this reference is for, e.g. "character", "palette", "environment".'}, 'url': {'type': 'string', 'description': 'Reference image URL.'}, 'name': {'type': 'string', 'description': 'Optional label.'}}, 'additionalProperties': False}, 'maxItems': 6, 'description': 'Up to 6 tagged reference images the model can look at.'}, 'description': {'type': 'string', 'description': "The idea in the user's own words: setting, mood, mechanics."}, 'idempotencyKey': {'type': 'string', 'minLength': 1, 'description': 'Optional Idempotency-Key for the real (dryRun:false) call. Omit and one is minted per call. Reuse the SAME value when retrying a call that failed with ENTITY_BUSY / 402 / 429 so the retry cannot double-dispatch.'}}, 'additionalProperties': False}
generate_ui_pack
Generate UI Pack
Get a cost preview for an exact component list and batch breakdown, then generate using the returned signed quote. Every paid raster/SVG batch is 100 credits; one pack action can contain several batches. Fonts are free. Defaults to dry-run; never alter the quote.
Acceso externo
Esquema de entrada
{'type': 'object', 'required': ['packId'], 'properties': {'quote': {'type': 'object', 'description': 'Unmodified signed quote returned by the dry-run. Required when dryRun is false.', 'additionalProperties': {}}, 'dryRun': {'type': 'boolean', 'default': True, 'description': 'Show the user estimatedCredits and ask whether to proceed, unless already authorized in this session. Prefer the client native question UI with Approve / Decline / Discuss choices; otherwise accept any unambiguous conversational approval. Never require a fixed phrase or magic word. Then set false and supply the returned quote.'}, 'packId': {'type': 'string', 'format': 'uuid', 'description': 'Owned UI Pack ID.'}, 'request': {'type': 'object', 'required': ['requestId', 'components'], 'properties': {'requestId': {'type': 'string', 'maxLength': 128, 'minLength': 8}, 'components': {'type': 'array', 'items': {'type': 'object', 'required': ['kind', 'role', 'name', 'description', 'quantity'], 'properties': {'kind': {'enum': ['icon', 'frame', 'panel', 'bar', 'control', 'indicator'], 'type': 'string'}, 'name': {'type': 'string'}, 'role': {'type': 'string'}, 'method': {'enum': ['recommended', 'illustrated', 'vector'], 'type': 'string', 'default': 'recommended'}, 'quantity': {'type': 'integer', 'maximum': 64, 'minimum': 1}, 'description': {'type': 'string'}, 'indicatorAttachment': {'enum': ['ground', 'actor', 'screen'], 'type': 'string', 'description': 'World indicators only. Ground follows the project camera; actor and screen remain flat. Omitted means ground.'}, 'requiredCapabilities': {'type': 'array', 'items': {'enum': ['artwork', 'hollow', 'fill', 'resize', 'text', 'states', 'projection'], 'type': 'string'}, 'default': ['artwork']}}, 'additionalProperties': False}, 'maxItems': 64, 'minItems': 1}}, 'additionalProperties': False}, 'idempotencyKey': {'type': 'string', 'maxLength': 128, 'minLength': 8, 'description': 'Reuse the same key when retrying a confirmed request.'}}, 'additionalProperties': False}
get_asset
Get asset
One asset with its revision iterations and typed animation projection. Accepts the asset id OR its slug. New Material assets use the wire-compatible `texture` type and expose a typed `material` block containing the versioned donor recipe and its platformer, topdown, or isometric projection. Legacy textures may instead carry metadata.seamless.seamMetric and support fix_asset_seams. Generation Contract assets expose `generationPlan` plus `extraction`. `extraction.status:"exact"` means the planned number of logical foreground objects was recovered; `"recovered"` means small detached decorations were safely grouped; `"needs_review"` preserves every detected object and carries a warning instead of silently deleting or inventing one. `grid.tiles[].url` returns each extracted object as its own transparent PNG; the grid is a rebuilt presentation layout, not the geometry used to cut the model output. Legacy assets without `extraction` retain their historical fixed-grid metadata and should still be reviewed with the old grid fields. Backgrounds carry a `background` block echoing the sub-type, view and the aspect ratio actually generated — read it back to confirm the shape when you left aspectRatio unset.
Solo lectura Acceso externo Idempotente
Esquema de entrada
{'type': 'object', 'required': ['assetId'], 'properties': {'assetId': {'type': 'string', 'description': 'Asset id or slug.'}}, 'additionalProperties': False}
get_character
Get character
The full PhaserCharacter JSON: animations, frameSize, gameType, animationDirection, per-group atlas + spritesheet URLs, poses and mount points. For topdown characters, animationDirection is Luna's saved mode suggestion or the user's last override; preselect it before asking for overhead, four-direction, or eight-direction animation generation. The top-level animationQualityGate is the delivery verdict per animation: ready:true means its deliveredIssues list is empty; needs_review means follow its actions before claiming the animation is ready; unscored means inspect the frames because no machine score can certify it. Check collision automatically: while an animation plays use animations[activeName].collisionBody before the character-level collisionBody; while displaying a pose use pose.collisionBody first. Fall back to a bbox only when the resolved body is absent. Bodies are normalized to the FULL untrimmed frameSize — never subtract atlas spriteSourceSize/alpha-trim offsets. Every binary URL is presigned and expires in ~1h — download immediately, never store or commit one. The in-app preview exercises shared export data, but validate the downloaded bundle and its supplied loader in the target engine before shipping.
Solo lectura Acceso externo Idempotente
Esquema de entrada
{'type': 'object', 'required': ['characterId'], 'properties': {'characterId': {'type': 'string', 'description': 'Character id.'}}, 'additionalProperties': False}
get_character_manifest
Get character manifest
The self-describing export contract (tizo-export.json manifest + its JSON Schema) without downloading the zip. Use this to learn the Phaser integration shape and field meanings before wiring an export into a game project. Its files[] is a logical canonical inventory, not an exact archive listing; use get_export_command and read the downloaded zip's tizo-export.json when exact shipped contents matter.
Solo lectura Acceso externo Idempotente
Esquema de entrada
{'type': 'object', 'required': ['characterId'], 'properties': {'characterId': {'type': 'string', 'description': 'Character id.'}}, 'additionalProperties': False}
get_credits
Get credit balance
Current credit balance, and optionally the recent ledger. Every ledger entry carries apiKeyId/apiKeyName so you can see exactly what THIS key spent. Check the balance before proposing any paid generation. When the balance will not cover what the user wants, say what IS affordable rather than only that they are short — "1200 for all three animations, you have 900, so two now or top up for all three" is the useful answer. API-key calls can use the account's full wallet balance; the dashboard-only 600-credit experiment and its activation exception do not apply. freeCreditLimit therefore reports applies:false with exemptionReason:"api_key". Two remaining walls need OPPOSITE advice: running out of BALANCE is fixed by buying credits (the 402 carries a topUpUrl — send that link, never quote prices, they change), while hitting the key's DAILY SPEND CAP is not a money problem at all — the credits are already in the account, and the fixes are raising the cap or waiting for resetsAt. Never suggest a purchase for a cap trip. If the user asks HOW to raise the cap: the 403 carries capSettingsUrl — give them that link and tell them to edit the key there. YOU cannot change it, by design: the cap edit needs a logged-in session and is unreachable with an API key, because a key that could raise its own cap would not be a cap. Do not retry hoping it passes, and do not ask them to paste credentials.
Solo lectura Acceso externo Idempotente
Esquema de entrada
{'type': 'object', 'properties': {'limit': {'type': 'integer', 'maximum': 500, 'minimum': 1, 'description': 'Max items to return (default 100, max 500).'}, 'apiKeyId': {'type': 'string', 'description': 'Filter ledger entries to one key (UUID).'}, 'includeLedger': {'type': 'boolean', 'description': 'Also return recent ledger entries.'}}, 'additionalProperties': False}
get_custom_fields
Get custom field definitions
Typed custom-field definitions for a character or asset, plus the derived builtins ($animation for characters, $autoplay/$loop for animated assets). Per-placement VALUES ride on get_map; map exports bake resolved values and ship fields-schema.json. Read-only here — definitions are edited in the dashboard.
Solo lectura Acceso externo Idempotente
Esquema de entrada
{'type': 'object', 'required': ['kind', 'entityId'], 'properties': {'kind': {'enum': ['character', 'asset'], 'type': 'string', 'description': 'Which entity table to read.'}, 'entityId': {'type': 'string', 'description': 'Character id, or asset id/slug.'}}, 'additionalProperties': False}
get_export_command
Get export download command
Build the authenticated download URL + a ready-to-run curl line for a zip export (character engine bundle, asset bundle, or map bundle). Run the curl in your own shell — zips are multi-MB binaries and must not be passed through the model. Phaser character exports may select size 512, 256, 128, or 64; the selected sheet/atlas pairs keep canonical size-agnostic filenames. Sparrow XML is character-only: preserve the bundle's Sparrow prefixes and multisparrow assetPath routing. This tool exports whole characters, not a dashboard single-animation selection. Requires SPRITESHIP_API_KEY to be set in that shell.
Solo lectura Acceso externo Idempotente
Esquema de entrada
{'type': 'object', 'required': ['target', 'entityId', 'engine'], 'properties': {'size': {'enum': ['512', '256', '128', '64'], 'type': 'string', 'description': 'Phaser character exports only — narrow the zip to one downscale variant. Godot, Unity, GameMaker, Unreal and Sparrow XML use full-resolution source frames; omit size for them.'}, 'engine': {'enum': ['phaser', 'godot', 'unity', 'gamemaker', 'fnf', 'unreal', 'tiled'], 'type': 'string', 'description': 'Target engine. "fnf" is characters only and emits Sparrow PNG/XML plus character JSON. "tiled" is maps only; sprites have no Tiled emitter. "unreal" is beta Paper2D artwork/flipbook import, not automatic gameplay or native-engine certification.'}, 'target': {'enum': ['character', 'asset', 'map'], 'type': 'string', 'description': 'What to export.'}, 'entityId': {'type': 'string', 'description': 'Character id, asset id/slug, or map id.'}}, 'additionalProperties': False}
get_frames
Get animation frames
Presigned per-frame thumbnails for a character animation or an asset motion pair — never inline base64. Use format:"sheet" to get ONE index-labeled contact sheet, which lets you judge a whole capture in a single look; that is the intended way to pick which frames to keep before calling select_frames.
Solo lectura Acceso externo Idempotente
Esquema de entrada
{'type': 'object', 'required': ['target', 'entityId'], 'properties': {'size': {'anyOf': [{'type': 'integer', 'maximum': 1024, 'minimum': 16}, {'type': 'string', 'const': 'full'}], 'description': 'Max thumbnail edge (default 256, cap 1024). "full" opts out of downscaling.'}, 'format': {'enum': ['thumbnails', 'sheet'], 'type': 'string', 'description': '"sheet" returns one labeled contact sheet.'}, 'pairId': {'type': 'string', 'description': 'Motion pair id — required when target=assetPair.'}, 'target': {'enum': ['character', 'assetPair'], 'type': 'string', 'description': 'Frames of a character animation, or of an asset motion pair.'}, 'indices': {'type': 'string', 'description': 'Comma-separated frame indices to subset, e.g. "0,4,8".'}, 'entityId': {'type': 'string', 'description': 'Character id (target=character) or asset id/slug (target=assetPair).'}, 'animation': {'type': 'string', 'description': 'Animation slug — required when target=character.'}}, 'additionalProperties': False}
get_integration_status
Check SpriteShip skill updates
Free advisory version check. Call once when starting SpriteShip work in a session, passing the version actually read from the installed skill; omit it when unknown. Report an available update with its release summary and manual update guide once, then continue compatible work. Unknown is not outdated; never downgrade a newer local copy. Does not install files, grant permissions, spend credits or require an update.
Solo lectura Acceso externo Idempotente
Esquema de entrada
{'type': 'object', 'properties': {'installedSkillVersion': {'type': 'string', 'pattern': '^(0|[1-9]\\d{0,5})\\.(0|[1-9]\\d{0,5})\\.(0|[1-9]\\d{0,5})$', 'description': 'Stable major.minor.patch version from the installed SpriteShip instructions; omit for unversioned or unknown copies.'}}, 'additionalProperties': False}
get_job
Get job status
Poll a background job. Every write tool that returns a jobId is polled here. On status:"error" the response is enriched with failureKind, failureAction, attempt-scoped creditsRefunded, retryCost, retryMode, and retryRecovery. If failureAction is edit_input, change the prompt or reference inputs and create a new generation instead of calling retry. Poll every few seconds — generations routinely take minutes. THIS IS HOW YOU LEARN WHAT A CREATE CALL MADE: characterIds / assetIds list the entities this job produced — ONE normally, FOUR when create_character ran with the 2x2 variation grid — and on status:"done" characterPreviews carries a presigned image per character so you can show the user the options and let them pick. IMPORTANT FOR CHARACTER ANIMATION JOBS: status:"done" means processing finished, not that the animation is ready. The response carries animationQualityGate.status:"check_required" with the affected animationNames; you MUST call get_character and resolve each affected animation until its gate is ready (or report that it needs review). Do not export, sync, or claim completion before this check. queued:true means it has not started yet (waiting for a slot) and has spent nothing. On any TERMINAL status (done or error) the response carries a `credits` block — { charged, refunded, net, balance, spendCapDaily, spentLast24h, capRemaining }. TELL THE USER `credits.net` AND `credits.balance` when the work finishes, in one short line. Report `net`, never your own pre-flight estimate: the two differ routinely — a 2x2 grid is ONE charge for four entities and failed steps are refunded — so quoting the estimate can report a cost that never happened. Do NOT attach a purchase suggestion to a successful generation; only raise buying credits when a call is actually blocked or the balance will not cover what the user asked for next.
Solo lectura Acceso externo Idempotente
Esquema de entrada
{'type': 'object', 'required': ['jobId'], 'properties': {'jobId': {'type': 'string', 'description': 'Job id.'}}, 'additionalProperties': False}
get_map
Get map
A map row plus its saved level data, revision and dependency-sensitive contentVersion for plan_sync. Preserve the returned contentVersion in the map lock entry after a successful import. Every placement has an immutable internal id and may have a user-authored mapData.materialRendering v1 snapshots the art style with optional profile, edgeMode and pixelSize overrides. Preserve it; it affects materials only, never geometry/physics. Hard edges suppress feathering without deleting saved blend widths. Absent settings retain original appearance. materialArea v1 visual fill: preserve its closed shape, material revision, repeatSize and blendWidthPx (inherits layer materialAreaBlendPx, default 16). Areas imply no swimming, damage or collision. Terrain layer can contain both materialGrid cells and materialArea objects: draw cells first, then shapes in array order. Honor materialArea.hidden. Terrain stays above Background and below object layers. Each placement can have a name plus map-unique gameplayId for game-code references; layers, Navigation paths, and per-placement custom-field values are included. Terrain materialGrid cells include elevation and continuous ramps; appearance.elevationShading (0–1, default 0.35) controls slope lighting, opaque cliff shading, and height-edge cues together, not collision. Zero disables all elevation lighting. Cell dimensions are authoritative; editor grid guides are not saved. Returns mapData:null when the map has never been saved.
Solo lectura Acceso externo Idempotente
Esquema de entrada
{'type': 'object', 'required': ['mapId'], 'properties': {'mapId': {'type': 'string', 'description': 'Map id.'}}, 'additionalProperties': False}
get_map_draft
Read a map draft
Read a prepared map draft, resolved document, hash and expiry.
Solo lectura Acceso externo Idempotente
Esquema de entrada
{'type': 'object', 'required': ['draftId'], 'properties': {'draftId': {'type': 'string', 'format': 'uuid'}}, 'additionalProperties': False}
get_project
Get project
One project with its description, registered mount slots, and saved style guide. The legacy assetSuggestions field is currently always null because automatic suggestions are disabled; do not poll for it.
Solo lectura Acceso externo Idempotente
Esquema de entrada
{'type': 'object', 'required': ['projectId'], 'properties': {'projectId': {'type': 'string', 'description': 'Project id.'}}, 'additionalProperties': False}
get_project_export_command
Download complete game project
Return an authenticated shell download command for a ready project export job. This tool checks status first and never starts a build. Run the command outside the model; do not transmit ZIP bytes through MCP. Supports Phaser, Godot and Unity.
Solo lectura Acceso externo Idempotente
Esquema de entrada
{'type': 'object', 'required': ['projectId', 'jobId'], 'properties': {'jobId': {'type': 'string'}, 'projectId': {'type': 'string'}}, 'additionalProperties': False}
get_project_export_review
Review complete project export
FREE. Check all saved maps, character and asset dependencies, choose the starting map/player, and inspect target-runtime compatibility before downloading an editable complete Phaser, Godot or Unity project. Errors block export; custom game code remains your responsibility.
Solo lectura Acceso externo Idempotente
Esquema de entrada
{'type': 'object', 'required': ['projectId', 'engine'], 'properties': {'engine': {'enum': ['phaser', 'godot', 'unity'], 'type': 'string'}, 'projectId': {'type': 'string'}, 'startMapId': {'type': 'string'}, 'playerCharacterId': {'type': 'string'}}, 'additionalProperties': False}
get_project_export_status
Check complete project export
FREE. Read a queued export job. Poll queued/running jobs about every two seconds. Ready jobs include the artifact size and expiry; failed jobs explain what to fix before retrying. Use get_project_export_command only once ready.
Solo lectura Acceso externo Idempotente
Esquema de entrada
{'type': 'object', 'required': ['projectId', 'jobId'], 'properties': {'jobId': {'type': 'string'}, 'projectId': {'type': 'string'}}, 'additionalProperties': False}
get_project_style_guide
Read project style guide
Read the current guide; old projects without an adopted guide receive an initial suggestion. Existing assets retain their saved guide versions.
Solo lectura Acceso externo Idempotente
Esquema de entrada
{'type': 'object', 'required': ['projectId'], 'properties': {'projectId': {'type': 'string'}}, 'additionalProperties': False}
get_subscription_allowances
Get enabled subscription allowances
Read the currently enabled subscriber benefits and their separate monthly limits, caps and balances. Disabled benefits return zeroed values and cannot be used. Unused units accumulate up to three monthly grants while the feature is enabled. These are not generation credits.
Solo lectura Acceso externo Idempotente
Esquema de entrada
{'type': 'object', 'properties': {}, 'additionalProperties': False}
get_ui_pack
Read a UI Pack
Read components, immutable revisions, capabilities, fonts and batch progress. Artwork URLs expire; native engine capability gaps are not successful tests.
Solo lectura Acceso externo Idempotente
Esquema de entrada
{'type': 'object', 'required': ['packId'], 'properties': {'packId': {'type': 'string', 'format': 'uuid', 'description': 'Owned UI Pack ID.'}}, 'additionalProperties': False}
get_ui_pack_batch
Read UI Pack batch
Read one paid batch and retained source URL; provider completion does not prove usable component delivery.
Solo lectura Acceso externo Idempotente
Esquema de entrada
{'type': 'object', 'required': ['packId', 'batchId'], 'properties': {'packId': {'type': 'string', 'format': 'uuid', 'description': 'Owned UI Pack ID.'}, 'batchId': {'type': 'string', 'format': 'uuid'}}, 'additionalProperties': False}
get_ui_pack_batch_recovery
Inspect retained UI sheet for recovery
Read original PNG dimensions, expiring image URL, source hash, and exact delivered/missing slots for an illustrated batch needing review. Inspect artwork before choosing crops.
Solo lectura Acceso externo Idempotente
Esquema de entrada
{'type': 'object', 'required': ['packId', 'batchId'], 'properties': {'packId': {'type': 'string', 'format': 'uuid', 'description': 'Owned UI Pack ID.'}, 'batchId': {'type': 'string', 'format': 'uuid'}}, 'additionalProperties': False}
get_ui_pack_export_command
Download UI Pack command
Return an authenticated curl command for a whole/selected UI Pack ZIP or component source. Run locally; never put multi-MB ZIP data into model context. Phaser has browser behavior coverage; Godot/Unity native acceptance is pending; GameMaker/Unreal deliver artwork, Tiled transports metadata. Recovery artworkOnly must be explicit.
Solo lectura Acceso externo Idempotente
Esquema de entrada
{'type': 'object', 'required': ['packId'], 'properties': {'engine': {'enum': ['phaser', 'godot', 'unity', 'gamemaker', 'unreal', 'tiled'], 'type': 'string', 'default': 'phaser'}, 'packId': {'type': 'string', 'format': 'uuid', 'description': 'Owned UI Pack ID.'}, 'artworkOnly': {'type': 'boolean', 'default': False}, 'componentIds': {'type': 'array', 'items': {'type': 'string', 'format': 'uuid', 'description': 'Owned component ID within this pack.'}}, 'sourceFormat': {'enum': ['svg', 'png'], 'type': 'string', 'default': 'png'}, 'sourceComponentId': {'type': 'string', 'format': 'uuid', 'description': 'Owned component ID within this pack.'}}, 'additionalProperties': False}
import_asset_image
Import a transparent asset image
Free imports: import ONE still PNG or WebP as an Object or Character. Unlimited for every account, including free users, with zero credits and no subscription or allowance check. Before uploading, tell the user: transparency required, one clear complete subject, clean edges, consistent project style and camera, no text/watermark, up to 10 MB and 4096px per side; recommend 256px or more except intentional pixel art. No videos, GIFs or animated files; upload does not remove backgrounds or fix quality. Set confirmed only after this notice and approval. For local files, prefer POST /api/v1/asset-imports multipart file/projectId/name/kind/requestId rather than passing large base64 through model context. Persist requestId for safe network retries.
Acceso externo
Esquema de entrada
{'type': 'object', 'required': ['projectId', 'name', 'kind', 'requestId', 'imageBase64'], 'properties': {'kind': {'enum': ['static', 'character'], 'type': 'string'}, 'name': {'type': 'string', 'maxLength': 100, 'minLength': 1}, 'confirmed': {'type': 'boolean'}, 'projectId': {'type': 'string'}, 'requestId': {'type': 'string', 'format': 'uuid'}, 'imageBase64': {'type': 'string'}}, 'additionalProperties': False}
list_assets
List assets
Assets (Object / Object Collection / staged / background / Environment Kit / Terrain Materials) with slug, hasAnimation, updatedAt, tags and favourite. Wire types remain tileset for collections, terrain for kits and texture for brushable materials. Object was formerly called Static Asset; its API type remains `static`. hasAnimation is data-derived: ANY asset type can carry an animation, so never infer it from the type.
Solo lectura Acceso externo Idempotente
Esquema de entrada
{'type': 'object', 'properties': {'name': {'type': 'string', 'description': 'Case-insensitive substring filter on the name.'}, 'slug': {'type': 'string', 'description': 'Exact slug match (a slug is an identifier — no partial hits).'}, 'type': {'enum': ['static', 'tileset', 'staged', 'background', 'terrain', 'texture'], 'type': 'string', 'description': 'Filter by asset type. Use `static` for Object (formerly Static Asset).'}, 'limit': {'type': 'integer', 'maximum': 500, 'minimum': 1, 'description': 'Max items to return (default 100, max 500).'}, 'projectId': {'type': 'string', 'description': 'Restrict to one project.'}}, 'additionalProperties': False}
list_character_poses
List character poses
All poses on a character: { id, name, prompt, status pending|done|error, url, direction, pendingSince, errorCode, creditsRefunded }. This is the poll target after generate_pose — pose generation has no job id. It is also the source of ready pose ids for generate_character_animation poseFirstFrameIds / poseLastFrameIds. A pose still pending long after pendingSince is stalled, not working.
Solo lectura Acceso externo Idempotente
Esquema de entrada
{'type': 'object', 'required': ['characterId'], 'properties': {'characterId': {'type': 'string', 'description': 'Character id.'}}, 'additionalProperties': False}
list_characters
List characters
Characters with the re-sync signals: contentVersion (opaque change token — compare for equality, never parse or order), hasActiveJob, apiReady, pose/animation counts, tags, favourite. Persist contentVersion per character and re-fetch only when it changes.
Solo lectura Acceso externo Idempotente
Esquema de entrada
{'type': 'object', 'properties': {'name': {'type': 'string', 'description': 'Case-insensitive substring filter on the name.'}, 'limit': {'type': 'integer', 'maximum': 500, 'minimum': 1, 'description': 'Max items to return (default 100, max 500).'}, 'projectId': {'type': 'string', 'description': 'Restrict to one project.'}}, 'additionalProperties': False}
list_map_revisions
List saved map revisions
List recoverable map revisions from editor and agent saves.
Solo lectura Acceso externo Idempotente
Esquema de entrada
{'type': 'object', 'required': ['mapId'], 'properties': {'mapId': {'type': 'string'}}, 'additionalProperties': False}
list_maps
List maps
Level-editor maps with updatedAt and hasMapData. hasMapData:false means the map was never saved and cannot be exported.
Solo lectura Acceso externo Idempotente
Esquema de entrada
{'type': 'object', 'properties': {'limit': {'type': 'integer', 'maximum': 500, 'minimum': 1, 'description': 'Max items to return (default 100, max 500).'}, 'projectId': {'type': 'string', 'description': 'Restrict to one project.'}}, 'additionalProperties': False}
list_projects
List projects
All of the user's projects: { id, name, gameType, style, itemCount, createdAt, updatedAt }. gameType (platformer / topdown / topdown_overhead / isometric / point_and_click) is the default perspective for new content — read it before generating anything. A character may override that default at creation; afterward its stored character gameType controls its own animation and turn behavior.
Solo lectura Acceso externo Idempotente
Esquema de entrada
{'type': 'object', 'properties': {'limit': {'type': 'integer', 'maximum': 500, 'minimum': 1, 'description': 'Max items to return (default 100, max 500).'}}, 'additionalProperties': False}
list_ui_fonts
List UI fonts
Read the retained licensed Google Fonts catalog. Existing font selection, preview and export cost zero customer credits.
Solo lectura Acceso externo Idempotente
Esquema de entrada
{'type': 'object', 'properties': {}, 'additionalProperties': False}
list_ui_packs
List UI Packs
List owned UI Packs, optionally within a project.
Solo lectura Acceso externo Idempotente
Esquema de entrada
{'type': 'object', 'properties': {'projectId': {'type': 'string'}}, 'additionalProperties': False}
map_authoring_context
Inspect map authoring context
Read project art, material recipes, limits, shape classes, current map JSON and revision. Inspect the returned artwork visually before selecting assets. Read your game code to establish movement/mechanics; SpriteShip fields are flexible metadata.
Solo lectura Acceso externo Idempotente
Esquema de entrada
{'type': 'object', 'required': ['projectId'], 'properties': {'mapId': {'type': 'string'}, 'projectId': {'type': 'string'}, 'assetOffset': {'type': 'integer', 'minimum': 0}}, 'additionalProperties': False}
map_authoring_schema
Read strict map document schema
Read the authoritative JSON Schema before composing a map. Use assetRef instead of inventing image URLs. Shapes, custom properties and paths retain their existing editor meanings.
Solo lectura Acceso externo Idempotente
Esquema de entrada
{'type': 'object', 'properties': {}, 'additionalProperties': False}
map_project_library
Read map assemblies and world graph
Read owned project maps, reusable detached assemblies, destination spawn IDs, room links and broken-link diagnostics. No browser required.
Solo lectura Acceso externo Idempotente
Esquema de entrada
{'type': 'object', 'required': ['projectId'], 'properties': {'projectId': {'type': 'string'}}, 'additionalProperties': False}
map_workbench_context
Read saved map capabilities and settings
Read saved camera, reference brief, gameplay, assemblies, links, tests and per-engine support. Runtime availability is distinct from playability evidence.
Solo lectura Acceso externo Idempotente
Esquema de entrada
{'type': 'object', 'required': ['mapId'], 'properties': {'mapId': {'type': 'string'}}, 'additionalProperties': False}
mirror_animation
Mirror an animation horizontally
FREE, no AI. Flip every cached frame of ONE animation horizontally and rebuild it — the cheap way to get walk_left from walk_right. NOT idempotent: calling it twice flips the animation back to its original orientation, so call it once and check the result before calling again. Frame count and order are preserved, so any frame selection stays valid. To keep BOTH directions, call duplicate_animation first and mirror the copy. Returns { jobId, mirrored } (frames flipped) — poll get_job.
Acceso externo
Esquema de entrada
{'type': 'object', 'required': ['characterId', 'animation'], 'properties': {'animation': {'type': 'string', 'description': 'Animation slug to flip in place.'}, 'characterId': {'type': 'string', 'description': 'Character id.'}}, 'additionalProperties': False}
phase_split
Split an animation into game phases
FREE, no AI. Carve ONE multi-state clip into separate game-phase animations by frame windows — the classic case is a jump becoming crouch/rise/fall/land, with fall looping while airborne and the rest playing once. Each phase becomes a real exportable animation; the source animation is untouched. Jump-family animations often carry a ready-made suggestion: get_character → animations[<anim>].phaseProposal — pass its phases through verbatim. Frame windows index the FULL capture. Returns { jobId, created } — poll get_job.
Acceso externo
Esquema de entrada
{'type': 'object', 'required': ['characterId', 'animation', 'phases'], 'properties': {'phases': {'type': 'array', 'items': {'type': 'object', 'required': ['id', 'startFrame', 'endFrame', 'loop'], 'properties': {'id': {'type': 'string', 'pattern': '^[a-zA-Z0-9_-]+$', 'maxLength': 64, 'minLength': 1, 'description': 'Slug for the new phase animation ([A-Za-z0-9_-]).'}, 'loop': {'type': 'boolean', 'description': 'Whether the phase loops (true for an airborne fall) or plays once.'}, 'role': {'type': 'string', 'maxLength': 32, 'description': 'Phase role from the proposal, e.g. "crouch" / "rise" / "fall" / "land".'}, 'label': {'type': 'string', 'maxLength': 120, 'description': 'Human-facing label.'}, 'endFrame': {'type': 'integer', 'minimum': 0, 'description': 'Last frame of the window (inclusive).'}, 'startFrame': {'type': 'integer', 'minimum': 0, 'description': 'First frame of the window (inclusive), indexing the FULL capture.'}}, 'additionalProperties': False}, 'maxItems': 6, 'minItems': 2, 'description': '2-6 phase windows. animations[<anim>].phaseProposal from get_character usually supplies these verbatim.'}, 'animation': {'type': 'string', 'description': 'Source animation slug (e.g. "jump").'}, 'characterId': {'type': 'string', 'description': 'Character id.'}}, 'additionalProperties': False}
plan_sync
Plan changed asset sync
Compare the versions in assets/spriteship/spriteship.lock.json with current SpriteShip state in one call. Returns unchanged/changed/unavailable per character, asset, map, or UI pack; exact animation frame-count/FPS/collision, revision, runtime-intent, map-shape and UI component summaries when the previous lock entry includes the snapshot returned by an earlier call; and explicit fetch/download/review-removal actions. Existing v1 lock files without snapshots still detect version changes, then upgrade by saving each returned snapshot. Requests may contain 100 entries; honor Retry-After if the weighted sync budget is reached. Never delete local files for an unavailable entity without user confirmation.
Solo lectura Acceso externo Idempotente
Esquema de entrada
{'type': 'object', 'required': ['entities'], 'properties': {'entities': {'type': 'array', 'items': {'type': 'object', 'required': ['kind', 'id'], 'properties': {'id': {'type': 'string', 'maxLength': 300, 'minLength': 1, 'description': 'Opaque entity id from the lock file.'}, 'kind': {'enum': ['character', 'asset', 'map', 'ui-pack'], 'type': 'string', 'description': 'Entity table represented by this lock entry.'}, 'engine': {'enum': ['phaser', 'godot', 'unity', 'gamemaker', 'fnf', 'unreal', 'tiled'], 'type': 'string', 'description': 'Export engine already used by this lock entry. Defaults to phaser; Sparrow XML supports characters; tiled supports maps and UI pack artwork.'}, 'version': {'anyOf': [{'type': 'string', 'maxLength': 300}, {'type': 'null'}], 'description': 'contentVersion for a character, map or the exact UI pack export; updatedAt for an asset.'}, 'snapshot': {'anyOf': [{'type': 'object', 'required': ['kind', 'name', 'frameSize', 'collisionBody', 'animations'], 'properties': {'kind': {'type': 'string', 'const': 'character'}, 'name': {'type': 'string', 'maxLength': 300}, 'frameSize': {'anyOf': [{'type': 'integer', 'exclusiveMinimum': 0}, {'type': 'null'}]}, 'animations': {'type': 'object', 'propertyNames': {'maxLength': 200}, 'additionalProperties': {'type': 'object', 'required': ['displayName', 'frameCount', 'fps', 'loop', 'collisionBody'], 'properties': {'fps': {'type': 'number', 'minimum': 0}, 'loop': {'type': 'boolean'}, 'frameCount': {'type': 'integer', 'minimum': 0}, 'displayName': {'anyOf': [{'type': 'string', 'maxLength': 200}, {'type': 'null'}]}, 'collisionBody': {'anyOf': [{'anyOf': [{'type': 'object', 'required': ['kind', 'cx', 'cy', 'hw', 'hh'], 'properties': {'cx': {'type': 'number'}, 'cy': {'type': 'number'}, 'hh': {'type': 'number'}, 'hw': {'type': 'number'}, 'rot': {'type': 'number'}, 'kind': {'type': 'string', 'const': 'rect'}}, 'additionalProperties': False}, {'type': 'object', 'required': ['kind', 'cx', 'cy', 'r'], 'properties': {'r': {'type': 'number'}, 'cx': {'type': 'number'}, 'cy': {'type': 'number'}, 'kind': {'type': 'string', 'const': 'circle'}}, 'additionalProperties': False}, {'type': 'object', 'required': ['kind', 'points'], 'properties': {'rot': {'type': 'number'}, 'kind': {'type': 'string', 'const': 'polygon'}, 'points': {'type': 'array', 'items': {'type': 'object', 'required': ['x', 'y'], 'properties': {'x': {'type': 'number'}, 'y': {'type': 'number'}}, 'additionalProperties': False}, 'maxItems': 64, 'minItems': 3}}, 'additionalProperties': False}]}, {'type': 'null'}]}}, 'additionalProperties': False}}, 'collisionBody': {'anyOf': [{'anyOf': [{'type': 'object', 'required': ['kind', 'cx', 'cy', 'hw', 'hh'], 'properties': {'cx': {'type': 'number'}, 'cy': {'type': 'number'}, 'hh': {'type': 'number'}, 'hw': {'type': 'number'}, 'rot': {'type': 'number'}, 'kind': {'type': 'string', 'const': 'rect'}}, 'additionalProperties': False}, {'type': 'object', 'required': ['kind', 'cx', 'cy', 'r'], 'properties': {'r': {'type': 'number'}, 'cx': {'type': 'number'}, 'cy': {'type': 'number'}, 'kind': {'type': 'string', 'const': 'circle'}}, 'additionalProperties': False}, {'type': 'object', 'required': ['kind', 'points'], 'properties': {'rot': {'type': 'number'}, 'kind': {'type': 'string', 'const': 'polygon'}, 'points': {'type': 'array', 'items': {'type': 'object', 'required': ['x', 'y'], 'properties': {'x': {'type': 'number'}, 'y': {'type': 'number'}}, 'additionalProperties': False}, 'maxItems': 64, 'minItems': 3}}, 'additionalProperties': False}]}, {'type': 'null'}]}}, 'additionalProperties': False}, {'type': 'object', 'required': ['kind', 'name', 'slug', 'currentIterationId', 'iterationCount', 'hasAnimation', 'runtimeUse', 'tileRuntimeUses', 'animationPairs'], 'properties': {'kind': {'type': 'string', 'const': 'asset'}, 'name': {'type': 'string', 'maxLength': 300}, 'slug': {'anyOf': [{'type': 'string', 'maxLength': 200}, {'type': 'null'}]}, 'runtimeUse': {'type': 'string', 'maxLength': 100}, 'hasAnimation': {'type': 'boolean'}, 'animationPairs': {'type': 'object', 'propertyNames': {'maxLength': 200}, 'additionalProperties': {'type': 'object', 'required': ['label', 'frameCount', 'fps', 'iterationCount'], 'properties': {'fps': {'anyOf': [{'type': 'number', 'minimum': 0}, {'type': 'null'}]}, 'label': {'anyOf': [{'type': 'string', 'maxLength': 300}, {'type': 'null'}]}, 'frameCount': {'anyOf': [{'type': 'integer', 'minimum': 0}, {'type': 'null'}]}, 'iterationCount': {'type': 'integer', 'minimum': 0}}, 'additionalProperties': False}}, 'iterationCount': {'type': 'integer', 'minimum': 0}, 'tileRuntimeUses': {'type': 'array', 'items': {'type': 'string', 'maxLength': 200}, 'maxItems': 256}, 'currentIterationId': {'anyOf': [{'type': 'string', 'maxLength': 300}, {'type': 'null'}]}}, 'additionalProperties': False}, {'type': 'object', 'required': ['kind', 'name', 'widthPx', 'heightPx', 'gridSize', 'hasMapData'], 'properties': {'kind': {'type': 'string', 'const': 'map'}, 'name': {'type': 'string', 'maxLength': 300}, 'widthPx': {'type': 'integer', 'exclusiveMinimum': 0}, 'gridSize': {'type': 'integer', 'exclusiveMinimum': 0}, 'heightPx': {'type': 'integer', 'exclusiveMinimum': 0}, 'hasMapData': {'type': 'boolean'}}, 'additionalProperties': False}, {'type': 'object', 'required': ['kind', 'name', 'componentCount', 'components'], 'properties': {'kind': {'type': 'string', 'const': 'ui-pack'}, 'name': {'type': 'string', 'maxLength': 300}, 'components': {'type': 'object', 'propertyNames': {'maxLength': 200}, 'additionalProperties': {'type': 'object', 'required': ['name', 'revisionId', 'configurationHash', 'status'], 'properties': {'name': {'type': 'string', 'maxLength': 300}, 'status': {'type': 'string', 'maxLength': 200}, 'revisionId': {'anyOf': [{'type': 'string', 'maxLength': 300}, {'type': 'null'}]}, 'configurationHash': {'anyOf': [{'type': 'string', 'maxLength': 300}, {'type': 'null'}]}}, 'additionalProperties': False}}, 'componentCount': {'type': 'integer', 'minimum': 0}}, 'additionalProperties': False}], 'description': 'Copy the prior snapshot from the lock file verbatim. Omit for a v1 lock entry.'}, 'artworkOnly': {'type': 'boolean', 'description': 'UI pack only: preserve the originally authorized recovery mode; never silently enable it.'}, 'componentIds': {'type': 'array', 'items': {'type': 'string', 'format': 'uuid'}, 'maxItems': 256, 'minItems': 1, 'description': 'UI pack only: preserve the original selected component IDs; omit for the whole pack.'}}, 'additionalProperties': False}, 'maxItems': 100, 'minItems': 1}}, 'additionalProperties': False}
prepare_map_draft
Prepare and validate a map draft
FREE. Resolve owned artwork and validate a complete editable map without changing the live map. Preserve stable placement IDs on edits and pass expectedRevision from context. Returns immutable draft ID/hash and graph-only topology report. Inspect canonical overview and camera-sized region images before commit; no browser is required. Walkable surfaces/transitions are ground-view only, visualParts/reveal apply across game types. Graph reachability is not body-clearance or gameplay proof. Missing assets use existing quoted generation with user approval.
Acceso externo
Esquema de entrada
{'type': 'object', 'required': ['projectId', 'name', 'document'], 'properties': {'name': {'type': 'string'}, 'mapId': {'type': 'string'}, 'document': {'type': 'object', 'description': 'Complete map JSON conforming to map_authoring_schema.', 'additionalProperties': {}}, 'projectId': {'type': 'string'}, 'expectedRevision': {'type': 'integer', 'minimum': 0}}, 'additionalProperties': False}
prepare_map_edits
Prepare transactional map edits
FREE. Apply up to 200 stable-ID operations against expectedRevision. Returns a validated draft and semantic diff without changing the live map. Preview/test then use commit_map_draft. Settings use null to remove optional values. Deleting referenced objects must repair their dependencies in the same batch.
Acceso externo
Esquema de entrada
{'type': 'object', 'required': ['expectedRevision', 'operations', 'mapId'], 'properties': {'mapId': {'type': 'string'}, 'operations': {'type': 'array', 'items': {'anyOf': [{'type': 'object', 'required': ['op', 'layerId', 'object'], 'properties': {'op': {'type': 'string', 'const': 'put-object'}, 'object': {'type': 'object', 'additionalProperties': {}}, 'layerId': {'type': 'string', 'maxLength': 160, 'minLength': 1}}, 'additionalProperties': False}, {'type': 'object', 'required': ['op', 'id', 'x', 'y'], 'properties': {'x': {'type': 'number'}, 'y': {'type': 'number'}, 'id': {'type': 'string', 'maxLength': 160, 'minLength': 1}, 'op': {'type': 'string', 'const': 'move-object'}, 'layerId': {'type': 'string', 'maxLength': 160, 'minLength': 1}}, 'additionalProperties': False}, {'type': 'object', 'required': ['op', 'id'], 'properties': {'id': {'type': 'string', 'maxLength': 160, 'minLength': 1}, 'op': {'type': 'string', 'const': 'remove-object'}}, 'additionalProperties': False}, {'type': 'object', 'required': ['op', 'layer'], 'properties': {'op': {'type': 'string', 'const': 'put-layer'}, 'layer': {'type': 'object', 'additionalProperties': {}}}, 'additionalProperties': False}, {'type': 'object', 'required': ['op', 'id'], 'properties': {'id': {'type': 'string', 'maxLength': 160, 'minLength': 1}, 'op': {'type': 'string', 'const': 'remove-layer'}}, 'additionalProperties': False}, {'type': 'object', 'required': ['op', 'values'], 'properties': {'op': {'type': 'string', 'const': 'settings'}, 'values': {'type': 'object', 'additionalProperties': {}}}, 'additionalProperties': False}, {'type': 'object', 'required': ['op', 'assemblyId', 'x', 'y', 'instanceId'], 'properties': {'x': {'type': 'number'}, 'y': {'type': 'number'}, 'op': {'type': 'string', 'const': 'instantiate-assembly'}, 'assemblyId': {'type': 'string', 'maxLength': 160, 'minLength': 1}, 'instanceId': {'type': 'string', 'pattern': '^[a-zA-Z0-9_-]{1,80}$'}}, 'additionalProperties': False}]}, 'maxItems': 200, 'minItems': 1}, 'expectedRevision': {'type': 'integer', 'minimum': 0}}, 'additionalProperties': False}
preview_map_draft
Render map draft preview
FREE. Render the actual map composition using canonical terrain/export rendering. Omit viewport for an overview, or request world-pixel viewport and scale for camera-sized inspection (2048px output limit). Inspect this image and fix problems before saving; image output is sufficient for visual review without browser automation. Split-part clips and walking-surface draw order use canonical semantics. This static preview does not prove playability; test mechanics in the target engine.
Acceso externo
Esquema de entrada
{'type': 'object', 'required': ['draftId'], 'properties': {'scale': {'type': 'number', 'maximum': 4, 'minimum': 0.01, 'description': 'Requested output pixels per world pixel; default 1. Capped to 2048 output pixels on the longest edge. Read returned scale for the effective value.'}, 'draftId': {'type': 'string', 'format': 'uuid'}, 'viewport': {'type': 'object', 'required': ['x', 'y', 'widthPx', 'heightPx'], 'properties': {'x': {'type': 'number', 'minimum': 0, 'description': 'Left edge in map world pixels.'}, 'y': {'type': 'number', 'minimum': 0, 'description': 'Top edge in map world pixels.'}, 'widthPx': {'type': 'number', 'maximum': 65536, 'description': 'Region width in world pixels; must fit inside the map.', 'exclusiveMinimum': 0}, 'heightPx': {'type': 'number', 'maximum': 65536, 'description': 'Region height in world pixels; must fit inside the map.', 'exclusiveMinimum': 0}}, 'description': 'Omit for the entire map. Use camera-sized regions to inspect terrain and placement detail.', 'additionalProperties': False}}, 'additionalProperties': False}
rebuild_character
Rebuild a character from its cached frames
FREE, no AI. Re-render one animation from its durable cached frames by passing animation. This is the repair/refresh tool: use it when a sheet looks stale or wrong after a series of edits, or when a previous rebuild failed. It never re-generates art, so it cannot change what the character looks like — only how the frames are packed and normalized. Omit animation only for an explicit full-character maintenance rebuild. Exact pose-owned scale references make the targeted path sibling-independent; legacy captures retain their compatibility sizing fallback. Image-only characters return NO_ANIMATIONS_TO_REBUILD without creating a job. A targeted rebuild returns an operationId/jobId — poll get_job.
Acceso externo
Esquema de entrada
{'type': 'object', 'required': ['characterId'], 'properties': {'animation': {'type': 'string', 'description': 'Animation slug to rebuild independently. Omit only to rebuild the whole character.'}, 'characterId': {'type': 'string', 'description': 'Character id.'}}, 'additionalProperties': False}
recover_ui_pack_components
Recover missing UI components for free
Crop missing slots from a retained original PNG after visual review. No provider call or credit charge. Supply original-pixel rectangles and the current source hash; already delivered siblings remain untouched. Inspect validation after recovery.
Acceso externo
Esquema de entrada
{'type': 'object', 'required': ['packId', 'batchId', 'sourceHash', 'crops'], 'properties': {'crops': {'type': 'array', 'items': {'type': 'object', 'required': ['index', 'bounds'], 'properties': {'index': {'type': 'integer', 'maximum': 7, 'minimum': 0}, 'bounds': {'type': 'object', 'required': ['x', 'y', 'width', 'height'], 'properties': {'x': {'type': 'integer', 'minimum': 0}, 'y': {'type': 'integer', 'minimum': 0}, 'width': {'type': 'integer', 'maximum': 2048, 'minimum': 1}, 'height': {'type': 'integer', 'maximum': 2048, 'minimum': 1}}, 'additionalProperties': False}}, 'additionalProperties': False}, 'maxItems': 8, 'minItems': 1}, 'packId': {'type': 'string', 'format': 'uuid', 'description': 'Owned UI Pack ID.'}, 'batchId': {'type': 'string', 'format': 'uuid'}, 'sourceHash': {'type': 'string', 'pattern': '^[a-f0-9]{64}$'}}, 'additionalProperties': False}
regen_asset_pair
Regenerate one asset motion pair
PAID (Wan 3.0 costs 150 credits/second: 300 credits at the default 2-second settings). Re-run video generation for a SINGLE motion pair of an animated asset, leaving its other pairs alone. The new take lands as an additional iteration on that pair — earlier takes are preserved. DEFAULTS TO A COST PREVIEW — see the dryRun argument. Returns { jobId } — poll get_job.
Acceso externo
Esquema de entrada
{'type': 'object', 'required': ['assetId', 'pairId'], 'properties': {'dryRun': {'type': 'boolean', 'default': True, 'description': "DEFAULTS TO TRUE. While true this returns only a cost quote ({ estimatedCredits, balance, spendCapDaily, spentLast24h, capRemaining }) and executes nothing. Show the user estimatedCredits, then ask a normal confirmation question. Prefer the client's native question UI with Approve / Decline / Discuss choices when available; otherwise accept any unambiguous conversational approval. Never require a fixed phrase or ask the user to type a magic word. Only after approval, re-call with dryRun:false to actually spend."}, 'pairId': {'type': 'string', 'description': 'Motion pair id (from get_asset).'}, 'assetId': {'type': 'string', 'description': 'Asset id or slug.'}, 'videoModel': {'type': 'string', 'description': 'Override the video model.'}, 'motionPrompt': {'type': 'string', 'description': 'Replacement motion prompt for this take.'}, 'idempotencyKey': {'type': 'string', 'minLength': 1, 'description': 'Optional Idempotency-Key for the real (dryRun:false) call. Omit and one is minted per call. Reuse the SAME value when retrying a call that failed with ENTITY_BUSY / 402 / 429 so the retry cannot double-dispatch.'}, 'durationSeconds': {'type': 'number', 'maximum': 10, 'minimum': 2, 'description': "Informs the cost estimate only — the dispatched job uses the pair's own duration."}}, 'additionalProperties': False}
rematte_animation
Fix an animation's edge artifacts (re-matte)
FREE, no AI. Try a cleaner background removal on ONE animation's source video — the repair for a quality read showing deliveredIssues containing "matte" (green fringe, flickering holes, ragged edges). The cleaner version is kept ONLY if it measures better, so this can never make the animation worse; the motion itself is unchanged. One attempt per capture: if the same frames were already tried (matteRepair stamp), a repeat call is a cheap re-check + free re-render — regenerate the animation for a fresh take instead. Fails with SOURCE_VIDEO_EXPIRED when the source video aged past its 30-day retention. Returns { jobId } — poll get_job, then re-read the character's quality block: "matte" gone = the cleaner version shipped.
Acceso externo
Esquema de entrada
{'type': 'object', 'required': ['characterId', 'animation'], 'properties': {'animation': {'type': 'string', 'description': 'Animation slug to re-matte in place.'}, 'characterId': {'type': 'string', 'description': 'Character id.'}}, 'additionalProperties': False}
rename_ui_component
Rename UI component
Rename an owned component for free. Supply its current name as expectedName to reject stale edits. Preserves IDs, artwork and historical revisions; re-sync updates its exported display name.
Acceso externo
Esquema de entrada
{'type': 'object', 'required': ['packId', 'componentId', 'name', 'expectedName'], 'properties': {'name': {'type': 'string', 'maxLength': 120, 'minLength': 1}, 'packId': {'type': 'string', 'format': 'uuid', 'description': 'Owned UI Pack ID.'}, 'componentId': {'type': 'string', 'format': 'uuid', 'description': 'Owned component ID within this pack.'}, 'expectedName': {'type': 'string', 'maxLength': 120, 'minLength': 1}}, 'additionalProperties': False}
replace_ui_component_png
Replace edited UI PNG
Save a locally edited PNG, revalidate behavior metadata and preserve the prior revision. Free. Maximum PNG 4 MB and 2048 pixels per axis; no SVG artwork editing.
Acceso externo
Esquema de entrada
{'type': 'object', 'required': ['packId', 'componentId', 'revisionId', 'imageBase64'], 'properties': {'packId': {'type': 'string', 'format': 'uuid', 'description': 'Owned UI Pack ID.'}, 'revisionId': {'type': 'string', 'format': 'uuid'}, 'componentId': {'type': 'string', 'format': 'uuid', 'description': 'Owned component ID within this pack.'}, 'imageBase64': {'type': 'string', 'maxLength': 6000000, 'minLength': 1}}, 'additionalProperties': False}
reprocess_asset
Arrange, align, and fit collection items
FREE and SYNCHRONOUS (no jobId — do not poll), no AI. Rebuild a staged, tileset, or terrain collection's presentation layout: anchor chooses the shared fixed point and cellOffsets apply per-item nudges. Modern manifest revisions are recomposed from their independent item PNGs and are never re-sliced; legacy staged and tileset revisions retain the source-sheet re-cut path, where cellInset can remove separator bleed. For a manifest revision, fitItemIndices makes those items fill their shared cell as much as possible while preserving aspect ratio. Legacy terrain must be upgraded to independent items first. Omitted fields keep the revision's current values; send cellOffsets:[] or cellInset:0 to clear. Returns a grid summary; call get_asset afterwards for fresh presigned tile URLs.
Acceso externo
Esquema de entrada
{'type': 'object', 'required': ['assetId', 'iterationId'], 'properties': {'anchor': {'enum': ['top-left', 'top-middle', 'top-right', 'middle-left', 'center', 'middle-right', 'bottom-left', 'bottom-middle', 'bottom-right'], 'type': 'string', 'description': 'Where each sprite is placed inside its cell. "bottom-middle" is the default for sprites that stand on the ground.'}, 'assetId': {'type': 'string', 'description': 'Asset id or slug (staged, tileset, or manifest-backed terrain).'}, 'cellInset': {'type': 'integer', 'maximum': 32, 'minimum': 0, 'description': 'Legacy source sheets only: pixels shaved off every side of each cell to drop neighbouring bleed (0-32). Ignored for independent-item manifests. Pass 0 to clear.'}, 'cellOffsets': {'type': 'array', 'items': {'type': 'object', 'required': ['x', 'y'], 'properties': {'x': {'type': 'integer', 'description': 'Horizontal nudge in pixels.'}, 'y': {'type': 'integer', 'description': 'Vertical nudge in pixels.'}}, 'additionalProperties': False}, 'description': 'Per-cell pixel nudges, in tile-index order. Pass [] to clear all nudges.'}, 'iterationId': {'type': 'string', 'description': 'Collection revision (iteration) id to arrange.'}, 'fitItemIndices': {'type': 'array', 'items': {'type': 'integer', 'minimum': 0}, 'maxItems': 256, 'description': 'Independent-item manifests only: itemIndex values to fit to the shared cell while preserving aspect ratio. This is a one-shot operation; omitted items keep their saved size.'}}, 'additionalProperties': False}
restore_map_revision
Restore an earlier map revision
FREE. Restore a saved revision as a new revision, preserving history. Pass the latest expectedRevision and reuse requestId on retry.
Acceso externo
Esquema de entrada
{'type': 'object', 'required': ['mapId', 'revision', 'expectedRevision', 'requestId'], 'properties': {'mapId': {'type': 'string'}, 'revision': {'type': 'integer', 'minimum': 0}, 'requestId': {'type': 'string', 'maxLength': 128, 'minLength': 8}, 'expectedRevision': {'type': 'integer', 'minimum': 0}}, 'additionalProperties': False}
resume_pose
Resume saved pose background removal
FREE. Resume a failed pose when list_character_poses reports removalRecoveryAvailable. Reuses the saved image; never generates or charges for another image. Respect the retry-after time on cooldown errors, then poll list_character_poses.
Acceso externo
Esquema de entrada
{'type': 'object', 'required': ['characterId', 'poseId'], 'properties': {'poseId': {'type': 'string'}, 'characterId': {'type': 'string'}}, 'additionalProperties': False}
resume_ui_pack_batch
Resume saved UI artwork background removal
FREE. Resume background removal when a failed/uncertain illustrated batch reports removalRecoveryAvailable. Reuses its saved artwork and original billing identity. Respect cooldown errors; never create a replacement paid batch.
Acceso externo
Esquema de entrada
{'type': 'object', 'required': ['packId', 'batchId'], 'properties': {'packId': {'type': 'string', 'format': 'uuid', 'description': 'Owned UI Pack ID.'}, 'batchId': {'type': 'string', 'format': 'uuid'}}, 'additionalProperties': False}
retry_job
Retry a failed job
FREE when the original KIE task or a validated stored artifact can be recovered; otherwise PAID only for the sub-steps that still need to run. Re-runs the FAILED step of a job whose status is "error" — the prompt, model and every setting are already on the job, so this is the cheap way out of a failure instead of creating the whole thing again. Work that already succeeded is NOT redone or re-charged: a generation that failed after its image landed reuses the paid result. get_job reports retryMode, retryRecovery and retryCost, and the dryRun quote here is that same number. If get_job reports failureAction:"edit_input", do not use this tool; edit the prompt or references and create a new generation. A non-retryable phase answers 400 JOB_NOT_RETRYABLE — some late phases hold partially-committed state and deliberately have no blanket retry. Eligible overhead Material jobs use stored_artifact recovery to repair the original without new generation or background removal. A confirmed failed repair is not offered again by that processor; refresh get_job and honor server eligibility, even below the general two-attempt limit. No automatic refund is implied. Confirmed background-removal provider failures already fall back automatically on the server, without a new user charge. There is no daily removal retry lockout; honor reported cooldowns and unknown-task safeguards if recovery still fails. For already-authorized generation, automatically execute a zero-credit recovery quote and poll it; no renewed approval or refund. Never duplicate a running recovery. Limit automatic retries to two per failed job per session; stop on recurring failure or any paid quote. DEFAULTS TO A COST PREVIEW — see the dryRun argument. Returns { jobId } — poll get_job.
Acceso externo
Esquema de entrada
{'type': 'object', 'required': ['jobId'], 'properties': {'jobId': {'type': 'string', 'description': 'Id of a job whose status is "error" (from get_job).'}, 'dryRun': {'type': 'boolean', 'default': True, 'description': "DEFAULTS TO TRUE. While true this returns only a cost quote ({ estimatedCredits, balance, spendCapDaily, spentLast24h, capRemaining }) and executes nothing. Show the user estimatedCredits, then ask a normal confirmation question. Prefer the client's native question UI with Approve / Decline / Discuss choices when available; otherwise accept any unambiguous conversational approval. Never require a fixed phrase or ask the user to type a magic word. Only after approval, re-call with dryRun:false to actually spend."}, 'idempotencyKey': {'type': 'string', 'minLength': 1, 'description': 'Optional Idempotency-Key for the real (dryRun:false) call. Omit and one is minted per call. Reuse the SAME value when retrying a call that failed with ENTITY_BUSY / 402 / 429 so the retry cannot double-dispatch.'}}, 'additionalProperties': False}
retry_unusable_result
Retry an unusable AI result
Quality Retry is the subscription compensation for AI art that invents details, ignores the request, or arrives unusable, letting the user try again without asking support for a credit refund. Costs ONE quality retry and ZERO credits; it is not a refund and preserves the original. Use get_subscription_allowances first and proceed only when features.retry is true; explain the purpose/cost and obtain approval before confirmed=true. This is distinct from retry_job (technical recovery) and ordinary paid revision. Do not use for arbitrary new ideas or imported still images. Persist requestId and reuse it after network errors; a returned allowance requires a new requestId.
Acceso externo
Esquema de entrada
{'type': 'object', 'required': ['kind', 'entityId', 'reason', 'requestId'], 'properties': {'kind': {'enum': ['asset_image', 'asset_animation', 'character_image', 'character_animation', 'character_pose'], 'type': 'string', 'description': 'Use character_pose with poseId for a completed generated pose with saved inputs, creating a new pose on the same character. Extracted/mirrored poses are excluded. Use character_animation for ordinary character animations and completed standalone or automatic setup 360 video turns. Setup requires a completed owned job with an approved review and retained padded input. Turn retries create a new standalone turn without replacing approved poses or rerunning dependent animations. Grid-sheet rotations and unidentifiable sources are excluded.'}, 'poseId': {'type': 'string'}, 'reason': {'enum': ['hallucinated', 'unusable', 'other'], 'type': 'string'}, 'entityId': {'type': 'string'}, 'confirmed': {'type': 'boolean', 'description': 'True only after the user approved using one quality retry.'}, 'requestId': {'type': 'string', 'format': 'uuid'}, 'revisionId': {'type': 'string'}, 'animationId': {'type': 'string'}, 'issueDetails': {'type': 'string', 'maxLength': 1000, 'minLength': 1, 'description': 'Required for reason=other. Describe the unusable result in up to 1000 characters; stored for support, not sent to AI or used to change the original prompt. Preserve on requestId replay.'}}, 'additionalProperties': False}
revise_asset
Revise an asset
PAID. Generate a new revision of an asset from feedback text. The previous revision is kept — revisions are additive, never destructive. Environment Kit (`terrain`) assets also accept the legacy templateId to pull a whole category pack (edges / grounds / props / slopes / textures / structures). Passing sourceItemIndex uses that extracted item as the visual source for a complete new related collection: the source stays untouched and every output is a separate new asset listed in get_job.assetIds. The default dry run returns the exact semantic revision plan and planToken; show the preview to the user, then resend the unchanged request with that token. DEFAULTS TO A PLAN + COST PREVIEW — see dryRun. Returns { jobId } — poll get_job.
Acceso externo
Esquema de entrada
{'type': 'object', 'required': ['assetId'], 'properties': {'dryRun': {'type': 'boolean', 'default': True, 'description': "DEFAULTS TO TRUE. While true this returns only a cost quote ({ estimatedCredits, balance, spendCapDaily, spentLast24h, capRemaining }) and executes nothing. Show the user estimatedCredits, then ask a normal confirmation question. Prefer the client's native question UI with Approve / Decline / Discuss choices when available; otherwise accept any unambiguous conversational approval. Never require a fixed phrase or ask the user to type a magic word. Only after approval, re-call with dryRun:false to actually spend."}, 'prompt': {'type': 'string', 'maxLength': 20000, 'description': 'What to change. Required unless templateId is given (terrain).'}, 'assetId': {'type': 'string', 'description': 'Asset id or slug.'}, 'planToken': {'type': 'string', 'description': 'REQUIRED when dryRun=false. Copy unchanged from the immediately preceding dry-run response.'}, 'imageModel': {'type': 'string', 'description': 'Override the image model.'}, 'templateId': {'enum': ['edges', 'grounds', 'props', 'slopes', 'textures', 'structures'], 'type': 'string', 'description': 'Environment Kit (`terrain`) only — legacy focused category pack, not a dashboard prompt-starter ID.'}, 'textureKind': {'enum': ['fill', 'strip'], 'type': 'string', 'description': "Texture only — 4-way seamless fill, or a directional left-right strip. Defaults to the asset's existing kind."}, 'idempotencyKey': {'type': 'string', 'minLength': 1, 'description': 'Optional Idempotency-Key for the real (dryRun:false) call. Omit and one is minted per call. Reuse the SAME value when retrying a call that failed with ENTITY_BUSY / 402 / 429 so the retry cannot double-dispatch.'}, 'sourceItemIndex': {'type': 'integer', 'minimum': 0, 'description': 'Collection item to seed a related collection. Preserves the source and creates one new asset per output.'}, 'sourceIterationId': {'type': 'string', 'description': 'Revise from a specific earlier revision instead of the current one.'}}, 'additionalProperties': False}
revise_ui_pack_png
Revise UI Pack PNG
Get a cost preview for a 100-credit selected PNG revision, then pass its signed quote to execute. SVG artwork editing is Phase 2; it is not enabled by this tool. Siblings and prior revisions remain available.
Acceso externo
Esquema de entrada
{'type': 'object', 'required': ['packId', 'componentId'], 'properties': {'quote': {'type': 'object', 'description': 'Unmodified signed quote returned by the dry-run. Required when dryRun is false.', 'additionalProperties': {}}, 'dryRun': {'type': 'boolean', 'default': True, 'description': 'Show the user estimatedCredits and ask whether to proceed, unless already authorized in this session. Prefer the client native question UI with Approve / Decline / Discuss choices; otherwise accept any unambiguous conversational approval. Never require a fixed phrase or magic word. Then set false and supply the returned quote.'}, 'packId': {'type': 'string', 'format': 'uuid', 'description': 'Owned UI Pack ID.'}, 'request': {'type': 'object', 'required': ['requestId', 'revisionId', 'prompt'], 'properties': {'prompt': {'type': 'string', 'maxLength': 2000, 'minLength': 1}, 'requestId': {'type': 'string', 'maxLength': 128, 'minLength': 8}, 'revisionId': {'type': 'string', 'format': 'uuid'}, 'referenceImageBase64': {'type': 'string', 'maxLength': 6000000}}, 'additionalProperties': False}, 'componentId': {'type': 'string', 'format': 'uuid', 'description': 'Owned component ID within this pack.'}, 'idempotencyKey': {'type': 'string', 'maxLength': 128, 'minLength': 8, 'description': 'Reuse the same key when retrying a confirmed request.'}}, 'additionalProperties': False}
run_map_playtest
Run a map movement test
FREE bounded browser-free route/clearance or deterministic controller replay. Choose exactly one saved mapId or prepared draftId. Returns map hash, declared body/profile, trace, events, diagnostics and limitations. A passed movement test is not proof of combat, scripts or destination-engine gameplay. Save reusable scenarios in document.playtests; inspect canonical images separately.
Solo lectura Acceso externo Idempotente
Esquema de entrada
{'type': 'object', 'required': ['scenario'], 'properties': {'mapId': {'type': 'string'}, 'draftId': {'type': 'string', 'format': 'uuid'}, 'scenario': {'anyOf': [{'type': 'object', 'required': ['id', 'name', 'kind', 'start', 'goal', 'body', 'expected'], 'properties': {'id': {'type': 'string', 'maxLength': 128, 'minLength': 1}, 'body': {'type': 'object', 'required': ['width', 'height'], 'properties': {'width': {'type': 'number', 'maximum': 16384, 'exclusiveMinimum': 0}, 'height': {'type': 'number', 'maximum': 16384, 'exclusiveMinimum': 0}}, 'additionalProperties': False}, 'goal': {'type': 'object', 'required': ['x', 'y'], 'properties': {'x': {'type': 'number', 'maximum': 1000000, 'minimum': -1000000}, 'y': {'type': 'number', 'maximum': 1000000, 'minimum': -1000000}, 'surfaceId': {'type': 'string', 'maxLength': 128, 'minLength': 1}}, 'additionalProperties': False}, 'kind': {'type': 'string', 'const': 'route'}, 'name': {'type': 'string', 'maxLength': 160, 'minLength': 1}, 'start': {'type': 'object', 'required': ['x', 'y'], 'properties': {'x': {'type': 'number', 'maximum': 1000000, 'minimum': -1000000}, 'y': {'type': 'number', 'maximum': 1000000, 'minimum': -1000000}, 'surfaceId': {'type': 'string', 'maxLength': 128, 'minLength': 1}}, 'additionalProperties': False}, 'cellSize': {'type': 'number', 'maximum': 128, 'minimum': 1}, 'expected': {'enum': ['reachable', 'blocked'], 'type': 'string'}, 'maxNodes': {'type': 'integer', 'maximum': 12000, 'minimum': 1}}, 'additionalProperties': False}, {'type': 'object', 'required': ['id', 'name', 'start', 'steps', 'hz', 'expect', 'kind', 'body'], 'properties': {'hz': {'enum': [30, 60, 120], 'type': 'number'}, 'id': {'type': 'string', 'maxLength': 128, 'minLength': 1}, 'body': {'type': 'object', 'required': ['radius', 'halfHeight'], 'properties': {'radius': {'type': 'number', 'maximum': 8192, 'exclusiveMinimum': 0}, 'halfHeight': {'type': 'number', 'maximum': 8192, 'exclusiveMinimum': 0}}, 'additionalProperties': False}, 'kind': {'type': 'string', 'const': 'surface-runner'}, 'name': {'type': 'string', 'maxLength': 160, 'minLength': 1}, 'start': {'type': 'object', 'required': ['x', 'y'], 'properties': {'x': {'type': 'number', 'maximum': 1000000, 'minimum': -1000000}, 'y': {'type': 'number', 'maximum': 1000000, 'minimum': -1000000}}, 'additionalProperties': False}, 'steps': {'type': 'array', 'items': {'type': 'object', 'required': ['frames', 'axis'], 'properties': {'axis': {'type': 'number', 'maximum': 1, 'minimum': -1}, 'jump': {'type': 'boolean'}, 'frames': {'type': 'integer', 'maximum': 3600, 'minimum': 1}, 'interact': {'type': 'boolean'}}, 'additionalProperties': False}, 'maxItems': 128, 'minItems': 1}, 'expect': {'type': 'object', 'properties': {'events': {'type': 'array', 'items': {'enum': ['land', 'jump', 'detach', 'connect', 'blocked', 'checkpoint', 'respawn', 'door', 'motion', 'custom'], 'type': 'string'}, 'maxItems': 10, 'minItems': 1}, 'region': {'type': 'object', 'required': ['x', 'y', 'width', 'height'], 'properties': {'x': {'type': 'number', 'maximum': 1000000, 'minimum': -1000000}, 'y': {'type': 'number', 'maximum': 1000000, 'minimum': -1000000}, 'width': {'type': 'number', 'maximum': 16384, 'exclusiveMinimum': 0}, 'height': {'type': 'number', 'maximum': 16384, 'exclusiveMinimum': 0}}, 'additionalProperties': False}, 'supportPathId': {'type': 'string', 'maxLength': 128, 'minLength': 1}}, 'additionalProperties': False}}, 'additionalProperties': False}, {'type': 'object', 'required': ['id', 'name', 'start', 'steps', 'hz', 'expect', 'kind', 'body', 'profile'], 'properties': {'hz': {'enum': [30, 60, 120], 'type': 'number'}, 'id': {'type': 'string', 'maxLength': 128, 'minLength': 1}, 'body': {'type': 'object', 'required': ['width', 'height'], 'properties': {'width': {'type': 'number', 'maximum': 16384, 'exclusiveMinimum': 0}, 'height': {'type': 'number', 'maximum': 16384, 'exclusiveMinimum': 0}}, 'additionalProperties': False}, 'kind': {'type': 'string', 'const': 'platformer'}, 'name': {'type': 'string', 'maxLength': 160, 'minLength': 1}, 'start': {'type': 'object', 'required': ['x', 'y'], 'properties': {'x': {'type': 'number', 'maximum': 1000000, 'minimum': -1000000}, 'y': {'type': 'number', 'maximum': 1000000, 'minimum': -1000000}}, 'additionalProperties': False}, 'steps': {'type': 'array', 'items': {'type': 'object', 'required': ['frames', 'axis'], 'properties': {'axis': {'type': 'number', 'maximum': 1, 'minimum': -1}, 'jump': {'type': 'boolean'}, 'frames': {'type': 'integer', 'maximum': 3600, 'minimum': 1}, 'interact': {'type': 'boolean'}}, 'additionalProperties': False}, 'maxItems': 128, 'minItems': 1}, 'expect': {'type': 'object', 'properties': {'events': {'type': 'array', 'items': {'enum': ['land', 'jump', 'detach', 'connect', 'blocked', 'checkpoint', 'respawn', 'door', 'motion', 'custom'], 'type': 'string'}, 'maxItems': 10, 'minItems': 1}, 'region': {'type': 'object', 'required': ['x', 'y', 'width', 'height'], 'properties': {'x': {'type': 'number', 'maximum': 1000000, 'minimum': -1000000}, 'y': {'type': 'number', 'maximum': 1000000, 'minimum': -1000000}, 'width': {'type': 'number', 'maximum': 16384, 'exclusiveMinimum': 0}, 'height': {'type': 'number', 'maximum': 16384, 'exclusiveMinimum': 0}}, 'additionalProperties': False}, 'supportPathId': {'type': 'string', 'maxLength': 128, 'minLength': 1}}, 'additionalProperties': False}, 'profile': {'type': 'object', 'required': ['speed', 'gravity', 'jumpSpeed'], 'properties': {'speed': {'type': 'number', 'maximum': 10000, 'exclusiveMinimum': 0}, 'gravity': {'type': 'number', 'maximum': 10000, 'exclusiveMinimum': 0}, 'airJumps': {'type': 'integer', 'maximum': 4, 'minimum': 0}, 'jumpSpeed': {'type': 'number', 'maximum': 10000, 'exclusiveMinimum': 0}}, 'additionalProperties': False}}, 'additionalProperties': False}]}}, 'additionalProperties': False}
save_project_style_guide
Save project style guide
Adopt a new immutable guide revision with optimistic concurrency. Colors, typography and camera apply to future generation, never silently rewrite prior assets.
Acceso externo
Esquema de entrada
{'type': 'object', 'required': ['projectId', 'expectedRevision', 'guide'], 'properties': {'guide': {'type': 'object', 'additionalProperties': {}}, 'projectId': {'type': 'string'}, 'expectedRevision': {'type': 'integer', 'minimum': 0}}, 'additionalProperties': False}
save_ui_component_defaults
Save UI component defaults
Save supported fill, text and layout values for an exact current revision. Free and deterministic; cannot manufacture unsupported capabilities or edit arbitrary SVG geometry.
Acceso externo
Esquema de entrada
{'type': 'object', 'required': ['packId', 'componentId', 'revisionId', 'configuration'], 'properties': {'packId': {'type': 'string', 'format': 'uuid', 'description': 'Owned UI Pack ID.'}, 'revisionId': {'type': 'string', 'format': 'uuid'}, 'componentId': {'type': 'string', 'format': 'uuid', 'description': 'Owned component ID within this pack.'}, 'configuration': {'type': 'object', 'additionalProperties': {}}}, 'additionalProperties': False}
save_ui_pack_style
Save UI Pack style
Save a pack-specific style for future quotes using the current pack updatedAt. Free; preserves project defaults and existing component revisions. A stale timestamp is rejected.
Acceso externo
Esquema de entrada
{'type': 'object', 'required': ['packId', 'styleGuide', 'expectedUpdatedAt'], 'properties': {'packId': {'type': 'string', 'format': 'uuid', 'description': 'Owned UI Pack ID.'}, 'styleGuide': {'type': 'object', 'additionalProperties': {}}, 'expectedUpdatedAt': {'type': 'string', 'format': 'date-time'}}, 'additionalProperties': False}
select_frames
Select animation frames
FREE, no AI. Curate which frames an animation keeps, by index into the full capture, in order. Pass an empty array to reset to all frames. Non-destructive: the full capture is retained, so you can re-select at any time. Use get_frames with format:"sheet" first to choose indices. Returns a jobId — poll get_job.
Acceso externo
Esquema de entrada
{'type': 'object', 'required': ['target', 'entityId', 'frames'], 'properties': {'frames': {'type': 'array', 'items': {'type': 'integer', 'minimum': 0}, 'description': 'Ordered frame indices to keep. Empty array resets to the full capture.'}, 'pairId': {'type': 'string', 'description': 'Motion pair id — required when target=assetPair.'}, 'target': {'enum': ['character', 'assetPair'], 'type': 'string', 'description': 'A character animation, or an asset motion pair.'}, 'entityId': {'type': 'string', 'description': 'Character id (target=character) or asset id/slug (target=assetPair).'}, 'animation': {'type': 'string', 'description': 'Animation slug — required when target=character.'}, 'compositing': {'type': 'object', 'required': ['scale', 'offsetX', 'offsetY'], 'properties': {'scale': {'type': 'number'}, 'offsetX': {'type': 'number'}, 'offsetY': {'type': 'number'}}, 'description': 'Characters only — apply scale/offset in the same rebuild.', 'additionalProperties': False}}, 'additionalProperties': False}
set_asset_collision_body
Set an asset's collision body
FREE and SYNCHRONOUS (no jobId — do not poll). Author the PHYSICS shape a game should build its collider from for an asset revision: rect, circle, polygon, compound of 1..16 simple disconnected bodies, or none, in NORMALIZED coordinates (0..1 fractions of the sprite/tile cell, origin top-left; a circle radius is a fraction of WIDTH). Set tileIndex to give one tile of a tileset/staged asset its own shape — it overrides the asset-level default for that tile. Pass collisionBody: null to clear/inherit, or {kind:"none"} to explicitly disable collision including bbox fallback. Compound children use the same cell space; preserve open archways between them. This is what stops a game from falling back to the sprite bounding box. The shape flows into every map and asset export made AFTER this edit — Tiled per-tile objectgroups, the Tiled map Collision layer, and the Phaser/Godot/Unity/GameMaker colliders — and it is resolved from the asset at export time, so it applies to tiles that were already placed on a map before you set it. Distinct from the FOOTPRINT, which is only the level editor's snap/tessellation shape and has no physics meaning.
Acceso externo
Esquema de entrada
{'type': 'object', 'required': ['assetId', 'iterationId', 'collisionBody'], 'properties': {'assetId': {'type': 'string', 'description': 'Asset id or slug.'}, 'tileIndex': {'type': 'integer', 'minimum': 0, 'description': 'Target one collection tile (tileset/staged/terrain). Coordinates are normalized to its padded presentation cell, not the cropped item image. Omit for the asset-level default.'}, 'iterationId': {'type': 'string', 'description': 'Revision (iteration) id to stamp.'}, 'collisionBody': {'anyOf': [{'anyOf': [{'anyOf': [{'type': 'object', 'required': ['kind', 'cx', 'cy', 'hw', 'hh'], 'properties': {'cx': {'type': 'number', 'maximum': 1, 'minimum': 0}, 'cy': {'type': 'number', 'maximum': 1, 'minimum': 0}, 'hh': {'type': 'number', 'exclusiveMinimum': 0}, 'hw': {'type': 'number', 'exclusiveMinimum': 0}, 'rot': {'type': 'number'}, 'kind': {'type': 'string', 'const': 'rect'}}, 'additionalProperties': False}, {'type': 'object', 'required': ['kind', 'cx', 'cy', 'r'], 'properties': {'r': {'type': 'number', 'exclusiveMinimum': 0}, 'cx': {'type': 'number', 'maximum': 1, 'minimum': 0}, 'cy': {'type': 'number', 'maximum': 1, 'minimum': 0}, 'kind': {'type': 'string', 'const': 'circle'}}, 'additionalProperties': False}, {'type': 'object', 'required': ['kind', 'points'], 'properties': {'rot': {'type': 'number'}, 'kind': {'type': 'string', 'const': 'polygon'}, 'points': {'type': 'array', 'items': {'type': 'object', 'required': ['x', 'y'], 'properties': {'x': {'type': 'number', 'maximum': 1, 'minimum': 0}, 'y': {'type': 'number', 'maximum': 1, 'minimum': 0}}, 'additionalProperties': False}, 'maxItems': 64, 'minItems': 3}}, 'additionalProperties': False}]}, {'type': 'object', 'required': ['kind', 'bodies'], 'properties': {'kind': {'type': 'string', 'const': 'compound'}, 'bodies': {'type': 'array', 'items': {'anyOf': [{'type': 'object', 'required': ['kind', 'cx', 'cy', 'hw', 'hh'], 'properties': {'cx': {'type': 'number', 'maximum': 1, 'minimum': 0}, 'cy': {'type': 'number', 'maximum': 1, 'minimum': 0}, 'hh': {'type': 'number', 'exclusiveMinimum': 0}, 'hw': {'type': 'number', 'exclusiveMinimum': 0}, 'rot': {'type': 'number'}, 'kind': {'type': 'string', 'const': 'rect'}}, 'additionalProperties': False}, {'type': 'object', 'required': ['kind', 'cx', 'cy', 'r'], 'properties': {'r': {'type': 'number', 'exclusiveMinimum': 0}, 'cx': {'type': 'number', 'maximum': 1, 'minimum': 0}, 'cy': {'type': 'number', 'maximum': 1, 'minimum': 0}, 'kind': {'type': 'string', 'const': 'circle'}}, 'additionalProperties': False}, {'type': 'object', 'required': ['kind', 'points'], 'properties': {'rot': {'type': 'number'}, 'kind': {'type': 'string', 'const': 'polygon'}, 'points': {'type': 'array', 'items': {'type': 'object', 'required': ['x', 'y'], 'properties': {'x': {'type': 'number', 'maximum': 1, 'minimum': 0}, 'y': {'type': 'number', 'maximum': 1, 'minimum': 0}}, 'additionalProperties': False}, 'maxItems': 64, 'minItems': 3}}, 'additionalProperties': False}]}, 'maxItems': 16, 'minItems': 1}}, 'additionalProperties': False}, {'type': 'object', 'required': ['kind'], 'properties': {'kind': {'type': 'string', 'const': 'none'}}, 'additionalProperties': False}], 'description': 'Reusable asset collider. All child coordinates are fractions of the same sprite/cell; circle radius is a fraction of width. Compound children are separate solids, not a filled bounding box. None explicitly disables collision; null/omission follows endpoint inheritance rules.'}, {'type': 'null'}], 'description': 'Normalized asset shape, compound of 1..16 simple shapes, explicit none for passable scenery, or null to clear/inherit.'}}, 'additionalProperties': False}
set_asset_collision_roles
Set asset movement, hurtbox and hitbox roles
FREE, synchronous metadata edit for an owned revision or collection tileIndex. Each independent role accepts a normalized simple body, disconnected compound, or none. Coordinates refer to the full sprite or padded collection cell; radius is a fraction of width. Omitted roles stay unchanged, null clears an override, none disables. Tile roles override asset roles independently. hitboxFrames is not supported on assets. Legacy collisionBody remains the movement/hurtbox fallback; hitbox requires explicit configuration. No paid job.
Acceso externo
Esquema de entrada
{'type': 'object', 'required': ['assetId', 'iterationId', 'collisionRoles'], 'properties': {'assetId': {'type': 'string'}, 'tileIndex': {'type': 'integer', 'minimum': 0}, 'iterationId': {'type': 'string'}, 'collisionRoles': {'anyOf': [{'type': 'object', 'properties': {'hitbox': {'anyOf': [{'anyOf': [{'anyOf': [{'type': 'object', 'required': ['kind', 'cx', 'cy', 'hw', 'hh'], 'properties': {'cx': {'type': 'number', 'maximum': 1, 'minimum': 0}, 'cy': {'type': 'number', 'maximum': 1, 'minimum': 0}, 'hh': {'type': 'number', 'exclusiveMinimum': 0}, 'hw': {'type': 'number', 'exclusiveMinimum': 0}, 'rot': {'type': 'number'}, 'kind': {'type': 'string', 'const': 'rect'}}, 'additionalProperties': False}, {'type': 'object', 'required': ['kind', 'cx', 'cy', 'r'], 'properties': {'r': {'type': 'number', 'exclusiveMinimum': 0}, 'cx': {'type': 'number', 'maximum': 1, 'minimum': 0}, 'cy': {'type': 'number', 'maximum': 1, 'minimum': 0}, 'kind': {'type': 'string', 'const': 'circle'}}, 'additionalProperties': False}, {'type': 'object', 'required': ['kind', 'points'], 'properties': {'rot': {'type': 'number'}, 'kind': {'type': 'string', 'const': 'polygon'}, 'points': {'type': 'array', 'items': {'type': 'object', 'required': ['x', 'y'], 'properties': {'x': {'type': 'number', 'maximum': 1, 'minimum': 0}, 'y': {'type': 'number', 'maximum': 1, 'minimum': 0}}, 'additionalProperties': False}, 'maxItems': 64, 'minItems': 3}}, 'additionalProperties': False}]}, {'type': 'object', 'required': ['kind', 'bodies'], 'properties': {'kind': {'type': 'string', 'const': 'compound'}, 'bodies': {'type': 'array', 'items': {'anyOf': [{'type': 'object', 'required': ['kind', 'cx', 'cy', 'hw', 'hh'], 'properties': {'cx': {'type': 'number', 'maximum': 1, 'minimum': 0}, 'cy': {'type': 'number', 'maximum': 1, 'minimum': 0}, 'hh': {'type': 'number', 'exclusiveMinimum': 0}, 'hw': {'type': 'number', 'exclusiveMinimum': 0}, 'rot': {'type': 'number'}, 'kind': {'type': 'string', 'const': 'rect'}}, 'additionalProperties': False}, {'type': 'object', 'required': ['kind', 'cx', 'cy', 'r'], 'properties': {'r': {'type': 'number', 'exclusiveMinimum': 0}, 'cx': {'type': 'number', 'maximum': 1, 'minimum': 0}, 'cy': {'type': 'number', 'maximum': 1, 'minimum': 0}, 'kind': {'type': 'string', 'const': 'circle'}}, 'additionalProperties': False}, {'type': 'object', 'required': ['kind', 'points'], 'properties': {'rot': {'type': 'number'}, 'kind': {'type': 'string', 'const': 'polygon'}, 'points': {'type': 'array', 'items': {'type': 'object', 'required': ['x', 'y'], 'properties': {'x': {'type': 'number', 'maximum': 1, 'minimum': 0}, 'y': {'type': 'number', 'maximum': 1, 'minimum': 0}}, 'additionalProperties': False}, 'maxItems': 64, 'minItems': 3}}, 'additionalProperties': False}]}, 'maxItems': 16, 'minItems': 1}}, 'additionalProperties': False}, {'type': 'object', 'required': ['kind'], 'properties': {'kind': {'type': 'string', 'const': 'none'}}, 'additionalProperties': False}], 'description': 'Reusable asset collider. All child coordinates are fractions of the same sprite/cell; circle radius is a fraction of width. Compound children are separate solids, not a filled bounding box. None explicitly disables collision; null/omission follows endpoint inheritance rules.'}, {'type': 'null'}], 'description': 'Reusable asset collider. All child coordinates are fractions of the same sprite/cell; circle radius is a fraction of width. Compound children are separate solids, not a filled bounding box. None explicitly disables collision; null/omission follows endpoint inheritance rules.'}, 'hurtbox': {'anyOf': [{'anyOf': [{'anyOf': [{'type': 'object', 'required': ['kind', 'cx', 'cy', 'hw', 'hh'], 'properties': {'cx': {'type': 'number', 'maximum': 1, 'minimum': 0}, 'cy': {'type': 'number', 'maximum': 1, 'minimum': 0}, 'hh': {'type': 'number', 'exclusiveMinimum': 0}, 'hw': {'type': 'number', 'exclusiveMinimum': 0}, 'rot': {'type': 'number'}, 'kind': {'type': 'string', 'const': 'rect'}}, 'additionalProperties': False}, {'type': 'object', 'required': ['kind', 'cx', 'cy', 'r'], 'properties': {'r': {'type': 'number', 'exclusiveMinimum': 0}, 'cx': {'type': 'number', 'maximum': 1, 'minimum': 0}, 'cy': {'type': 'number', 'maximum': 1, 'minimum': 0}, 'kind': {'type': 'string', 'const': 'circle'}}, 'additionalProperties': False}, {'type': 'object', 'required': ['kind', 'points'], 'properties': {'rot': {'type': 'number'}, 'kind': {'type': 'string', 'const': 'polygon'}, 'points': {'type': 'array', 'items': {'type': 'object', 'required': ['x', 'y'], 'properties': {'x': {'type': 'number', 'maximum': 1, 'minimum': 0}, 'y': {'type': 'number', 'maximum': 1, 'minimum': 0}}, 'additionalProperties': False}, 'maxItems': 64, 'minItems': 3}}, 'additionalProperties': False}]}, {'type': 'object', 'required': ['kind', 'bodies'], 'properties': {'kind': {'type': 'string', 'const': 'compound'}, 'bodies': {'type': 'array', 'items': {'anyOf': [{'type': 'object', 'required': ['kind', 'cx', 'cy', 'hw', 'hh'], 'properties': {'cx': {'type': 'number', 'maximum': 1, 'minimum': 0}, 'cy': {'type': 'number', 'maximum': 1, 'minimum': 0}, 'hh': {'type': 'number', 'exclusiveMinimum': 0}, 'hw': {'type': 'number', 'exclusiveMinimum': 0}, 'rot': {'type': 'number'}, 'kind': {'type': 'string', 'const': 'rect'}}, 'additionalProperties': False}, {'type': 'object', 'required': ['kind', 'cx', 'cy', 'r'], 'properties': {'r': {'type': 'number', 'exclusiveMinimum': 0}, 'cx': {'type': 'number', 'maximum': 1, 'minimum': 0}, 'cy': {'type': 'number', 'maximum': 1, 'minimum': 0}, 'kind': {'type': 'string', 'const': 'circle'}}, 'additionalProperties': False}, {'type': 'object', 'required': ['kind', 'points'], 'properties': {'rot': {'type': 'number'}, 'kind': {'type': 'string', 'const': 'polygon'}, 'points': {'type': 'array', 'items': {'type': 'object', 'required': ['x', 'y'], 'properties': {'x': {'type': 'number', 'maximum': 1, 'minimum': 0}, 'y': {'type': 'number', 'maximum': 1, 'minimum': 0}}, 'additionalProperties': False}, 'maxItems': 64, 'minItems': 3}}, 'additionalProperties': False}]}, 'maxItems': 16, 'minItems': 1}}, 'additionalProperties': False}, {'type': 'object', 'required': ['kind'], 'properties': {'kind': {'type': 'string', 'const': 'none'}}, 'additionalProperties': False}], 'description': 'Reusable asset collider. All child coordinates are fractions of the same sprite/cell; circle radius is a fraction of width. Compound children are separate solids, not a filled bounding box. None explicitly disables collision; null/omission follows endpoint inheritance rules.'}, {'type': 'null'}], 'description': 'Reusable asset collider. All child coordinates are fractions of the same sprite/cell; circle radius is a fraction of width. Compound children are separate solids, not a filled bounding box. None explicitly disables collision; null/omission follows endpoint inheritance rules.'}, 'movement': {'anyOf': [{'anyOf': [{'anyOf': [{'type': 'object', 'required': ['kind', 'cx', 'cy', 'hw', 'hh'], 'properties': {'cx': {'type': 'number', 'maximum': 1, 'minimum': 0}, 'cy': {'type': 'number', 'maximum': 1, 'minimum': 0}, 'hh': {'type': 'number', 'exclusiveMinimum': 0}, 'hw': {'type': 'number', 'exclusiveMinimum': 0}, 'rot': {'type': 'number'}, 'kind': {'type': 'string', 'const': 'rect'}}, 'additionalProperties': False}, {'type': 'object', 'required': ['kind', 'cx', 'cy', 'r'], 'properties': {'r': {'type': 'number', 'exclusiveMinimum': 0}, 'cx': {'type': 'number', 'maximum': 1, 'minimum': 0}, 'cy': {'type': 'number', 'maximum': 1, 'minimum': 0}, 'kind': {'type': 'string', 'const': 'circle'}}, 'additionalProperties': False}, {'type': 'object', 'required': ['kind', 'points'], 'properties': {'rot': {'type': 'number'}, 'kind': {'type': 'string', 'const': 'polygon'}, 'points': {'type': 'array', 'items': {'type': 'object', 'required': ['x', 'y'], 'properties': {'x': {'type': 'number', 'maximum': 1, 'minimum': 0}, 'y': {'type': 'number', 'maximum': 1, 'minimum': 0}}, 'additionalProperties': False}, 'maxItems': 64, 'minItems': 3}}, 'additionalProperties': False}]}, {'type': 'object', 'required': ['kind', 'bodies'], 'properties': {'kind': {'type': 'string', 'const': 'compound'}, 'bodies': {'type': 'array', 'items': {'anyOf': [{'type': 'object', 'required': ['kind', 'cx', 'cy', 'hw', 'hh'], 'properties': {'cx': {'type': 'number', 'maximum': 1, 'minimum': 0}, 'cy': {'type': 'number', 'maximum': 1, 'minimum': 0}, 'hh': {'type': 'number', 'exclusiveMinimum': 0}, 'hw': {'type': 'number', 'exclusiveMinimum': 0}, 'rot': {'type': 'number'}, 'kind': {'type': 'string', 'const': 'rect'}}, 'additionalProperties': False}, {'type': 'object', 'required': ['kind', 'cx', 'cy', 'r'], 'properties': {'r': {'type': 'number', 'exclusiveMinimum': 0}, 'cx': {'type': 'number', 'maximum': 1, 'minimum': 0}, 'cy': {'type': 'number', 'maximum': 1, 'minimum': 0}, 'kind': {'type': 'string', 'const': 'circle'}}, 'additionalProperties': False}, {'type': 'object', 'required': ['kind', 'points'], 'properties': {'rot': {'type': 'number'}, 'kind': {'type': 'string', 'const': 'polygon'}, 'points': {'type': 'array', 'items': {'type': 'object', 'required': ['x', 'y'], 'properties': {'x': {'type': 'number', 'maximum': 1, 'minimum': 0}, 'y': {'type': 'number', 'maximum': 1, 'minimum': 0}}, 'additionalProperties': False}, 'maxItems': 64, 'minItems': 3}}, 'additionalProperties': False}]}, 'maxItems': 16, 'minItems': 1}}, 'additionalProperties': False}, {'type': 'object', 'required': ['kind'], 'properties': {'kind': {'type': 'string', 'const': 'none'}}, 'additionalProperties': False}], 'description': 'Reusable asset collider. All child coordinates are fractions of the same sprite/cell; circle radius is a fraction of width. Compound children are separate solids, not a filled bounding box. None explicitly disables collision; null/omission follows endpoint inheritance rules.'}, {'type': 'null'}], 'description': 'Reusable asset collider. All child coordinates are fractions of the same sprite/cell; circle radius is a fraction of width. Compound children are separate solids, not a filled bounding box. None explicitly disables collision; null/omission follows endpoint inheritance rules.'}}, 'additionalProperties': False}, {'type': 'null'}]}}, 'additionalProperties': False}
set_asset_runtime_intent
Set an asset's runtime render intent
FREE and SYNCHRONOUS (no jobId — do not poll). Declare how an asset revision should be rendered at runtime: plain_image, particle_emitter, deformable_strip, repeat_fill, nine_slice or shader_effect. path_follow is accepted only for backward compatibility; do not set it on new assets. Draw and configure motion per placement in the level editor instead. The intent and its config flow into every engine export made AFTER this edit. Set tileIndex to target one tile of a tileset/staged asset.
Acceso externo
Esquema de entrada
{'type': 'object', 'required': ['assetId', 'iterationId', 'runtimeUse'], 'properties': {'config': {'type': 'object', 'description': 'Intent-specific config. Validated and clamped server-side; unknown keys are dropped.', 'additionalProperties': {}}, 'assetId': {'type': 'string', 'description': 'Asset id or slug.'}, 'tileIndex': {'type': 'integer', 'minimum': 0, 'description': 'Target one tile (tileset/staged only).'}, 'runtimeUse': {'enum': ['plain_image', 'particle_emitter', 'deformable_strip', 'repeat_fill', 'nine_slice', 'shader_effect', 'path_follow'], 'type': 'string', 'description': 'The render intent. plain_image clears any previous intent. path_follow is legacy-only; new path motion is authored per placement in the level editor.'}, 'iterationId': {'type': 'string', 'description': 'Revision (iteration) id to stamp.'}}, 'additionalProperties': False}
set_character_collision_roles
Set character movement, hurtbox and hitbox roles
FREE, synchronous metadata edit. Independent normalized full-frame movement, hurtbox and hitbox bodies. Character movement permits a simple body or none; hurtbox/hitbox also permit compound. Omitted keys stay unchanged; null clears that scoped override; none explicitly disables a role. Scope defaults to character base; select one poseId or animation. Only animation scope accepts hitboxFrames (inclusive zero-based delivered indices, maximum 64 windows). Omitted windows mean the explicitly configured hitbox is active for the whole animation; [] disables it for all frames. A hurtbox never inherits the new movement shape. Legacy collisionBody fallback remains supported. No paid job or implicit combat/faction rules.
Acceso externo
Esquema de entrada
{'type': 'object', 'required': ['characterId', 'collisionRoles'], 'properties': {'poseId': {'type': 'string'}, 'animation': {'type': 'string'}, 'characterId': {'type': 'string'}, 'collisionRoles': {'anyOf': [{'type': 'object', 'properties': {'hitbox': {'anyOf': [{'anyOf': [{'anyOf': [{'type': 'object', 'required': ['kind', 'cx', 'cy', 'hw', 'hh'], 'properties': {'cx': {'type': 'number', 'maximum': 1, 'minimum': 0}, 'cy': {'type': 'number', 'maximum': 1, 'minimum': 0}, 'hh': {'type': 'number', 'exclusiveMinimum': 0}, 'hw': {'type': 'number', 'exclusiveMinimum': 0}, 'rot': {'type': 'number'}, 'kind': {'type': 'string', 'const': 'rect'}}, 'additionalProperties': False}, {'type': 'object', 'required': ['kind', 'cx', 'cy', 'r'], 'properties': {'r': {'type': 'number', 'exclusiveMinimum': 0}, 'cx': {'type': 'number', 'maximum': 1, 'minimum': 0}, 'cy': {'type': 'number', 'maximum': 1, 'minimum': 0}, 'kind': {'type': 'string', 'const': 'circle'}}, 'additionalProperties': False}, {'type': 'object', 'required': ['kind', 'points'], 'properties': {'rot': {'type': 'number'}, 'kind': {'type': 'string', 'const': 'polygon'}, 'points': {'type': 'array', 'items': {'type': 'object', 'required': ['x', 'y'], 'properties': {'x': {'type': 'number', 'maximum': 1, 'minimum': 0}, 'y': {'type': 'number', 'maximum': 1, 'minimum': 0}}, 'additionalProperties': False}, 'maxItems': 64, 'minItems': 3}}, 'additionalProperties': False}]}, {'type': 'object', 'required': ['kind', 'bodies'], 'properties': {'kind': {'type': 'string', 'const': 'compound'}, 'bodies': {'type': 'array', 'items': {'anyOf': [{'type': 'object', 'required': ['kind', 'cx', 'cy', 'hw', 'hh'], 'properties': {'cx': {'type': 'number', 'maximum': 1, 'minimum': 0}, 'cy': {'type': 'number', 'maximum': 1, 'minimum': 0}, 'hh': {'type': 'number', 'exclusiveMinimum': 0}, 'hw': {'type': 'number', 'exclusiveMinimum': 0}, 'rot': {'type': 'number'}, 'kind': {'type': 'string', 'const': 'rect'}}, 'additionalProperties': False}, {'type': 'object', 'required': ['kind', 'cx', 'cy', 'r'], 'properties': {'r': {'type': 'number', 'exclusiveMinimum': 0}, 'cx': {'type': 'number', 'maximum': 1, 'minimum': 0}, 'cy': {'type': 'number', 'maximum': 1, 'minimum': 0}, 'kind': {'type': 'string', 'const': 'circle'}}, 'additionalProperties': False}, {'type': 'object', 'required': ['kind', 'points'], 'properties': {'rot': {'type': 'number'}, 'kind': {'type': 'string', 'const': 'polygon'}, 'points': {'type': 'array', 'items': {'type': 'object', 'required': ['x', 'y'], 'properties': {'x': {'type': 'number', 'maximum': 1, 'minimum': 0}, 'y': {'type': 'number', 'maximum': 1, 'minimum': 0}}, 'additionalProperties': False}, 'maxItems': 64, 'minItems': 3}}, 'additionalProperties': False}]}, 'maxItems': 16, 'minItems': 1}}, 'additionalProperties': False}, {'type': 'object', 'required': ['kind'], 'properties': {'kind': {'type': 'string', 'const': 'none'}}, 'additionalProperties': False}], 'description': 'Reusable asset collider. All child coordinates are fractions of the same sprite/cell; circle radius is a fraction of width. Compound children are separate solids, not a filled bounding box. None explicitly disables collision; null/omission follows endpoint inheritance rules.'}, {'type': 'null'}], 'description': 'Reusable asset collider. All child coordinates are fractions of the same sprite/cell; circle radius is a fraction of width. Compound children are separate solids, not a filled bounding box. None explicitly disables collision; null/omission follows endpoint inheritance rules.'}, 'hurtbox': {'anyOf': [{'anyOf': [{'anyOf': [{'type': 'object', 'required': ['kind', 'cx', 'cy', 'hw', 'hh'], 'properties': {'cx': {'type': 'number', 'maximum': 1, 'minimum': 0}, 'cy': {'type': 'number', 'maximum': 1, 'minimum': 0}, 'hh': {'type': 'number', 'exclusiveMinimum': 0}, 'hw': {'type': 'number', 'exclusiveMinimum': 0}, 'rot': {'type': 'number'}, 'kind': {'type': 'string', 'const': 'rect'}}, 'additionalProperties': False}, {'type': 'object', 'required': ['kind', 'cx', 'cy', 'r'], 'properties': {'r': {'type': 'number', 'exclusiveMinimum': 0}, 'cx': {'type': 'number', 'maximum': 1, 'minimum': 0}, 'cy': {'type': 'number', 'maximum': 1, 'minimum': 0}, 'kind': {'type': 'string', 'const': 'circle'}}, 'additionalProperties': False}, {'type': 'object', 'required': ['kind', 'points'], 'properties': {'rot': {'type': 'number'}, 'kind': {'type': 'string', 'const': 'polygon'}, 'points': {'type': 'array', 'items': {'type': 'object', 'required': ['x', 'y'], 'properties': {'x': {'type': 'number', 'maximum': 1, 'minimum': 0}, 'y': {'type': 'number', 'maximum': 1, 'minimum': 0}}, 'additionalProperties': False}, 'maxItems': 64, 'minItems': 3}}, 'additionalProperties': False}]}, {'type': 'object', 'required': ['kind', 'bodies'], 'properties': {'kind': {'type': 'string', 'const': 'compound'}, 'bodies': {'type': 'array', 'items': {'anyOf': [{'type': 'object', 'required': ['kind', 'cx', 'cy', 'hw', 'hh'], 'properties': {'cx': {'type': 'number', 'maximum': 1, 'minimum': 0}, 'cy': {'type': 'number', 'maximum': 1, 'minimum': 0}, 'hh': {'type': 'number', 'exclusiveMinimum': 0}, 'hw': {'type': 'number', 'exclusiveMinimum': 0}, 'rot': {'type': 'number'}, 'kind': {'type': 'string', 'const': 'rect'}}, 'additionalProperties': False}, {'type': 'object', 'required': ['kind', 'cx', 'cy', 'r'], 'properties': {'r': {'type': 'number', 'exclusiveMinimum': 0}, 'cx': {'type': 'number', 'maximum': 1, 'minimum': 0}, 'cy': {'type': 'number', 'maximum': 1, 'minimum': 0}, 'kind': {'type': 'string', 'const': 'circle'}}, 'additionalProperties': False}, {'type': 'object', 'required': ['kind', 'points'], 'properties': {'rot': {'type': 'number'}, 'kind': {'type': 'string', 'const': 'polygon'}, 'points': {'type': 'array', 'items': {'type': 'object', 'required': ['x', 'y'], 'properties': {'x': {'type': 'number', 'maximum': 1, 'minimum': 0}, 'y': {'type': 'number', 'maximum': 1, 'minimum': 0}}, 'additionalProperties': False}, 'maxItems': 64, 'minItems': 3}}, 'additionalProperties': False}]}, 'maxItems': 16, 'minItems': 1}}, 'additionalProperties': False}, {'type': 'object', 'required': ['kind'], 'properties': {'kind': {'type': 'string', 'const': 'none'}}, 'additionalProperties': False}], 'description': 'Reusable asset collider. All child coordinates are fractions of the same sprite/cell; circle radius is a fraction of width. Compound children are separate solids, not a filled bounding box. None explicitly disables collision; null/omission follows endpoint inheritance rules.'}, {'type': 'null'}], 'description': 'Reusable asset collider. All child coordinates are fractions of the same sprite/cell; circle radius is a fraction of width. Compound children are separate solids, not a filled bounding box. None explicitly disables collision; null/omission follows endpoint inheritance rules.'}, 'movement': {'anyOf': [{'anyOf': [{'anyOf': [{'type': 'object', 'required': ['kind', 'cx', 'cy', 'hw', 'hh'], 'properties': {'cx': {'type': 'number', 'maximum': 1, 'minimum': 0}, 'cy': {'type': 'number', 'maximum': 1, 'minimum': 0}, 'hh': {'type': 'number', 'exclusiveMinimum': 0}, 'hw': {'type': 'number', 'exclusiveMinimum': 0}, 'rot': {'type': 'number'}, 'kind': {'type': 'string', 'const': 'rect'}}, 'additionalProperties': False}, {'type': 'object', 'required': ['kind', 'cx', 'cy', 'r'], 'properties': {'r': {'type': 'number', 'exclusiveMinimum': 0}, 'cx': {'type': 'number', 'maximum': 1, 'minimum': 0}, 'cy': {'type': 'number', 'maximum': 1, 'minimum': 0}, 'kind': {'type': 'string', 'const': 'circle'}}, 'additionalProperties': False}, {'type': 'object', 'required': ['kind', 'points'], 'properties': {'rot': {'type': 'number'}, 'kind': {'type': 'string', 'const': 'polygon'}, 'points': {'type': 'array', 'items': {'type': 'object', 'required': ['x', 'y'], 'properties': {'x': {'type': 'number', 'maximum': 1, 'minimum': 0}, 'y': {'type': 'number', 'maximum': 1, 'minimum': 0}}, 'additionalProperties': False}, 'maxItems': 64, 'minItems': 3}}, 'additionalProperties': False}]}, {'type': 'object', 'required': ['kind', 'bodies'], 'properties': {'kind': {'type': 'string', 'const': 'compound'}, 'bodies': {'type': 'array', 'items': {'anyOf': [{'type': 'object', 'required': ['kind', 'cx', 'cy', 'hw', 'hh'], 'properties': {'cx': {'type': 'number', 'maximum': 1, 'minimum': 0}, 'cy': {'type': 'number', 'maximum': 1, 'minimum': 0}, 'hh': {'type': 'number', 'exclusiveMinimum': 0}, 'hw': {'type': 'number', 'exclusiveMinimum': 0}, 'rot': {'type': 'number'}, 'kind': {'type': 'string', 'const': 'rect'}}, 'additionalProperties': False}, {'type': 'object', 'required': ['kind', 'cx', 'cy', 'r'], 'properties': {'r': {'type': 'number', 'exclusiveMinimum': 0}, 'cx': {'type': 'number', 'maximum': 1, 'minimum': 0}, 'cy': {'type': 'number', 'maximum': 1, 'minimum': 0}, 'kind': {'type': 'string', 'const': 'circle'}}, 'additionalProperties': False}, {'type': 'object', 'required': ['kind', 'points'], 'properties': {'rot': {'type': 'number'}, 'kind': {'type': 'string', 'const': 'polygon'}, 'points': {'type': 'array', 'items': {'type': 'object', 'required': ['x', 'y'], 'properties': {'x': {'type': 'number', 'maximum': 1, 'minimum': 0}, 'y': {'type': 'number', 'maximum': 1, 'minimum': 0}}, 'additionalProperties': False}, 'maxItems': 64, 'minItems': 3}}, 'additionalProperties': False}]}, 'maxItems': 16, 'minItems': 1}}, 'additionalProperties': False}, {'type': 'object', 'required': ['kind'], 'properties': {'kind': {'type': 'string', 'const': 'none'}}, 'additionalProperties': False}], 'description': 'Reusable asset collider. All child coordinates are fractions of the same sprite/cell; circle radius is a fraction of width. Compound children are separate solids, not a filled bounding box. None explicitly disables collision; null/omission follows endpoint inheritance rules.'}, {'type': 'null'}], 'description': 'Reusable asset collider. All child coordinates are fractions of the same sprite/cell; circle radius is a fraction of width. Compound children are separate solids, not a filled bounding box. None explicitly disables collision; null/omission follows endpoint inheritance rules.'}, 'hitboxFrames': {'anyOf': [{'type': 'array', 'items': {'type': 'object', 'required': ['from', 'to'], 'properties': {'to': {'type': 'integer', 'minimum': 0}, 'from': {'type': 'integer', 'minimum': 0}}, 'additionalProperties': False}, 'maxItems': 64}, {'type': 'null'}]}}, 'additionalProperties': False}, {'type': 'null'}]}}, 'additionalProperties': False}
start_project_export
Build complete game project
FREE. Queue a durable complete Phaser, Godot or Unity project export. First review with get_project_export_review and pass its version and selected starting map/player. Returns a job ID immediately; poll get_project_export_status until ready. No generation credits are spent.
Acceso externo
Esquema de entrada
{'type': 'object', 'required': ['projectId', 'engine', 'startMapId', 'playerCharacterId', 'expectedVersion'], 'properties': {'engine': {'enum': ['phaser', 'godot', 'unity'], 'type': 'string'}, 'projectId': {'type': 'string'}, 'startMapId': {'type': 'string'}, 'expectedVersion': {'type': 'string', 'pattern': '^[a-f0-9]{64}$'}, 'playerCharacterId': {'type': 'string'}}, 'additionalProperties': False}
suggest_motion_hint
Suggest a motion hint for a staged asset
PAID but very cheap (one configured text-model call) and SYNCHRONOUS — returns { hint, cost } inline, no jobId. Reads a STAGED asset's prompt plus the stage pairs you intend to animate and writes the one-sentence motion description to pass as animate_asset's motionHint. Use it when you are about to spend 300 credits on a default video and are unsure what to write: a few credits here protects that spend. Object States assets only — any other type answers 400.
Acceso externo
Esquema de entrada
{'type': 'object', 'required': ['assetId'], 'properties': {'pairs': {'type': 'array', 'items': {'type': 'object', 'required': ['from', 'to'], 'properties': {'to': {'anyOf': [{'type': 'integer', 'minimum': 0}, {'type': 'null'}], 'description': 'End stage index, or null for open-ended motion.'}, 'from': {'type': 'integer', 'minimum': 0, 'description': 'Start stage index.'}}, 'additionalProperties': False}, 'maxItems': 32, 'description': 'The stage transitions you plan to animate — context for the hint, nothing is generated from them.'}, 'dryRun': {'type': 'boolean', 'default': True, 'description': "DEFAULTS TO TRUE. While true this returns only a cost quote ({ estimatedCredits, balance, spendCapDaily, spentLast24h, capRemaining }) and executes nothing. Show the user estimatedCredits, then ask a normal confirmation question. Prefer the client's native question UI with Approve / Decline / Discuss choices when available; otherwise accept any unambiguous conversational approval. Never require a fixed phrase or ask the user to type a magic word. Only after approval, re-call with dryRun:false to actually spend."}, 'assetId': {'type': 'string', 'description': 'Object States asset id or slug.'}, 'idempotencyKey': {'type': 'string', 'minLength': 1, 'description': 'Optional Idempotency-Key for the real (dryRun:false) call. Omit and one is minted per call. Reuse the SAME value when retrying a call that failed with ENTITY_BUSY / 402 / 429 so the retry cannot double-dispatch.'}}, 'additionalProperties': False}
suggest_project_style
Suggest style and fonts
Suggest palette, treatment and existing font IDs from the available catalog. Free to customers; suggestions require explicit save to adopt.
Acceso externo
Esquema de entrada
{'type': 'object', 'required': ['projectId', 'direction'], 'properties': {'direction': {'type': 'string', 'maxLength': 2000, 'minLength': 1}, 'projectId': {'type': 'string'}, 'previewText': {'type': 'string', 'maxLength': 2000}}, 'additionalProperties': False}
validate_ui_component_layout
Validate UI component layout
Revalidate an exact current revision and apply only proven deterministic runtime layout repairs, including bar fill openings, panel text/slice regions, and explicitly named SVG button-state separation. Free; preserves original sources. This is not arbitrary SVG artwork editing and cannot promise a successful capability result.
Acceso externo
Esquema de entrada
{'type': 'object', 'required': ['packId', 'componentId', 'revisionId'], 'properties': {'packId': {'type': 'string', 'format': 'uuid', 'description': 'Owned UI Pack ID.'}, 'revisionId': {'type': 'string', 'format': 'uuid'}, 'componentId': {'type': 'string', 'format': 'uuid', 'description': 'Owned component ID within this pack.'}}, 'additionalProperties': False}
whoami
Who am I
Verify the API key and report which powers it has. Returns { userId, username, keyId, keyName, scopes, mapLimits }. mapLimits contains maxMapsPerProject (null means unlimited), maxAreaPx (width × height allowance per map), maxWidthPx and maxHeightPx (independent technical side limits), and canResizeMaps. Paid plans allow any aspect ratio within both area and side limits. Admin accounts receive Studio map capacity even without a subscription. Read effective limits and the saved map before recommending gameplay-sized dimensions; starter dimensions are not an account limit. Free is fixed at 720 × 480; saved larger maps remain editable/exportable, but resizing requires a subscription. Map creation and editing use the web editor. Call this first when a tool fails with a scope error — the scopes array tells you what this key can and cannot do.
Solo lectura Acceso externo Idempotente
Esquema de entrada
{'type': 'object', 'properties': {}, 'additionalProperties': False}
Añadido
restore_map_revision
1 de October de 2026 a las 02:54
Añadido
list_map_revisions
1 de October de 2026 a las 02:54
Añadido
commit_map_draft
1 de October de 2026 a las 02:54
Añadido
preview_map_draft
1 de October de 2026 a las 02:54
Añadido
get_map_draft
1 de October de 2026 a las 02:54
Añadido
prepare_map_draft
1 de October de 2026 a las 02:54
Añadido
map_authoring_schema
1 de October de 2026 a las 02:54
Añadido
map_authoring_context
1 de October de 2026 a las 02:54
Añadido
prepare_map_edits
1 de October de 2026 a las 02:54
Añadido
map_workbench_context
1 de October de 2026 a las 02:54
Añadido
map_project_library
1 de October de 2026 a las 02:54
Añadido
run_map_playtest
1 de October de 2026 a las 02:54
Modificado
set_asset_collision_body
1 de October de 2026 a las 02:54
Añadido
set_asset_collision_roles
1 de October de 2026 a las 02:54
Añadido
set_character_collision_roles
1 de October de 2026 a las 02:54
Modificado
get_map
1 de October de 2026 a las 02:54
Modificado
plan_sync
1 de October de 2026 a las 02:54
Añadido
get_project_export_command
1 de October de 2026 a las 02:54
Añadido
get_project_export_status
1 de October de 2026 a las 02:54
Añadido
start_project_export
1 de October de 2026 a las 02:54
Añadido
get_project_export_review
1 de October de 2026 a las 02:54
Añadido
resume_ui_pack_batch
25 de September de 2026 a las 03:03
Modificado
suggest_motion_hint
25 de September de 2026 a las 03:03
Modificado
retry_job
25 de September de 2026 a las 03:03
Modificado
create_asset
25 de September de 2026 a las 03:03
Modificado
fix_asset_seams
25 de September de 2026 a las 03:03
Modificado
regen_asset_pair
25 de September de 2026 a las 03:03
Modificado
animate_asset
25 de September de 2026 a las 03:03
Modificado
generate_pose
25 de September de 2026 a las 03:03
Añadido
resume_pose
25 de September de 2026 a las 03:03