{
  "openapi": "3.1.0",
  "info": {
    "title": "Killa Tamata AI",
    "version": "0.7.0",
    "description": "API-first prepaid $ credit gateway for Killa Tamata media generation. Purchase credits, settle checkout claims, manage keys, and submit media jobs."
  },
  "servers": [
    {
      "url": "https://api.killatamata.com"
    }
  ],
  "tags": [
    {
      "name": "auth"
    },
    {
      "name": "affiliates"
    },
    {
      "name": "health"
    },
    {
      "name": "catalog"
    },
    {
      "name": "checkout"
    },
    {
      "name": "credits"
    },
    {
      "name": "claim"
    },
    {
      "name": "keys"
    },
    {
      "name": "balance"
    },
    {
      "name": "arcade"
    },
    {
      "name": "studio"
    },
    {
      "name": "media"
    },
    {
      "name": "webhooks"
    }
  ],
  "components": {
    "securitySchemes": {
      "BearerAuth": {
        "type": "http",
        "scheme": "bearer",
        "bearerFormat": "API key"
      }
    },
    "schemas": {
      "HealthSkillVersion": {
        "type": "object",
        "required": [
          "name",
          "version",
          "compatibleApiVersion",
          "compatibilityPolicy",
          "autoUpdate",
          "manifestUrl",
          "metadataUrl",
          "rootUrl",
          "entrypointUrl"
        ],
        "properties": {
          "name": {
            "type": "string"
          },
          "version": {
            "type": "string"
          },
          "compatibleApiVersion": {
            "type": "string"
          },
          "compatibilityPolicy": {
            "type": "string",
            "enum": [
              "exact"
            ]
          },
          "autoUpdate": {
            "type": "boolean"
          },
          "manifestUrl": {
            "type": "string",
            "format": "uri"
          },
          "metadataUrl": {
            "type": "string",
            "format": "uri"
          },
          "rootUrl": {
            "type": "string",
            "format": "uri"
          },
          "entrypointUrl": {
            "type": "string",
            "format": "uri"
          }
        },
        "additionalProperties": false
      },
      "HealthVersionInfo": {
        "type": "object",
        "required": [
          "release",
          "api",
          "skill"
        ],
        "properties": {
          "release": {
            "type": "string"
          },
          "api": {
            "type": "string"
          },
          "skill": {
            "$ref": "#/components/schemas/HealthSkillVersion"
          }
        },
        "additionalProperties": false
      },
      "HealthResponse": {
        "type": "object",
        "required": [
          "status",
          "service",
          "timestamp",
          "version"
        ],
        "properties": {
          "status": {
            "type": "string",
            "enum": [
              "ok"
            ]
          },
          "service": {
            "type": "string"
          },
          "timestamp": {
            "type": "string",
            "format": "date-time"
          },
          "version": {
            "$ref": "#/components/schemas/HealthVersionInfo"
          }
        },
        "additionalProperties": false
      },
      "MediaAspectRatio": {
        "type": "string",
        "enum": [
          "1:1",
          "16:9",
          "9:16",
          "9:7",
          "7:9"
        ]
      },
      "MediaImageOutputFormat": {
        "type": "string",
        "enum": [
          "webp",
          "png",
          "jpg"
        ],
        "default": "webp",
        "description": "Optional output image format. Defaults to webp when omitted. Dot-prefixed aliases are also accepted at runtime (.webp, .png, .jpg)."
      },
      "MediaInlineImageSource": {
        "type": "object",
        "properties": {
          "url": {
            "type": "string",
            "format": "uri"
          },
          "dataBase64": {
            "type": "string",
            "description": "Raw image bytes encoded as base64 (or data URI). Input is staged on CDN, with best-effort WebP conversion when encoder support is available."
          },
          "mimeType": {
            "type": "string",
            "enum": [
              "image/webp",
              "image/png",
              "image/jpeg",
              "image/jpg"
            ],
            "description": "Supported inline MIME types. image/jpg is accepted and normalized to image/jpeg at runtime."
          }
        },
        "additionalProperties": false,
        "oneOf": [
          {
            "required": [
              "url"
            ]
          },
          {
            "required": [
              "dataBase64"
            ]
          }
        ]
      },
      "MediaImageInput": {
        "oneOf": [
          {
            "type": "string",
            "format": "uri"
          },
          {
            "$ref": "#/components/schemas/MediaInlineImageSource"
          }
        ],
        "description": "Provide either a direct image URL string or an inline image object."
      },
      "MediaInlineAudioSource": {
        "type": "object",
        "properties": {
          "url": {
            "type": "string",
            "format": "uri"
          },
          "dataBase64": {
            "type": "string",
            "description": "Raw audio bytes encoded as base64 (or data URI). Input is staged on CDN before provider submission."
          },
          "mimeType": {
            "type": "string",
            "enum": [
              "audio/ogg",
              "audio/opus",
              "audio/wav",
              "audio/x-wav",
              "audio/wave",
              "audio/mpeg",
              "audio/mp3",
              "audio/flac",
              "audio/x-flac",
              "audio/aac",
              "audio/mp4",
              "audio/webm"
            ]
          }
        },
        "additionalProperties": false,
        "oneOf": [
          {
            "required": [
              "url"
            ]
          },
          {
            "required": [
              "dataBase64"
            ]
          }
        ]
      },
      "MediaAudioInput": {
        "oneOf": [
          {
            "type": "string",
            "format": "uri"
          },
          {
            "$ref": "#/components/schemas/MediaInlineAudioSource"
          }
        ],
        "description": "Provide either a direct audio URL string or an inline audio object."
      },
      "MediaJobRequest": {
        "oneOf": [
          {
            "type": "object",
            "required": [
              "task",
              "input"
            ],
            "properties": {
              "task": {
                "type": "string",
                "enum": [
                  "image.generate"
                ]
              },
              "input": {
                "type": "object",
                "required": [
                  "prompt"
                ],
                "properties": {
                  "prompt": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 4000
                  },
                  "aspectRatio": {
                    "$ref": "#/components/schemas/MediaAspectRatio"
                  },
                  "outputFormat": {
                    "$ref": "#/components/schemas/MediaImageOutputFormat"
                  },
                  "highDetail": {
                    "type": "boolean",
                    "default": false,
                    "description": "Optional higher-detail image mode. Defaults to false. Increases inference steps by 50% and billed cost by 50%."
                  },
                  "upscale": {
                    "type": "boolean",
                    "description": "Optional built-in 1.5x upscale toggle. Defaults to false."
                  },
                  "width": {
                    "type": "integer",
                    "minimum": 32,
                    "multipleOf": 32,
                    "description": "Optional explicit output width. Must be provided together with height. Max 4MP total."
                  },
                  "height": {
                    "type": "integer",
                    "minimum": 32,
                    "multipleOf": 32,
                    "description": "Optional explicit output height. Must be provided together with width. Max 4MP total."
                  },
                  "referenceImageUrls": {
                    "type": "array",
                    "maxItems": 5,
                    "items": {
                      "type": "string",
                      "format": "uri"
                    },
                    "description": "URL-only legacy alias for reference images."
                  },
                  "referenceImages": {
                    "type": "array",
                    "maxItems": 5,
                    "items": {
                      "$ref": "#/components/schemas/MediaImageInput"
                    },
                    "description": "Preferred reference image input (URL strings or inline objects)."
                  }
                },
                "additionalProperties": false
              },
              "idempotencyKey": {
                "type": "string",
                "minLength": 1,
                "maxLength": 200
              },
              "completionCallbackUrl": {
                "type": "string",
                "format": "uri",
                "description": "Optional terminal callback URL. Receives one job-level POST when the job reaches a terminal state."
              }
            },
            "additionalProperties": false
          },
          {
            "type": "object",
            "required": [
              "task",
              "input"
            ],
            "properties": {
              "task": {
                "type": "string",
                "enum": [
                  "image.edit"
                ]
              },
              "input": {
                "type": "object",
                "required": [
                  "prompt"
                ],
                "anyOf": [
                  {
                    "required": [
                      "sourceImageUrl"
                    ]
                  },
                  {
                    "required": [
                      "sourceImage"
                    ]
                  }
                ],
                "properties": {
                  "prompt": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 4000
                  },
                  "sourceImageUrl": {
                    "type": "string",
                    "format": "uri"
                  },
                  "sourceImage": {
                    "$ref": "#/components/schemas/MediaImageInput"
                  },
                  "outputFormat": {
                    "$ref": "#/components/schemas/MediaImageOutputFormat"
                  },
                  "highDetail": {
                    "type": "boolean",
                    "default": false,
                    "description": "Optional higher-detail image mode. Defaults to false. Increases inference steps by 50% and billed cost by 50%."
                  },
                  "referenceImageUrls": {
                    "type": "array",
                    "maxItems": 5,
                    "items": {
                      "type": "string",
                      "format": "uri"
                    },
                    "description": "URL-only legacy alias for reference images."
                  },
                  "referenceImages": {
                    "type": "array",
                    "maxItems": 5,
                    "items": {
                      "$ref": "#/components/schemas/MediaImageInput"
                    },
                    "description": "Preferred reference image input (URL strings or inline objects)."
                  }
                },
                "additionalProperties": false
              },
              "idempotencyKey": {
                "type": "string",
                "minLength": 1,
                "maxLength": 200
              },
              "completionCallbackUrl": {
                "type": "string",
                "format": "uri",
                "description": "Optional terminal callback URL. Receives one job-level POST when the job reaches a terminal state."
              }
            },
            "additionalProperties": false
          },
          {
            "type": "object",
            "required": [
              "task",
              "input"
            ],
            "properties": {
              "task": {
                "type": "string",
                "enum": [
                  "video.generate"
                ]
              },
              "input": {
                "type": "object",
                "required": [
                  "prompt"
                ],
                "description": "Provide startFrameImage/startFrameImageUrl (or sourceImage/sourceImageUrl aliases) for image-to-video, or omit them for text-to-video. Seamless extension is supported via overlapFrameImageUrls/overlapFrameImages: upload trailing frames from the previous clip in chronological order, preferably as lossless or visually lossless WebP extracted on the client at sampled/base FPS. If no separate start frame is provided, the first overlap frame becomes frame zero automatically. Optional reference audio is supported via referenceAudioUrl/referenceAudio, requires either a start frame or overlap frames, and can be combined with finalFrameImageUrl/finalFrameImage when you need both audio sync and a closing-frame guide. Reference-audio requests are strict and are not silently downgraded to non-audio conditioning. Prefer durationFrames for exact continuation timing; it uses sampled/base FPS and must satisfy the LTX rule 8n + 1. durationSeconds is accepted only when its implied sampled-frame count stays within the same valid LTX frame budget. Width/height define the final output canvas. Standard routing automatically selects the appropriate backend memory tier for the requested clip; set extremeQuality=true only when you explicitly want the higher-fidelity path, which bills 50% more. Image-to-video output is probabilistic and may be frozen/warped/unusable on some runs, so clients should run multiple candidates and select winners.",
                "properties": {
                  "prompt": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 4000
                  },
                  "startFrameImageUrl": {
                    "type": "string",
                    "format": "uri",
                    "description": "Optional start-frame image URL. Omit for text-to-video mode. Equivalent to sourceImageUrl."
                  },
                  "startFrameImage": {
                    "allOf": [
                      {
                        "$ref": "#/components/schemas/MediaImageInput"
                      }
                    ],
                    "description": "Optional start-frame image as URL string or inline object. Equivalent to sourceImage."
                  },
                  "sourceImageUrl": {
                    "type": "string",
                    "format": "uri",
                    "description": "Legacy alias for startFrameImageUrl."
                  },
                  "sourceImage": {
                    "allOf": [
                      {
                        "$ref": "#/components/schemas/MediaImageInput"
                      }
                    ],
                    "description": "Legacy alias for startFrameImage."
                  },
                  "overlapFrameImageUrls": {
                    "type": "array",
                    "maxItems": 12,
                    "items": {
                      "type": "string",
                      "format": "uri"
                    },
                    "description": "Optional ordered overlap-frame URLs for seamless clip extension. Upload client-extracted trailing frames from the previous clip in chronological order. Default to lossless or visually lossless WebP for continuation work. If no separate start frame is provided, the first overlap frame becomes frame zero automatically."
                  },
                  "overlapFrameImages": {
                    "type": "array",
                    "maxItems": 12,
                    "items": {
                      "$ref": "#/components/schemas/MediaImageInput"
                    },
                    "description": "Optional ordered overlap frames as URL strings or inline objects. Upload client-extracted trailing frames from the previous clip in chronological order. Prefer inline or URL-based WebP for efficient continuation payloads; avoid JPEG for seam-sensitive extension work."
                  },
                  "finalFrameImageUrl": {
                    "type": "string",
                    "format": "uri",
                    "description": "Optional final-frame steering URL. Can be used with or without referenceAudioUrl/referenceAudio."
                  },
                  "finalFrameImage": {
                    "$ref": "#/components/schemas/MediaImageInput",
                    "description": "Optional final-frame steering (URL string or inline object). Can be used with or without referenceAudioUrl/referenceAudio."
                  },
                  "referenceAudioUrl": {
                    "type": "string",
                    "format": "uri",
                    "description": "Optional reference audio URL for motion/audio synchronization. Requires a start frame or overlap frames and may be combined with finalFrameImage* when you need both audio sync and final-frame steering. Requests are strict: if reference audio cannot be applied, the request fails. Prompt these shots as anchored performances: honor frame-zero composition, keep the subject readable, and let mouth articulation, jaw travel, breath timing, shoulder rhythm, and phrase-timed gestures carry the sync."
                  },
                  "referenceAudio": {
                    "allOf": [
                      {
                        "$ref": "#/components/schemas/MediaAudioInput"
                      }
                    ],
                    "description": "Optional reference audio as URL string or inline object. Requires a start frame or overlap frames and may be combined with finalFrameImage* when you need both audio sync and final-frame steering. Requests are strict: if reference audio cannot be applied, the request fails. Prompt these shots as anchored performances: honor frame-zero composition, keep the subject readable, and let mouth articulation, jaw travel, breath timing, shoulder rhythm, and phrase-timed gestures carry the sync."
                  },
                  "durationSeconds": {
                    "type": "integer",
                    "minimum": 3,
                    "maximum": 20,
                    "description": "Optional whole-second duration. Use only when the implied sampled-frame count remains inside the LTX-valid frame budget for the chosen sampledFps. Prefer durationFrames for exact continuation timing."
                  },
                  "durationFrames": {
                    "type": "integer",
                    "minimum": 9,
                    "maximum": 257,
                    "description": "Optional sampled/base frame count for exact-duration video generation. Must satisfy the LTX rule 8n + 1 (for example 9, 17, 25, ...). Prefer this over durationSeconds for extension-video work."
                  },
                  "aspectRatio": {
                    "$ref": "#/components/schemas/MediaAspectRatio"
                  },
                  "sampledFps": {
                    "type": "integer",
                    "minimum": 1,
                    "maximum": 50,
                    "description": "Optional sampled/base FPS used for duration-frame math and overlap timing. At 25fps, exact continuation-friendly durations use valid durationFrames such as 249 or 257 rather than 250."
                  },
                  "width": {
                    "type": "integer",
                    "minimum": 32,
                    "multipleOf": 32,
                    "description": "Optional final output width. Must be provided together with height. The workflow always runs the first sampling pass at half of the requested final width."
                  },
                  "height": {
                    "type": "integer",
                    "minimum": 32,
                    "multipleOf": 32,
                    "description": "Optional final output height. Must be provided together with width. The workflow always runs the first sampling pass at half of the requested final height."
                  },
                  "interpolationFps": {
                    "description": "Optional output FPS target for interpolation. Omit to keep the default 60 FPS interpolation. Use 0 to disable interpolation and keep sampled/base FPS. Default pipeline is 30fps sampled + RIFE interpolation to 60fps. Allowed values: 0 or 30..60.",
                    "default": 60,
                    "anyOf": [
                      {
                        "type": "integer",
                        "const": 0
                      },
                      {
                        "type": "integer",
                        "minimum": 30,
                        "maximum": 60
                      }
                    ]
                  },
                  "seed": {
                    "type": "integer",
                    "minimum": 1,
                    "maximum": 2147483647,
                    "description": "Optional deterministic seed. Keep this fixed across clip-B continuation variants when comparing seam quality, color continuity, or overlap strategies."
                  },
                  "extremeQuality": {
                    "type": "boolean",
                    "default": false,
                    "description": "Optional higher-fidelity video path. Defaults to false. Set true only when you explicitly want the extreme-quality path; it bills 50% more than standard video generation."
                  }
                },
                "additionalProperties": false
              },
              "idempotencyKey": {
                "type": "string",
                "minLength": 1,
                "maxLength": 200
              },
              "completionCallbackUrl": {
                "type": "string",
                "format": "uri",
                "description": "Optional terminal callback URL. Receives one job-level POST when the job reaches a terminal state."
              }
            },
            "additionalProperties": false
          },
          {
            "type": "object",
            "required": [
              "task",
              "input"
            ],
            "properties": {
              "task": {
                "type": "string",
                "enum": [
                  "video.combine"
                ]
              },
              "input": {
                "type": "object",
                "required": [
                  "videoUrls"
                ],
                "description": "Combines one or more existing video clips into a single output clip while concatenating their embedded audio. This path is designed for stitching continuation outputs without loading every frame into a large in-memory graph. `overlapFrames` trims duplicated head frames from every clip after the first and trims the corresponding leading audio duration before concatenation. `frameRate` defaults to 60 and is used to convert overlap frames into trim seconds inside the streaming concat node.",
                "properties": {
                  "videoUrls": {
                    "type": "array",
                    "minItems": 2,
                    "maxItems": 24,
                    "items": {
                      "type": "string",
                      "format": "uri"
                    },
                    "description": "Ordered source clip URLs. At least two clips are required. Each clip is appended after the previous one. The API submits them to the streaming concat node as direct HTTPS entries."
                  },
                  "overlapFrames": {
                    "type": "integer",
                    "minimum": 0,
                    "maximum": 120,
                    "default": 1,
                    "description": "Optional number of duplicated head frames to remove from every clip after the first. Use 1 for current `video_ltx23` continuation clips, or raise it if a future workflow carries a longer overlap region."
                  },
                  "frameRate": {
                    "type": "integer",
                    "minimum": 1,
                    "maximum": 120,
                    "default": 60,
                    "description": "Optional frame rate used when loading source clips and converting overlap frames into an audio trim duration. Keep this aligned with the actual clip FPS; current `video_ltx23` outputs are expected to use 60 FPS."
                  }
                },
                "additionalProperties": false
              },
              "idempotencyKey": {
                "type": "string",
                "minLength": 1,
                "maxLength": 200
              },
              "completionCallbackUrl": {
                "type": "string",
                "format": "uri",
                "description": "Optional terminal callback URL. Receives one job-level POST when the job reaches a terminal state."
              }
            },
            "additionalProperties": false
          },
          {
            "type": "object",
            "required": [
              "task",
              "input"
            ],
            "properties": {
              "task": {
                "type": "string",
                "enum": [
                  "video.resize"
                ]
              },
              "input": {
                "type": "object",
                "required": [
                  "sourceVideoUrl",
                  "width",
                  "height"
                ],
                "description": "Deterministically rescales an existing remote video to explicit even output dimensions. The gateway probes the source clip at submit time and bills from output resolution plus billable frame count. Provide sourceDurationSeconds only as a fallback when remote probing is unavailable.",
                "properties": {
                  "sourceVideoUrl": {
                    "type": "string",
                    "format": "uri",
                    "description": "Remote source clip URL to resize."
                  },
                  "width": {
                    "type": "integer",
                    "minimum": 2,
                    "maximum": 7680,
                    "multipleOf": 2,
                    "description": "Required even output width in pixels."
                  },
                  "height": {
                    "type": "integer",
                    "minimum": 2,
                    "maximum": 7680,
                    "multipleOf": 2,
                    "description": "Required even output height in pixels."
                  },
                  "frameRate": {
                    "type": "integer",
                    "minimum": 1,
                    "maximum": 120,
                    "description": "Optional source/output frame rate hint. Defaults to 60 and is used for submit-time billing and duration estimates."
                  },
                  "sourceDurationSeconds": {
                    "type": "number",
                    "minimum": 0.1,
                    "maximum": 600,
                    "description": "Optional source clip duration hint in seconds. Defaults to 8 when omitted for pricing and ETA estimation."
                  }
                },
                "additionalProperties": false
              },
              "idempotencyKey": {
                "type": "string",
                "minLength": 1,
                "maxLength": 200
              },
              "completionCallbackUrl": {
                "type": "string",
                "format": "uri",
                "description": "Optional terminal callback URL. Receives one job-level POST when the job reaches a terminal state."
              }
            },
            "additionalProperties": false
          },
          {
            "type": "object",
            "required": [
              "task",
              "input"
            ],
            "properties": {
              "task": {
                "type": "string",
                "enum": [
                  "audio.speak"
                ]
              },
              "input": {
                "type": "object",
                "required": [
                  "text"
                ],
                "properties": {
                  "text": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 6000,
                    "description": "TTS synthesis text. Both providers accept 1..6000 chars. Gemini settles to an exact completion-time bill after a submit-time hold; OmniVoice remains submit-time billed."
                  },
                  "provider": {
                    "type": "string",
                    "enum": [
                      "omnivoice",
                      "gemini"
                    ],
                    "description": "Optional TTS provider selector. Omit to use OmniVoice. Use gemini for direct Gemini 3.1 Flash TTS single-speaker WAV output."
                  },
                  "mode": {
                    "type": "string",
                    "enum": [
                      "voice_design",
                      "voice_clone"
                    ],
                    "description": "Optional OmniVoice mode selector. Omit for voice design, or set voice_clone when supplying reference audio. Gemini does not support voice_clone."
                  },
                  "voiceDescription": {
                    "type": "string",
                    "minLength": 4,
                    "maxLength": 240,
                    "description": "OmniVoice-only comma-separated voice tags. Supported English tags in this API release: female, male, child, teenager, young adult, middle-aged, elderly, very low pitch, low pitch, moderate pitch, high pitch, very high pitch, whisper, american accent, british accent, australian accent, canadian accent, indian accent, chinese accent, korean accent, japanese accent, portuguese accent, russian accent. In voice design mode it defines the synthetic voice; in voice clone mode it can add light steering on top of the reference voice."
                  },
                  "voiceName": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 120,
                    "description": "Gemini-only voice name. Defaults to Kore when omitted. Keep this as a non-empty string because Google's preview voice inventory can change over time."
                  },
                  "instructions": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 2000,
                    "description": "Gemini-only delivery/style guidance. When present, the gateway prepends it ahead of the literal spoken text using 'Read the following text exactly as written:'."
                  },
                  "referenceAudioUrl": {
                    "type": "string",
                    "format": "uri",
                    "description": "OmniVoice-only reference audio URL for voice clone mode."
                  },
                  "referenceAudio": {
                    "anyOf": [
                      {
                        "type": "string",
                        "format": "uri"
                      },
                      {
                        "type": "object",
                        "properties": {
                          "url": {
                            "type": "string",
                            "format": "uri"
                          },
                          "dataBase64": {
                            "type": "string"
                          },
                          "mimeType": {
                            "type": "string"
                          }
                        },
                        "additionalProperties": false
                      }
                    ],
                    "description": "OmniVoice-only inline or URL-based reference audio for voice clone mode."
                  },
                  "referenceTranscript": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 2000,
                    "description": "OmniVoice-only transcript matching the reference audio clip for voice clone mode."
                  },
                  "language": {
                    "type": "string",
                    "enum": [
                      "English",
                      "en"
                    ],
                    "description": "OmniVoice language selection for this v1 release (English only)."
                  },
                  "quality": {
                    "type": "string",
                    "enum": [
                      "96k",
                      "128k",
                      "192k"
                    ],
                    "description": "OmniVoice output Opus quality preset."
                  },
                  "seed": {
                    "type": "integer",
                    "minimum": 1,
                    "maximum": 2147483647,
                    "description": "OmniVoice-only seed."
                  }
                },
                "additionalProperties": false
              },
              "idempotencyKey": {
                "type": "string",
                "minLength": 1,
                "maxLength": 200
              },
              "completionCallbackUrl": {
                "type": "string",
                "format": "uri",
                "description": "Optional terminal callback URL. Receives one job-level POST when the job reaches a terminal state."
              }
            },
            "additionalProperties": false
          },
          {
            "type": "object",
            "required": [
              "task",
              "input"
            ],
            "properties": {
              "task": {
                "type": "string",
                "enum": [
                  "audio.annotation.reference"
                ]
              },
              "input": {
                "type": "object",
                "anyOf": [
                  {
                    "required": [
                      "sourceAudioUrl"
                    ]
                  },
                  {
                    "required": [
                      "sourceAudio"
                    ]
                  }
                ],
                "properties": {
                  "sourceAudioUrl": {
                    "type": "string",
                    "format": "uri",
                    "description": "Source audio URL to annotate."
                  },
                  "sourceAudio": {
                    "allOf": [
                      {
                        "$ref": "#/components/schemas/MediaAudioInput"
                      }
                    ],
                    "description": "Source audio as URL string or inline base64 object."
                  },
                  "transcript": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 24000,
                    "description": "Optional transcript used for reference anchoring, section recovery, and stronger word timings. If omitted, the gateway switches to transcriptless ASR."
                  },
                  "language": {
                    "type": "string",
                    "enum": [
                      "en"
                    ],
                    "description": "Language code for transcript anchoring or transcriptless ASR."
                  },
                  "transcriptionModel": {
                    "type": "string",
                    "enum": [
                      "distil-large-v3",
                      "large-v3"
                    ],
                    "description": "Whisper model selection for transcription. The default is distil-large-v3 when transcript anchoring is used, and large-v3 when transcriptless ASR is used."
                  },
                  "device": {
                    "type": "string",
                    "enum": [
                      "auto",
                      "cuda",
                      "cpu"
                    ],
                    "description": "Worker execution target hint for the annotation node."
                  }
                },
                "additionalProperties": false
              },
              "idempotencyKey": {
                "type": "string",
                "minLength": 1,
                "maxLength": 200
              },
              "completionCallbackUrl": {
                "type": "string",
                "format": "uri",
                "description": "Optional terminal callback URL. Receives one job-level POST when the job reaches a terminal state."
              }
            },
            "additionalProperties": false
          },
          {
            "type": "object",
            "required": [
              "task",
              "input"
            ],
            "properties": {
              "task": {
                "type": "string",
                "enum": [
                  "ace.step.create"
                ]
              },
              "input": {
                "type": "object",
                "required": [
                  "tags",
                  "lyrics"
                ],
                "properties": {
                  "tags": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 2000
                  },
                  "lyrics": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 12000
                  },
                  "qualityPreset": {
                    "type": "string",
                    "enum": [
                      "default",
                      "high_quality"
                    ],
                    "description": "Optional recipe preset. high_quality applies long-form music defaults tuned from Ace Step QA rounds (108s, 192k, richer sampler settings). Explicit fields still override preset defaults."
                  },
                  "durationSeconds": {
                    "type": "integer",
                    "minimum": 15,
                    "maximum": 240
                  },
                  "bpm": {
                    "type": "integer",
                    "minimum": 40,
                    "maximum": 240
                  },
                  "quality": {
                    "type": "string",
                    "enum": [
                      "96k",
                      "128k",
                      "192k"
                    ],
                    "description": "Output Opus quality preset."
                  },
                  "seed": {
                    "type": "integer",
                    "minimum": 1,
                    "maximum": 2147483647
                  },
                  "steps": {
                    "type": "integer",
                    "minimum": 4,
                    "maximum": 32
                  },
                  "textCfgScale": {
                    "type": "number",
                    "minimum": 1,
                    "maximum": 8
                  },
                  "samplerCfg": {
                    "type": "number",
                    "minimum": 1,
                    "maximum": 12
                  },
                  "temperature": {
                    "type": "number",
                    "minimum": 0.1,
                    "maximum": 2
                  },
                  "topP": {
                    "type": "number",
                    "minimum": 0,
                    "maximum": 1
                  },
                  "topK": {
                    "type": "integer",
                    "minimum": 0,
                    "maximum": 200
                  },
                  "minP": {
                    "type": "number",
                    "minimum": 0,
                    "maximum": 0.5
                  },
                  "timeSignature": {
                    "type": "string",
                    "enum": [
                      "2",
                      "3",
                      "4",
                      "5",
                      "6",
                      "7"
                    ]
                  },
                  "language": {
                    "type": "string",
                    "enum": [
                      "en"
                    ],
                    "description": "Ace Step 1.5 language code (currently English only)."
                  },
                  "keyScale": {
                    "type": "string",
                    "pattern": "^[A-G](?:#|b)?\\s(?:major|minor)$",
                    "description": "Musical key, for example 'E minor' or 'C major'."
                  }
                },
                "additionalProperties": false
              },
              "idempotencyKey": {
                "type": "string",
                "minLength": 1,
                "maxLength": 200
              },
              "completionCallbackUrl": {
                "type": "string",
                "format": "uri",
                "description": "Optional terminal callback URL. Receives one job-level POST when the job reaches a terminal state."
              }
            },
            "additionalProperties": false
          },
          {
            "type": "object",
            "required": [
              "task",
              "input"
            ],
            "properties": {
              "task": {
                "type": "string",
                "enum": [
                  "moss.sound.effect"
                ]
              },
              "input": {
                "type": "object",
                "required": [
                  "prompt"
                ],
                "properties": {
                  "prompt": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 2000
                  },
                  "durationSeconds": {
                    "type": "integer",
                    "minimum": 1,
                    "maximum": 30
                  },
                  "quality": {
                    "type": "string",
                    "enum": [
                      "96k",
                      "128k",
                      "192k"
                    ],
                    "description": "Output Opus quality preset."
                  },
                  "temperature": {
                    "type": "number",
                    "minimum": 0.1,
                    "maximum": 3
                  },
                  "topP": {
                    "type": "number",
                    "minimum": 0,
                    "maximum": 1
                  },
                  "topK": {
                    "type": "integer",
                    "minimum": 1,
                    "maximum": 200
                  },
                  "repetitionPenalty": {
                    "type": "number",
                    "minimum": 0.8,
                    "maximum": 2.5
                  },
                  "maxNewTokens": {
                    "type": "integer",
                    "minimum": 64,
                    "maximum": 4096
                  }
                },
                "additionalProperties": false
              },
              "idempotencyKey": {
                "type": "string",
                "minLength": 1,
                "maxLength": 200
              },
              "completionCallbackUrl": {
                "type": "string",
                "format": "uri",
                "description": "Optional terminal callback URL. Receives one job-level POST when the job reaches a terminal state."
              }
            },
            "additionalProperties": false
          },
          {
            "type": "object",
            "required": [
              "task",
              "input"
            ],
            "properties": {
              "task": {
                "type": "string",
                "enum": [
                  "trellis.generate"
                ]
              },
              "input": {
                "type": "object",
                "anyOf": [
                  {
                    "required": [
                      "sourceImageUrl"
                    ]
                  },
                  {
                    "required": [
                      "sourceImage"
                    ]
                  }
                ],
                "properties": {
                  "sourceImageUrl": {
                    "type": "string",
                    "format": "uri"
                  },
                  "sourceImage": {
                    "$ref": "#/components/schemas/MediaInlineImageSource"
                  },
                  "qualityPreset": {
                    "type": "string",
                    "enum": [
                      "performance",
                      "balanced",
                      "fidelity"
                    ],
                    "description": "Preset defaults tuned for speed, balanced quality, or fidelity."
                  },
                  "targetFaceCount": {
                    "type": "integer",
                    "minimum": 1000,
                    "maximum": 500000
                  },
                  "textureSize": {
                    "type": "integer",
                    "enum": [
                      512,
                      1024,
                      2048
                    ]
                  },
                  "textureResolution": {
                    "type": "integer",
                    "enum": [
                      512,
                      1024,
                      1536
                    ],
                    "description": "Texture bake resolution. 1536 requires textureSize=2048 and works best with maxViews<=5 and textureSteps<=16."
                  },
                  "maxViews": {
                    "type": "integer",
                    "minimum": 2,
                    "maximum": 6
                  },
                  "sparseStructureSteps": {
                    "type": "integer",
                    "minimum": 8,
                    "maximum": 20
                  },
                  "shapeSteps": {
                    "type": "integer",
                    "minimum": 8,
                    "maximum": 20
                  },
                  "textureSteps": {
                    "type": "integer",
                    "minimum": 8,
                    "maximum": 20
                  },
                  "meshResolution": {
                    "type": "integer",
                    "enum": [
                      128,
                      256,
                      512,
                      1024
                    ]
                  },
                  "removeBackground": {
                    "type": "boolean"
                  },
                  "padding": {
                    "type": "integer",
                    "minimum": 0,
                    "maximum": 64
                  },
                  "refinerResolution": {
                    "type": "integer",
                    "enum": [
                      512,
                      1024,
                      1536
                    ],
                    "description": "Optional low-poly refiner resolution. 1536 requires textureSize=2048."
                  },
                  "refinerDownsampling": {
                    "type": "integer",
                    "enum": [
                      16,
                      32,
                      64
                    ]
                  },
                  "remeshFillHoles": {
                    "type": "boolean"
                  },
                  "remeshFillHolesMaxPerimeter": {
                    "type": "number",
                    "minimum": 0.005,
                    "maximum": 0.2
                  },
                  "remeshRemoveFloaters": {
                    "type": "boolean"
                  },
                  "remeshRemoveInnerFaces": {
                    "type": "boolean"
                  },
                  "meshClusterConeHalfAngleRad": {
                    "type": "number",
                    "minimum": 35,
                    "maximum": 85
                  },
                  "postprocessPositionEpsilon": {
                    "type": "number",
                    "minimum": 0.000001,
                    "maximum": 0.001,
                    "description": "Optional normal-postprocess epsilon used in low-poly Trellis mesh postprocess."
                  },
                  "postprocessNormalCreaseDeg": {
                    "type": "number",
                    "minimum": 1,
                    "maximum": 180,
                    "description": "Optional normal crease angle used in low-poly Trellis mesh postprocess."
                  },
                  "seed": {
                    "type": "integer",
                    "minimum": 1,
                    "maximum": 2147483647
                  }
                },
                "additionalProperties": false
              },
              "idempotencyKey": {
                "type": "string",
                "minLength": 1,
                "maxLength": 200
              },
              "completionCallbackUrl": {
                "type": "string",
                "format": "uri",
                "description": "Optional terminal callback URL. Receives one job-level POST when the job reaches a terminal state."
              }
            },
            "additionalProperties": false
          }
        ]
      },
      "X402CreditPurchaseRequest": {
        "type": "object",
        "required": [
          "usdCents"
        ],
        "properties": {
          "usdCents": {
            "type": "integer",
            "minimum": 100,
            "maximum": 900719925474,
            "description": "Credit purchase amount in USD cents. Minimum is $1.00. Maximum is capped for integer-safe micros math."
          },
          "affiliateCode": {
            "type": "string",
            "minLength": 4,
            "maxLength": 32,
            "description": "Optional affiliate code to bind before settling the credit purchase."
          }
        },
        "additionalProperties": false
      },
      "StripeCheckoutRequest": {
        "type": "object",
        "required": [
          "packageCode"
        ],
        "properties": {
          "packageCode": {
            "type": "string",
            "minLength": 1,
            "description": "Package code from GET /api/v1/packages."
          },
          "successUrl": {
            "type": "string",
            "format": "uri",
            "description": "Optional success redirect URL override."
          },
          "cancelUrl": {
            "type": "string",
            "format": "uri",
            "description": "Optional cancel redirect URL override."
          },
          "email": {
            "type": "string",
            "format": "email",
            "description": "Deprecated. Ignored unless it matches the authenticated API key account email exactly."
          },
          "affiliateCode": {
            "type": "string",
            "minLength": 4,
            "maxLength": 32,
            "description": "Optional affiliate code to bind before checkout creation."
          }
        },
        "additionalProperties": false
      },
      "CryptoCheckoutRequest": {
        "type": "object",
        "required": [
          "packageCode"
        ],
        "properties": {
          "packageCode": {
            "type": "string",
            "minLength": 1,
            "description": "Package code from GET /api/v1/packages."
          },
          "redirectUrl": {
            "type": "string",
            "format": "uri",
            "description": "Optional hosted checkout return URL override."
          },
          "cancelUrl": {
            "type": "string",
            "format": "uri",
            "description": "Optional hosted checkout cancel URL override."
          },
          "email": {
            "type": "string",
            "format": "email",
            "description": "Deprecated. Ignored unless it matches the authenticated API key account email exactly."
          },
          "affiliateCode": {
            "type": "string",
            "minLength": 4,
            "maxLength": 32,
            "description": "Optional affiliate code to bind before checkout creation."
          }
        },
        "additionalProperties": false
      },
      "ClaimStripeRequest": {
        "type": "object",
        "required": [
          "sessionId"
        ],
        "properties": {
          "sessionId": {
            "type": "string",
            "minLength": 1,
            "description": "Stripe Checkout Session ID to settle."
          }
        },
        "additionalProperties": false
      },
      "ClaimCryptoRequest": {
        "type": "object",
        "required": [
          "chargeId"
        ],
        "properties": {
          "chargeId": {
            "type": "string",
            "minLength": 1,
            "description": "Coinbase Commerce charge ID to settle."
          }
        },
        "additionalProperties": false
      },
      "ClaimSettlementResponse": {
        "type": "object",
        "required": [
          "provider",
          "packageCode",
          "depositUsdCents",
          "currentBalanceUsdMicros"
        ],
        "properties": {
          "provider": {
            "type": "string",
            "enum": [
              "stripe",
              "coinbase"
            ]
          },
          "sessionId": {
            "type": "string",
            "nullable": true
          },
          "chargeId": {
            "type": "string",
            "nullable": true
          },
          "packageCode": {
            "type": "string"
          },
          "depositUsdCents": {
            "type": "integer"
          },
          "currentBalanceUsdMicros": {
            "type": "integer"
          }
        },
        "additionalProperties": false
      },
      "CreateKeyRequest": {
        "type": "object",
        "properties": {
          "label": {
            "type": "string",
            "minLength": 1,
            "maxLength": 64,
            "description": "Optional key label."
          },
          "idToken": {
            "type": "string",
            "minLength": 20,
            "description": "Optional Google ID token for first-key bootstrap when no API key is available."
          }
        },
        "additionalProperties": false
      },
      "GoogleAuthRequest": {
        "type": "object",
        "required": [
          "idToken"
        ],
        "properties": {
          "idToken": {
            "type": "string",
            "minLength": 20,
            "description": "Google ID token used to mint the first API key for the account."
          },
          "keyLabel": {
            "type": "string",
            "minLength": 1,
            "maxLength": 64,
            "description": "Optional label for the newly issued API key."
          }
        },
        "additionalProperties": false
      },
      "EmailAuthStartRequest": {
        "type": "object",
        "required": [
          "email"
        ],
        "properties": {
          "email": {
            "type": "string",
            "format": "email",
            "description": "Email address that should receive the one-time verification code."
          }
        },
        "additionalProperties": false
      },
      "EmailAuthVerifyRequest": {
        "type": "object",
        "required": [
          "email",
          "code"
        ],
        "properties": {
          "email": {
            "type": "string",
            "format": "email",
            "description": "Same email address used during POST /api/v1/auth/email/start."
          },
          "code": {
            "type": "string",
            "minLength": 6,
            "maxLength": 6,
            "description": "One-time verification code delivered to the email address."
          },
          "keyLabel": {
            "type": "string",
            "minLength": 1,
            "maxLength": 64,
            "description": "Optional label for the newly issued API key."
          }
        },
        "additionalProperties": false
      },
      "AffiliateValidateCodeRequest": {
        "type": "object",
        "required": [
          "code"
        ],
        "properties": {
          "code": {
            "type": "string",
            "minLength": 4,
            "maxLength": 32,
            "description": "Affiliate code to validate."
          }
        },
        "additionalProperties": false
      },
      "AffiliateCaptureRequest": {
        "type": "object",
        "required": [
          "code"
        ],
        "properties": {
          "code": {
            "type": "string",
            "minLength": 4,
            "maxLength": 32,
            "description": "Affiliate code to capture into a signed attribution token/cookie."
          }
        },
        "additionalProperties": false
      },
      "AffiliateApplyRequest": {
        "type": "object",
        "required": [
          "displayName",
          "contactEmail"
        ],
        "properties": {
          "displayName": {
            "type": "string",
            "minLength": 2,
            "maxLength": 120
          },
          "contactEmail": {
            "type": "string",
            "format": "email"
          },
          "countryCode": {
            "type": "string",
            "minLength": 2,
            "maxLength": 2,
            "description": "Optional ISO 3166-1 alpha-2 country code."
          },
          "payoutAddress": {
            "type": "string",
            "minLength": 3,
            "maxLength": 320,
            "description": "Optional payout handle/address required before requesting payout."
          },
          "termsVersion": {
            "type": "string",
            "minLength": 1,
            "maxLength": 64,
            "description": "Optional affiliate terms version accepted by the client."
          }
        },
        "additionalProperties": false
      },
      "AffiliateUpdateRequest": {
        "type": "object",
        "properties": {
          "displayName": {
            "type": "string",
            "minLength": 2,
            "maxLength": 120
          },
          "contactEmail": {
            "type": "string",
            "format": "email"
          },
          "countryCode": {
            "type": "string",
            "minLength": 2,
            "maxLength": 2,
            "description": "Optional ISO 3166-1 alpha-2 country code."
          },
          "payoutAddress": {
            "type": "string",
            "minLength": 3,
            "maxLength": 320,
            "description": "Optional payout handle/address required before requesting payout."
          }
        },
        "additionalProperties": false
      },
      "AffiliateBindCodeRequest": {
        "type": "object",
        "required": [
          "code"
        ],
        "properties": {
          "code": {
            "type": "string",
            "minLength": 4,
            "maxLength": 32,
            "description": "Affiliate code to bind to the authenticated account."
          },
          "captureToken": {
            "type": "string",
            "minLength": 24,
            "maxLength": 4096,
            "description": "Optional explicit capture token from POST /api/v1/affiliates/capture."
          }
        },
        "additionalProperties": false
      },
      "AffiliatePayoutRequestCreateRequest": {
        "type": "object",
        "properties": {
          "note": {
            "type": "string",
            "minLength": 1,
            "maxLength": 512,
            "description": "Optional operator note included with the payout request."
          }
        },
        "additionalProperties": false
      },
      "DeviceLinkStartRequest": {
        "type": "object",
        "properties": {
          "keyLabel": {
            "type": "string",
            "minLength": 1,
            "maxLength": 64,
            "description": "Optional label used when issuing the linked API key."
          }
        },
        "additionalProperties": false
      },
      "DeviceLinkApproveRequest": {
        "type": "object",
        "required": [
          "userCode"
        ],
        "properties": {
          "userCode": {
            "type": "string",
            "minLength": 4,
            "maxLength": 32,
            "description": "User code shown by device-link start flow (for example: ABCD-EFGH)."
          },
          "keyLabel": {
            "type": "string",
            "minLength": 1,
            "maxLength": 64,
            "description": "Optional label override for the linked API key."
          }
        },
        "additionalProperties": false
      },
      "DeviceLinkPollRequest": {
        "type": "object",
        "required": [
          "deviceCode"
        ],
        "properties": {
          "deviceCode": {
            "type": "string",
            "minLength": 20,
            "maxLength": 256,
            "description": "Opaque device code returned by POST /api/v1/device/link/start."
          }
        },
        "additionalProperties": false
      },
      "MediaInputAdjustment": {
        "type": "object",
        "required": [
          "field",
          "reason"
        ],
        "properties": {
          "field": {
            "type": "string"
          },
          "requested": {},
          "effective": {},
          "reason": {
            "type": "string"
          }
        },
        "additionalProperties": false
      },
      "MediaJobBilling": {
        "type": "object",
        "properties": {
          "usdChargedMicros": {
            "type": "integer",
            "nullable": true
          },
          "usdCharged": {
            "type": "string",
            "nullable": true
          },
          "pricingMeta": {
            "type": "object",
            "nullable": true,
            "additionalProperties": true
          },
          "stagedInputCount": {
            "type": "integer",
            "nullable": true
          }
        },
        "additionalProperties": false
      },
      "MediaJobSubmitResponse": {
        "type": "object",
        "properties": {
          "ok": {
            "type": "boolean"
          },
          "task": {
            "type": "string"
          },
          "externalJobId": {
            "type": "string"
          },
          "usdChargedMicros": {
            "type": "integer"
          },
          "usdCharged": {
            "type": "string"
          },
          "usdBalanceMicros": {
            "type": "integer"
          },
          "usdBalance": {
            "type": "string"
          },
          "pricingMeta": {
            "type": "object",
            "additionalProperties": true
          },
          "stagedInputCount": {
            "type": "integer"
          },
          "estimatedDurationSeconds": {
            "type": "number"
          },
          "durationEstimateMeta": {
            "type": "object",
            "additionalProperties": true
          },
          "effectiveInput": {
            "type": "object",
            "additionalProperties": true
          },
          "inputAdjustments": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/MediaInputAdjustment"
            }
          },
          "billing": {
            "$ref": "#/components/schemas/MediaJobBilling"
          },
          "result": {
            "type": "object",
            "additionalProperties": true
          }
        },
        "additionalProperties": true
      },
      "MediaJobStatusResponse": {
        "type": "object",
        "properties": {
          "ok": {
            "type": "boolean"
          },
          "task": {
            "type": "string",
            "nullable": true
          },
          "externalJobId": {
            "type": "string"
          },
          "status": {
            "type": "string"
          },
          "result": {
            "type": "object",
            "additionalProperties": true
          },
          "effectiveInput": {
            "type": "object",
            "additionalProperties": true
          },
          "inputAdjustments": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/MediaInputAdjustment"
            }
          },
          "estimatedDurationSeconds": {
            "type": "number",
            "nullable": true
          },
          "durationEstimateMeta": {
            "type": "object",
            "nullable": true,
            "additionalProperties": true
          },
          "billing": {
            "$ref": "#/components/schemas/MediaJobBilling"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "updatedAt": {
            "type": "string",
            "format": "date-time"
          },
          "durationMs": {
            "type": "integer",
            "nullable": true
          },
          "outputFiles": {
            "type": "array",
            "nullable": true,
            "items": {}
          },
          "outputUrl": {
            "type": "string",
            "nullable": true
          },
          "generatedImageIds": {
            "type": "object",
            "nullable": true,
            "additionalProperties": true
          },
          "expectedOutputUrls": {
            "type": "array",
            "items": {
              "type": "string",
              "format": "uri"
            },
            "description": "Expected output URLs inferred from submit-time output destinations."
          },
          "downloadableOutputUrls": {
            "type": "array",
            "items": {
              "type": "string",
              "format": "uri"
            },
            "description": "Downloadable output URLs. Guaranteed availability for 48 hours after completion; background cleanup targets 72 hours."
          }
        },
        "additionalProperties": true
      }
    }
  },
  "paths": {
    "/api/v1/health": {
      "get": {
        "tags": [
          "health"
        ],
        "summary": "Health check and release compatibility metadata",
        "responses": {
          "200": {
            "description": "API health payload with versioned skill compatibility information.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HealthResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/packages": {
      "get": {
        "tags": [
          "catalog"
        ],
        "summary": "List available credit packages"
      }
    },
    "/api/v1/affiliates/r": {
      "get": {
        "tags": [
          "affiliates"
        ],
        "summary": "Resolve affiliate referral redirect and capture attribution token",
        "parameters": [
          {
            "in": "query",
            "name": "code",
            "required": true,
            "schema": {
              "type": "string",
              "minLength": 4,
              "maxLength": 32
            },
            "description": "Affiliate code to resolve."
          }
        ]
      }
    },
    "/api/v1/affiliates/validate-code": {
      "post": {
        "tags": [
          "affiliates"
        ],
        "summary": "Validate affiliate code",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/AffiliateValidateCodeRequest"
              }
            }
          }
        }
      }
    },
    "/api/v1/affiliates/capture": {
      "post": {
        "tags": [
          "affiliates"
        ],
        "summary": "Capture/refresh affiliate attribution token",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/AffiliateCaptureRequest"
              }
            }
          }
        }
      }
    },
    "/api/v1/affiliates/me/apply": {
      "post": {
        "tags": [
          "affiliates"
        ],
        "summary": "Apply for affiliate account",
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/AffiliateApplyRequest"
              }
            }
          }
        }
      }
    },
    "/api/v1/affiliates/me": {
      "get": {
        "tags": [
          "affiliates"
        ],
        "summary": "Get affiliate profile",
        "security": [
          {
            "BearerAuth": []
          }
        ]
      },
      "patch": {
        "tags": [
          "affiliates"
        ],
        "summary": "Update affiliate profile",
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/AffiliateUpdateRequest"
              }
            }
          }
        }
      }
    },
    "/api/v1/affiliates/me/code": {
      "get": {
        "tags": [
          "affiliates"
        ],
        "summary": "Get or create the authenticated affiliate referral code",
        "security": [
          {
            "BearerAuth": []
          }
        ]
      }
    },
    "/api/v1/affiliates/me/dashboard": {
      "get": {
        "tags": [
          "affiliates"
        ],
        "summary": "Get affiliate dashboard metrics",
        "security": [
          {
            "BearerAuth": []
          }
        ]
      }
    },
    "/api/v1/affiliates/me/commissions": {
      "get": {
        "tags": [
          "affiliates"
        ],
        "summary": "List affiliate commissions",
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "parameters": [
          {
            "in": "query",
            "name": "limit",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 1
            },
            "description": "Optional page size. Defaults to 100."
          }
        ]
      }
    },
    "/api/v1/affiliates/me/payouts": {
      "get": {
        "tags": [
          "affiliates"
        ],
        "summary": "List affiliate payout history",
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "parameters": [
          {
            "in": "query",
            "name": "limit",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 1
            },
            "description": "Optional page size. Defaults to 20."
          }
        ]
      }
    },
    "/api/v1/affiliates/me/payout-requests": {
      "get": {
        "tags": [
          "affiliates"
        ],
        "summary": "List affiliate payout requests and eligibility state",
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "parameters": [
          {
            "in": "query",
            "name": "limit",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 1
            },
            "description": "Optional page size. Defaults to 20."
          }
        ]
      },
      "post": {
        "tags": [
          "affiliates"
        ],
        "summary": "Create affiliate payout request",
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/AffiliatePayoutRequestCreateRequest"
              }
            }
          }
        }
      }
    },
    "/api/v1/affiliates/me/bind-code": {
      "post": {
        "tags": [
          "affiliates"
        ],
        "summary": "Bind affiliate code to authenticated user",
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/AffiliateBindCodeRequest"
              }
            }
          }
        }
      }
    },
    "/api/v1/auth/google": {
      "post": {
        "tags": [
          "auth"
        ],
        "summary": "Exchange a Google ID token for a new API key",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/GoogleAuthRequest"
              }
            }
          }
        }
      }
    },
    "/api/v1/auth/browser/google": {
      "post": {
        "tags": [
          "auth"
        ],
        "summary": "Exchange a Google ID token for a browser session cookie",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/GoogleAuthRequest"
              }
            }
          }
        }
      }
    },
    "/api/v1/auth/email/start": {
      "post": {
        "tags": [
          "auth"
        ],
        "summary": "Start email one-time-code sign-in",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/EmailAuthStartRequest"
              }
            }
          }
        }
      }
    },
    "/api/v1/auth/email/verify": {
      "post": {
        "tags": [
          "auth"
        ],
        "summary": "Verify email one-time code and mint API key",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/EmailAuthVerifyRequest"
              }
            }
          }
        }
      }
    },
    "/api/v1/auth/browser/email/verify": {
      "post": {
        "tags": [
          "auth"
        ],
        "summary": "Verify email one-time code and issue a browser session cookie",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/EmailAuthVerifyRequest"
              }
            }
          }
        }
      }
    },
    "/api/v1/auth/browser/session": {
      "get": {
        "tags": [
          "auth"
        ],
        "summary": "Inspect the active browser session"
      },
      "delete": {
        "tags": [
          "auth"
        ],
        "summary": "Clear the active browser session"
      }
    },
    "/api/v1/device/link/start": {
      "post": {
        "tags": [
          "auth"
        ],
        "summary": "Start browser-assisted local skill linking",
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/DeviceLinkStartRequest"
              }
            }
          }
        }
      }
    },
    "/api/v1/device/link/request": {
      "get": {
        "tags": [
          "auth"
        ],
        "summary": "Get device-link request status by user code",
        "parameters": [
          {
            "in": "query",
            "name": "userCode",
            "required": true,
            "schema": {
              "type": "string",
              "minLength": 4
            },
            "description": "User code shown during device-link bootstrap."
          }
        ]
      }
    },
    "/api/v1/device/link/approve": {
      "post": {
        "tags": [
          "auth"
        ],
        "summary": "Approve a pending device-link request (API key required)",
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/DeviceLinkApproveRequest"
              }
            }
          }
        }
      }
    },
    "/api/v1/device/link/poll": {
      "post": {
        "tags": [
          "auth"
        ],
        "summary": "Poll a device-link request and retrieve one-time API key when approved",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/DeviceLinkPollRequest"
              }
            }
          }
        }
      }
    },
    "/api/v1/checkout/stripe": {
      "post": {
        "tags": [
          "checkout"
        ],
        "summary": "Create Stripe checkout (API key required)",
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/StripeCheckoutRequest"
              }
            }
          }
        }
      }
    },
    "/api/v1/checkout/crypto": {
      "post": {
        "tags": [
          "checkout"
        ],
        "summary": "Create crypto checkout (API key required)",
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CryptoCheckoutRequest"
              }
            }
          }
        }
      }
    },
    "/api/v1/claim/stripe": {
      "post": {
        "tags": [
          "claim"
        ],
        "summary": "Finalize Stripe checkout settlement (API key required)",
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ClaimStripeRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Stripe settlement finalized for the authenticated account.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ClaimSettlementResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/claim/crypto": {
      "post": {
        "tags": [
          "claim"
        ],
        "summary": "Finalize Coinbase checkout settlement (API key required)",
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ClaimCryptoRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Coinbase settlement finalized for the authenticated account.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ClaimSettlementResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/credits/purchase/x402": {
      "post": {
        "tags": [
          "credits"
        ],
        "summary": "Purchase prepaid $ credits using x402 (API key required)",
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/X402CreditPurchaseRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Credit purchase replay recognized (already applied)."
          },
          "201": {
            "description": "Credit purchase settled and applied."
          },
          "402": {
            "description": "x402 payment required or settlement rejected. Uses PAYMENT-REQUIRED / PAYMENT-RESPONSE headers."
          }
        }
      }
    },
    "/api/v1/deposit/x402": {
      "post": {
        "tags": [
          "credits"
        ],
        "deprecated": true,
        "summary": "Legacy alias for x402 prepaid $ credit purchase",
        "description": "Deprecated route alias. Use POST /api/v1/credits/purchase/x402 instead.",
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/X402CreditPurchaseRequest"
              }
            }
          }
        }
      }
    },
    "/api/v1/keys": {
      "get": {
        "tags": [
          "keys"
        ],
        "summary": "List API keys",
        "security": [
          {
            "BearerAuth": []
          }
        ]
      },
      "post": {
        "tags": [
          "keys"
        ],
        "summary": "Create API key (API key auth or Google ID token bootstrap)",
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateKeyRequest"
              }
            }
          }
        }
      }
    },
    "/api/v1/keys/revoke": {
      "post": {
        "tags": [
          "keys"
        ],
        "summary": "Revoke API key",
        "security": [
          {
            "BearerAuth": []
          }
        ]
      }
    },
    "/api/v1/balance": {
      "get": {
        "tags": [
          "balance"
        ],
        "summary": "Get USD balance",
        "security": [
          {
            "BearerAuth": []
          }
        ]
      }
    },
    "/api/v1/arcade/games": {
      "post": {
        "tags": [
          "arcade"
        ],
        "summary": "Create an arcade game record",
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "slug",
                  "title",
                  "shortDescription",
                  "description"
                ],
                "properties": {
                  "slug": {
                    "type": "string"
                  },
                  "title": {
                    "type": "string"
                  },
                  "shortDescription": {
                    "type": "string"
                  },
                  "description": {
                    "type": "string"
                  },
                  "tags": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/arcade/games/mine": {
      "get": {
        "tags": [
          "arcade"
        ],
        "summary": "List creator-owned arcade games and releases",
        "security": [
          {
            "BearerAuth": []
          }
        ]
      }
    },
    "/api/v1/arcade/games/detail": {
      "get": {
        "tags": [
          "arcade"
        ],
        "summary": "Load one arcade game detail record by slug and channel",
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "parameters": [
          {
            "in": "query",
            "name": "slug",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "in": "query",
            "name": "channel",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "dev",
                "live"
              ],
              "default": "live"
            }
          }
        ]
      }
    },
    "/api/v1/arcade/catalog": {
      "get": {
        "tags": [
          "arcade"
        ],
        "summary": "List accessible arcade catalog entries for one channel",
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "parameters": [
          {
            "in": "query",
            "name": "channel",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "dev",
                "live"
              ],
              "default": "live"
            }
          }
        ]
      }
    },
    "/api/v1/arcade/releases/upload": {
      "post": {
        "tags": [
          "arcade"
        ],
        "summary": "Upload a Godot web release bundle for an existing arcade game",
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "multipart/form-data": {
              "schema": {
                "type": "object",
                "required": [
                  "gameId",
                  "manifestJson",
                  "bundle"
                ],
                "properties": {
                  "gameId": {
                    "type": "string"
                  },
                  "manifestJson": {
                    "type": "string"
                  },
                  "bundle": {
                    "type": "string",
                    "format": "binary"
                  },
                  "coverImage": {
                    "type": "string",
                    "format": "binary"
                  }
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/arcade/releases/submit": {
      "patch": {
        "tags": [
          "arcade"
        ],
        "summary": "Submit a draft arcade release for manual review",
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "releaseId"
                ],
                "properties": {
                  "releaseId": {
                    "type": "string"
                  }
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/arcade/review/queue": {
      "get": {
        "tags": [
          "arcade"
        ],
        "summary": "List arcade releases awaiting admin review",
        "security": [
          {
            "BearerAuth": []
          }
        ]
      }
    },
    "/api/v1/arcade/review/release": {
      "patch": {
        "tags": [
          "arcade"
        ],
        "summary": "Advance, approve, reject, or assign an arcade release to dev/live",
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "releaseId",
                  "action"
                ],
                "properties": {
                  "releaseId": {
                    "type": "string"
                  },
                  "action": {
                    "type": "string",
                    "enum": [
                      "send_to_review",
                      "approve",
                      "reject",
                      "publish"
                    ]
                  },
                  "notes": {
                    "type": "string"
                  },
                  "channel": {
                    "type": "string",
                    "enum": [
                      "dev",
                      "live"
                    ]
                  },
                  "visibility": {
                    "type": "string",
                    "enum": [
                      "hidden",
                      "owner_only",
                      "public"
                    ]
                  }
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/arcade/launch-sessions": {
      "post": {
        "tags": [
          "arcade"
        ],
        "summary": "Create a signed arcade launch session for one channel-assigned release",
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "slug",
                  "idempotencyKey"
                ],
                "properties": {
                  "slug": {
                    "type": "string"
                  },
                  "idempotencyKey": {
                    "type": "string"
                  },
                  "channel": {
                    "type": "string",
                    "enum": [
                      "dev",
                      "live"
                    ],
                    "default": "live"
                  }
                }
              }
            }
          }
        }
      },
      "patch": {
        "tags": [
          "arcade"
        ],
        "summary": "Update arcade launch-session telemetry state",
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "sessionId",
                  "event"
                ],
                "properties": {
                  "sessionId": {
                    "type": "string"
                  },
                  "event": {
                    "type": "string",
                    "enum": [
                      "launched",
                      "heartbeat",
                      "end",
                      "failed_bootstrap"
                    ]
                  },
                  "failureReason": {
                    "type": "string"
                  }
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/studio/snapshot": {
      "get": {
        "tags": [
          "studio"
        ],
        "summary": "Get Studio workspace snapshot",
        "description": "Returns the authenticated Studio workspace snapshot, including projects, assets, workflow runs, approvals, templates, publishing state, and the active thread.",
        "security": [
          {
            "BearerAuth": []
          }
        ]
      }
    },
    "/api/v1/studio/projects/assets": {
      "get": {
        "tags": [
          "studio"
        ],
        "summary": "List Studio project assets",
        "description": "Returns the paginated Studio browser asset list for a project, including active or recycling-bin scopes and optional search filtering.",
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "parameters": [
          {
            "in": "query",
            "name": "projectId",
            "required": true,
            "schema": {
              "type": "string",
              "minLength": 1
            }
          },
          {
            "in": "query",
            "name": "scope",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "active",
                "recycling"
              ]
            }
          },
          {
            "in": "query",
            "name": "searchQuery",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "in": "query",
            "name": "offset",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 0
            }
          },
          {
            "in": "query",
            "name": "limit",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 1
            }
          }
        ]
      }
    },
    "/api/v1/studio/projects": {
      "post": {
        "tags": [
          "studio"
        ],
        "summary": "Create Studio project",
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "title"
                ],
                "properties": {
                  "title": {
                    "type": "string",
                    "minLength": 2,
                    "maxLength": 120
                  },
                  "description": {
                    "type": "string",
                    "maxLength": 4000
                  }
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/studio/projects/update": {
      "patch": {
        "tags": [
          "studio"
        ],
        "summary": "Update Studio project",
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "projectId"
                ],
                "properties": {
                  "projectId": {
                    "type": "string",
                    "minLength": 1
                  },
                  "title": {
                    "type": "string",
                    "minLength": 2,
                    "maxLength": 120
                  },
                  "description": {
                    "type": "string",
                    "maxLength": 4000
                  }
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/studio/settings": {
      "patch": {
        "tags": [
          "studio"
        ],
        "summary": "Update Studio settings",
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "defaultAgentModel",
                  "defaultReasoningLevel"
                ],
                "properties": {
                  "userDisplayName": {
                    "type": "string",
                    "maxLength": 80
                  },
                  "assistantDisplayName": {
                    "type": "string",
                    "maxLength": 80
                  },
                  "conversationStarterInstructions": {
                    "type": "string",
                    "maxLength": 2000
                  },
                  "defaultAgentModel": {
                    "type": "string",
                    "enum": [
                      "gpt-5.4-nano",
                      "gpt-5.4-mini",
                      "gpt-5.4",
                      "deepseek-chat",
                      "minimax/minimax-m2.7",
                      "zai-org/GLM-5",
                      "moonshotai/Kimi-K2.5"
                    ]
                  },
                  "defaultReasoningLevel": {
                    "type": "string",
                    "enum": [
                      "default",
                      "low",
                      "medium",
                      "high",
                      "xhigh"
                    ]
                  }
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/studio/threads": {
      "post": {
        "tags": [
          "studio"
        ],
        "summary": "Create Studio conversation",
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "projectId"
                ],
                "properties": {
                  "projectId": {
                    "type": "string",
                    "minLength": 1
                  },
                  "title": {
                    "type": "string",
                    "minLength": 2,
                    "maxLength": 120
                  },
                  "agentModel": {
                    "type": "string",
                    "enum": [
                      "gpt-5.4-nano",
                      "gpt-5.4-mini",
                      "gpt-5.4"
                    ]
                  },
                  "reasoningLevel": {
                    "type": "string",
                    "enum": [
                      "default",
                      "low",
                      "medium",
                      "high",
                      "xhigh"
                    ]
                  }
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/studio/threads/select": {
      "post": {
        "tags": [
          "studio"
        ],
        "summary": "Select Studio conversation",
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "threadId"
                ],
                "properties": {
                  "threadId": {
                    "type": "string",
                    "minLength": 1
                  }
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/studio/threads/detail": {
      "get": {
        "tags": [
          "studio"
        ],
        "summary": "Load Studio conversation detail",
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "parameters": [
          {
            "in": "query",
            "name": "threadId",
            "required": true,
            "schema": {
              "type": "string",
              "minLength": 1
            }
          }
        ]
      }
    },
    "/api/v1/studio/threads/update": {
      "patch": {
        "tags": [
          "studio"
        ],
        "summary": "Rename Studio conversation",
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "threadId",
                  "title"
                ],
                "properties": {
                  "threadId": {
                    "type": "string",
                    "minLength": 1
                  },
                  "title": {
                    "type": "string",
                    "minLength": 2,
                    "maxLength": 120
                  }
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/studio/assets/upload": {
      "post": {
        "tags": [
          "studio"
        ],
        "summary": "Upload Studio asset",
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "parameters": [
          {
            "in": "query",
            "name": "projectId",
            "required": true,
            "schema": {
              "type": "string",
              "minLength": 1
            }
          },
          {
            "in": "query",
            "name": "filename",
            "required": true,
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 240
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/octet-stream": {
              "schema": {
                "type": "string",
                "format": "binary"
              }
            }
          }
        }
      }
    },
    "/api/v1/studio/assets/metadata": {
      "patch": {
        "tags": [
          "studio"
        ],
        "summary": "Update Studio asset metadata",
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "assetId",
                  "userMetadata"
                ],
                "properties": {
                  "assetId": {
                    "type": "string",
                    "minLength": 1
                  },
                  "userMetadata": {
                    "type": "object"
                  }
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/studio/assets/text": {
      "post": {
        "tags": [
          "studio"
        ],
        "summary": "Create Studio text asset",
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "projectId",
                  "title"
                ],
                "properties": {
                  "projectId": {
                    "type": "string",
                    "minLength": 1
                  },
                  "title": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 120
                  },
                  "content": {
                    "type": "string",
                    "maxLength": 524288
                  },
                  "mimeType": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 120
                  }
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/studio/assets/text/document": {
      "get": {
        "tags": [
          "studio"
        ],
        "summary": "Get Studio text document",
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "parameters": [
          {
            "in": "query",
            "name": "assetId",
            "required": true,
            "schema": {
              "type": "string",
              "minLength": 1
            }
          }
        ]
      },
      "patch": {
        "tags": [
          "studio"
        ],
        "summary": "Update Studio text document",
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "assetId",
                  "content"
                ],
                "properties": {
                  "assetId": {
                    "type": "string",
                    "minLength": 1
                  },
                  "title": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 120
                  },
                  "content": {
                    "type": "string",
                    "maxLength": 524288
                  }
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/studio/assets/storyboards": {
      "post": {
        "tags": [
          "studio"
        ],
        "summary": "Create Studio storyboard",
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "projectId",
                  "title"
                ],
                "properties": {
                  "projectId": {
                    "type": "string",
                    "minLength": 1
                  },
                  "title": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 120
                  },
                  "storyboard": {
                    "type": "object",
                    "description": "Optional version 2 video storyboard document payload."
                  }
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/studio/assets/storyboards/document": {
      "get": {
        "tags": [
          "studio"
        ],
        "summary": "Get Studio storyboard document",
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "parameters": [
          {
            "in": "query",
            "name": "assetId",
            "required": true,
            "schema": {
              "type": "string",
              "minLength": 1
            }
          }
        ]
      },
      "patch": {
        "tags": [
          "studio"
        ],
        "summary": "Update Studio storyboard document",
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "assetId",
                  "storyboard"
                ],
                "properties": {
                  "assetId": {
                    "type": "string",
                    "minLength": 1
                  },
                  "title": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 120
                  },
                  "storyboard": {
                    "type": "object",
                    "description": "Version 2 video storyboard document payload."
                  }
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/studio/assets/storyboards/import": {
      "post": {
        "tags": [
          "studio"
        ],
        "summary": "Import Studio storyboard from legacy asset",
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "projectId",
                  "sourceAssetId"
                ],
                "properties": {
                  "projectId": {
                    "type": "string",
                    "minLength": 1
                  },
                  "sourceAssetId": {
                    "type": "string",
                    "minLength": 1
                  },
                  "title": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 120
                  }
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/studio/assets/storyboards/export-markdown": {
      "get": {
        "tags": [
          "studio"
        ],
        "summary": "Export Studio storyboard as markdown",
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "parameters": [
          {
            "in": "query",
            "name": "assetId",
            "required": true,
            "schema": {
              "type": "string",
              "minLength": 1
            }
          }
        ]
      }
    },
    "/api/v1/studio/agent/messages": {
      "post": {
        "tags": [
          "studio"
        ],
        "summary": "Send Studio agent prompt",
        "description": "Runs a Studio agent prompt after the paid-job approval preflight has already been satisfied. Clients should prepare first and only send directly when the prepare step returns execute_now.",
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "projectId",
                  "prompt"
                ],
                "properties": {
                  "projectId": {
                    "type": "string",
                    "minLength": 1
                  },
                  "prompt": {
                    "type": "string",
                    "minLength": 2,
                    "maxLength": 12000
                  },
                  "agentModel": {
                    "type": "string",
                    "enum": [
                      "gpt-5.4-nano",
                      "gpt-5.4-mini",
                      "gpt-5.4"
                    ]
                  },
                  "reasoningLevel": {
                    "type": "string",
                    "enum": [
                      "default",
                      "low",
                      "medium",
                      "high",
                      "xhigh"
                    ]
                  }
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/studio/agent/messages/prepare": {
      "post": {
        "tags": [
          "studio"
        ],
        "summary": "Prepare Studio agent prompt",
        "description": "Prepares the Studio agent prompt without executing paid jobs. Returns either execute_now for zero-cost or pre-approved runs, or an approval-required payload containing the persisted paid job bundle and estimated cost details.",
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "projectId",
                  "prompt"
                ],
                "properties": {
                  "projectId": {
                    "type": "string",
                    "minLength": 1
                  },
                  "prompt": {
                    "type": "string",
                    "minLength": 2,
                    "maxLength": 12000
                  },
                  "agentModel": {
                    "type": "string",
                    "enum": [
                      "gpt-5.4-nano",
                      "gpt-5.4-mini",
                      "gpt-5.4"
                    ]
                  },
                  "reasoningLevel": {
                    "type": "string",
                    "enum": [
                      "default",
                      "low",
                      "medium",
                      "high",
                      "xhigh"
                    ]
                  }
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/studio/agent/approval-plans/execute": {
      "post": {
        "tags": [
          "studio"
        ],
        "summary": "Execute approved Studio plan",
        "description": "Marks a prepared Studio approval plan as approved and executes the stored normalized paid job bundle without replanning.",
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "approvalPlanId"
                ],
                "properties": {
                  "approvalPlanId": {
                    "type": "string",
                    "minLength": 1
                  }
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/studio/agent/requests": {
      "get": {
        "tags": [
          "studio"
        ],
        "summary": "Get Studio agent request state",
        "description": "Returns the latest persisted status for an asynchronous Studio agent request, along with any incremental assistant text and tool-call deltas since the supplied offsets.",
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "parameters": [
          {
            "in": "query",
            "name": "requestId",
            "required": true,
            "schema": {
              "type": "string",
              "minLength": 1
            }
          },
          {
            "in": "query",
            "name": "assistantOffset",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 0
            }
          },
          {
            "in": "query",
            "name": "toolCallOffset",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 0
            }
          }
        ]
      }
    },
    "/api/v1/credits/balance": {
      "get": {
        "tags": [
          "credits"
        ],
        "deprecated": true,
        "summary": "Deprecated credits balance route",
        "description": "Deprecated route. Always returns HTTP 410 and instructs clients to use GET /api/v1/balance."
      }
    },
    "/api/v1/credits/consume": {
      "post": {
        "tags": [
          "credits"
        ],
        "deprecated": true,
        "summary": "Deprecated credits consume route",
        "description": "Deprecated route. Always returns HTTP 410 and instructs clients to use POST /api/v1/media/jobs instead."
      }
    },
    "/api/v1/media/jobs": {
      "get": {
        "tags": [
          "media"
        ],
        "summary": "Get media job status and output URLs",
        "description": "Download outputs within 48 hours of completion. CDN cleanup runs after 72 hours, so links may work slightly longer but are not guaranteed after 48 hours.",
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "parameters": [
          {
            "in": "query",
            "name": "jobId",
            "required": true,
            "schema": {
              "type": "string",
              "minLength": 1
            },
            "description": "External media job id returned by POST /api/v1/media/jobs."
          },
          {
            "in": "query",
            "name": "includeDetails",
            "required": false,
            "schema": {
              "type": "boolean"
            },
            "description": "When true, includes sanitized upstream result payload, effectiveInput, and inputAdjustments for debugging."
          }
        ],
        "responses": {
          "200": {
            "description": "Media job status payload.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MediaJobStatusResponse"
                }
              }
            }
          }
        }
      },
      "post": {
        "tags": [
          "media"
        ],
        "summary": "Submit media job",
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/MediaJobRequest"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Media job accepted and queued.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MediaJobSubmitResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/webhooks/stripe": {
      "post": {
        "tags": [
          "webhooks"
        ],
        "summary": "Stripe webhook"
      }
    },
    "/api/v1/webhooks/crypto": {
      "post": {
        "tags": [
          "webhooks"
        ],
        "summary": "Coinbase webhook"
      }
    }
  }
}
