{
  "openapi": "3.0.3",
  "info": {
    "title": "Audivra API",
    "version": "1.0.0",
    "description": "API-first voice and digital human infrastructure — text-to-speech, lip-synced video, voice cloning, and conversational agents. Import this spec into Postman, Insomnia, or OpenAPI codegen tools.",
    "contact": {
      "name": "Audivra Docs",
      "url": "http://127.0.0.1:3000/docs"
    }
  },
  "servers": [
    {
      "url": "http://127.0.0.1:3000",
      "description": "Audivra API"
    }
  ],
  "tags": [
    {
      "name": "Speech to text",
      "description": "Transcribe uploaded audio or a public audio URL"
    },
    {
      "name": "Music",
      "description": "Score beds billed per second from the prepaid pool"
    },
    {
      "name": "Sound effects",
      "description": "Short cues billed per clip"
    },
    {
      "name": "Dubbing",
      "description": "STT, translate, TTS, and lip-sync as an async job"
    },
    {
      "name": "Generate",
      "description": "Unified TTS, LLM, lip-sync, and async video pipeline"
    },
    {
      "name": "Assets",
      "description": "Reusable video, audio, and image library"
    },
    {
      "name": "Voices",
      "description": "Preset voices and catalog metadata"
    },
    {
      "name": "Voice cloning",
      "description": "Instant and professional custom voices from audio samples (paid plans)"
    },
    {
      "name": "Voice design",
      "description": "Prompt-based custom voices (paid plans)"
    },
    {
      "name": "Voice remix",
      "description": "Natural-language remix of owned clones"
    },
    {
      "name": "Marketplace",
      "description": "Community voice listings, licensing, and previews"
    },
    {
      "name": "Avatars & jobs",
      "description": "Talking-head video jobs, polling, and SSE"
    },
    {
      "name": "Agents",
      "description": "Turn-based conversational voice agents"
    },
    {
      "name": "Billing",
      "description": "Plan checkout — Stripe and Global South rails"
    },
    {
      "name": "Webhooks",
      "description": "Inbound payment provider webhooks"
    },
    {
      "name": "Dashboard",
      "description": "Session-authenticated dashboard helpers"
    }
  ],
  "paths": {
    "/api/v1/tts": {
      "post": {
        "tags": [
          "Text to speech"
        ],
        "operationId": "createSpeech",
        "summary": "Create speech",
        "description": "Returns audio/wav. Meters len(text) against plan character quota.",
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/TtsRequest"
              },
              "example": {
                "text": "Hello from Audivra",
                "voice_id": "aurora",
                "model": "kokoro-82m"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "WAV audio",
            "content": {
              "audio/wav": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              }
            },
            "headers": {
              "X-Characters": {
                "schema": {
                  "type": "integer"
                }
              },
              "X-Model": {
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized — missing or invalid API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "402": {
            "description": "Payment required — quota or plan limit exceeded",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Conflict — e.g. voice clone still training or video not ready",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "502": {
            "description": "Bad gateway — inference or worker unavailable",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/tts/stream": {
      "post": {
        "tags": [
          "Text to speech"
        ],
        "operationId": "streamSpeech",
        "summary": "Stream speech",
        "description": "Chunked Opus/AAC/WAV streaming optimized for low-bandwidth mobile networks.",
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/TtsStreamRequest"
              },
              "example": {
                "text": "Sentence one.",
                "voice_id": "zuri-sw",
                "format": "opus"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Chunked audio stream",
            "content": {
              "audio/opus": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              },
              "audio/aac": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              },
              "audio/wav": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized — missing or invalid API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "402": {
            "description": "Payment required — quota or plan limit exceeded",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Conflict — e.g. voice clone still training or video not ready",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/stt": {
      "get": {
        "tags": [
          "Speech to text"
        ],
        "operationId": "listSttLanguages",
        "summary": "STT languages and caps",
        "responses": {
          "200": {
            "description": "Language catalog",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SttCatalog"
                }
              }
            }
          }
        }
      },
      "post": {
        "tags": [
          "Speech to text"
        ],
        "operationId": "createTranscription",
        "summary": "Transcribe speech",
        "description": "Multipart audio or JSON audio_url (SSRF-checked, no redirects). Meters STT seconds. Max 180s / 15 MB.",
        "security": [
          {
            "BearerAuth": []
          },
          {
            "SessionAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "multipart/form-data": {
              "schema": {
                "$ref": "#/components/schemas/SttUpload"
              }
            },
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SttJsonRequest"
              },
              "example": {
                "audio_url": "https://cdn.example.com/clip.wav",
                "language": "sw"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Transcript",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SttResponse"
                }
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized — missing or invalid API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "402": {
            "description": "Payment required — quota or plan limit exceeded",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Unprocessable — no speech detected",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Service unavailable — STT engine or optional worker not installed",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/music": {
      "post": {
        "tags": [
          "Music"
        ],
        "operationId": "createMusicBed",
        "summary": "Create score bed",
        "description": "JSON prompt + seconds (2–20). Meters music seconds. Returns audio/wav.",
        "security": [
          {
            "BearerAuth": []
          },
          {
            "SessionAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/MusicRequest"
              },
              "example": {
                "prompt": "soft kora under a news open",
                "seconds": 8
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "WAV score bed",
            "content": {
              "audio/wav": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized — missing or invalid API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "402": {
            "description": "Payment required — quota or plan limit exceeded",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/sfx": {
      "post": {
        "tags": [
          "Sound effects"
        ],
        "operationId": "createSoundEffect",
        "summary": "Create sound cue",
        "description": "JSON prompt. Meters one SFX clip. Returns audio/wav.",
        "security": [
          {
            "BearerAuth": []
          },
          {
            "SessionAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SfxRequest"
              },
              "example": {
                "prompt": "soft whoosh into a studio sting"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "WAV cue",
            "content": {
              "audio/wav": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized — missing or invalid API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "402": {
            "description": "Payment required — quota or plan limit exceeded",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/dub": {
      "post": {
        "tags": [
          "Dubbing"
        ],
        "operationId": "createDubJob",
        "summary": "Create dubbing job",
        "description": "Transcribe (or use script), translate, synthesize, lip-sync. Returns 202 + job_id. Poll GET /api/v1/jobs/{id}.",
        "security": [
          {
            "BearerAuth": []
          },
          {
            "SessionAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "multipart/form-data": {
              "schema": {
                "$ref": "#/components/schemas/DubUpload"
              }
            }
          }
        },
        "responses": {
          "202": {
            "description": "Dub job queued",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DubJobCreated"
                }
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized — missing or invalid API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "402": {
            "description": "Payment required — quota or plan limit exceeded",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Conflict — e.g. voice clone still training or video not ready",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Service unavailable — STT engine or optional worker not installed",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/generate": {
      "post": {
        "tags": [
          "Generate"
        ],
        "operationId": "unifiedGenerate",
        "summary": "Unified generate",
        "description": "Routes to local_worker (sync TTS/LLM) or gpu_cluster (async video). Returns 200 for fast-path sync or 202 with job_id for heavy jobs.",
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/GenerateRequest"
              },
              "example": {
                "text": "Habari from Audivra",
                "voice_id": "zuri-sw",
                "avatar_id": "studio-host",
                "taskType": "unified"
              }
            },
            "multipart/form-data": {
              "schema": {
                "type": "object",
                "properties": {
                  "video": {
                    "type": "string",
                    "format": "binary"
                  },
                  "audio": {
                    "type": "string",
                    "format": "binary"
                  },
                  "sync_mode": {
                    "type": "string"
                  },
                  "video_url": {
                    "type": "string"
                  },
                  "audio_url": {
                    "type": "string"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Sync fast-path result",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GenerateSyncResponse"
                }
              }
            }
          },
          "202": {
            "description": "Async job accepted",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GenerateAsyncResponse"
                }
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized — missing or invalid API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "402": {
            "description": "Payment required — quota or plan limit exceeded",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Conflict — e.g. voice clone still training or video not ready",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "502": {
            "description": "Bad gateway — inference or worker unavailable",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/generate/batch": {
      "post": {
        "tags": [
          "Generate"
        ],
        "operationId": "batchGenerate",
        "summary": "Batch generate (paid)",
        "description": "Queue many talking-head jobs. Paid plans only. Items are enqueued sequentially; they do not run 500 GPU renders in parallel.",
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/BatchGenerateRequest"
              },
              "example": {
                "items": [
                  {
                    "text": "Hello from Audivra",
                    "voice_id": "aurora"
                  }
                ]
              }
            }
          }
        },
        "responses": {
          "202": {
            "description": "Jobs accepted",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/BatchGenerateResponse"
                }
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized — missing or invalid API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "402": {
            "description": "Payment required — quota or plan limit exceeded",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden — paid plan required or batch cap exceeded",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Conflict — e.g. voice clone still training or video not ready",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Too many requests — rate limit exceeded (Retry-After: 60)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/estimate": {
      "post": {
        "tags": [
          "Generate"
        ],
        "operationId": "estimateUsage",
        "summary": "Estimate credits",
        "description": "Preview credits, duration, and plan caps without spending the wallet.",
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/EstimateRequest"
              },
              "example": {
                "kind": "video",
                "text": "Studio intro"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Estimate",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/EstimateResponse"
                }
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized — missing or invalid API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/generate/batch/{id}": {
      "get": {
        "tags": [
          "Generate"
        ],
        "operationId": "getGenerateBatch",
        "summary": "Get batch",
        "description": "Poll batch metrics and child jobs.",
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Batch status"
          },
          "401": {
            "description": "Unauthorized — missing or invalid API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/assets": {
      "get": {
        "tags": [
          "Assets"
        ],
        "operationId": "listAssets",
        "summary": "List assets",
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "Asset list"
          }
        }
      },
      "post": {
        "tags": [
          "Assets"
        ],
        "operationId": "createAsset",
        "summary": "Create asset",
        "description": "Multipart file or JSON url.",
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "responses": {
          "201": {
            "description": "Created"
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized — missing or invalid API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/assets/{id}": {
      "get": {
        "tags": [
          "Assets"
        ],
        "operationId": "getAsset",
        "summary": "Get asset",
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Asset"
          },
          "401": {
            "description": "Unauthorized — missing or invalid API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "patch": {
        "tags": [
          "Assets"
        ],
        "operationId": "updateAsset",
        "summary": "Rename asset",
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Asset"
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized — missing or invalid API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "delete": {
        "tags": [
          "Assets"
        ],
        "operationId": "deleteAsset",
        "summary": "Delete asset",
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Deleted"
          },
          "401": {
            "description": "Unauthorized — missing or invalid API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/assets/{id}/file": {
      "get": {
        "tags": [
          "Assets"
        ],
        "operationId": "downloadAsset",
        "summary": "Download asset bytes",
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Binary media"
          },
          "401": {
            "description": "Unauthorized — missing or invalid API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/changelog": {
      "get": {
        "tags": [
          "Dashboard"
        ],
        "operationId": "getApiChangelog",
        "summary": "API changelog & versioning policy",
        "description": "Public release history, v1 stability promise, and current deployment mode.",
        "responses": {
          "200": {
            "description": "Changelog",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "api_version": {
                      "type": "string",
                      "example": "v1"
                    },
                    "url_prefix": {
                      "type": "string",
                      "example": "/api/v1"
                    },
                    "openapi_version": {
                      "type": "string",
                      "example": "1.0.0"
                    },
                    "deployment_mode": {
                      "type": "string",
                      "enum": [
                        "cloud",
                        "private",
                        "air_gapped"
                      ]
                    },
                    "releases": {
                      "type": "array",
                      "items": {
                        "type": "object"
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/voices": {
      "get": {
        "tags": [
          "Voices"
        ],
        "operationId": "listVoices",
        "summary": "List voices",
        "description": "Preset voices, TTS models, and ready clones for the authenticated user.",
        "security": [
          {
            "BearerAuth": []
          },
          {}
        ],
        "responses": {
          "200": {
            "description": "Voice catalog",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/VoiceCatalog"
                }
              }
            }
          }
        }
      }
    },
    "/api/voices/clone": {
      "get": {
        "tags": [
          "Voice cloning"
        ],
        "operationId": "listVoiceClones",
        "summary": "List voice clones",
        "security": [
          {
            "BearerAuth": []
          },
          {
            "SessionAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "Clone list",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/VoiceCloneList"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized — missing or invalid API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "post": {
        "tags": [
          "Voice cloning"
        ],
        "operationId": "createVoiceClone",
        "summary": "Create voice clone",
        "description": "Multipart upload. Instant: 1–5 WAV/MP3 samples (5–10s). Professional (Creator+): 5–25 samples, 2–30 minutes. Optional webhook_url for clone.ready / clone.failed.",
        "security": [
          {
            "BearerAuth": []
          },
          {
            "SessionAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "multipart/form-data": {
              "schema": {
                "$ref": "#/components/schemas/VoiceCloneUpload"
              }
            }
          }
        },
        "responses": {
          "202": {
            "description": "Clone queued",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/VoiceCloneCreated"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized — missing or invalid API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "402": {
            "description": "Payment required — quota or plan limit exceeded",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/voices/clone/{id}": {
      "patch": {
        "tags": [
          "Voice cloning"
        ],
        "operationId": "renameVoiceClone",
        "summary": "Rename voice clone",
        "description": "Updates the display name. voice_id stays the same.",
        "security": [
          {
            "BearerAuth": []
          },
          {
            "SessionAuth": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/VoiceCloneRename"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Clone renamed",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/VoiceCloneRenamed"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized — missing or invalid API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "delete": {
        "tags": [
          "Voice cloning"
        ],
        "operationId": "deleteVoiceClone",
        "summary": "Delete voice clone",
        "description": "Removes clone artifacts and frees a custom voice slot.",
        "security": [
          {
            "BearerAuth": []
          },
          {
            "SessionAuth": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Clone deleted",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/VoiceCloneDeleted"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized — missing or invalid API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/voices/clone/{id}/publish": {
      "post": {
        "tags": [
          "Marketplace"
        ],
        "operationId": "publishVoiceClone",
        "summary": "Publish clone to marketplace",
        "description": "List a ready clone you own. Requires consent attestation.",
        "security": [
          {
            "BearerAuth": []
          },
          {
            "SessionAuth": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/VoiceListingPublish"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Listing published",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/VoiceListingPublished"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized — missing or invalid API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "402": {
            "description": "Payment required — quota or plan limit exceeded",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "delete": {
        "tags": [
          "Marketplace"
        ],
        "operationId": "unlistVoiceClone",
        "summary": "Unlist marketplace listing",
        "security": [
          {
            "BearerAuth": []
          },
          {
            "SessionAuth": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Listing unlisted",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/VoiceListingPublished"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized — missing or invalid API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/voices/{id}/remix": {
      "post": {
        "tags": [
          "Voice remix"
        ],
        "operationId": "remixVoice",
        "summary": "Remix an owned clone",
        "description": "Creates a new clone from a ready voice you own using a natural-language prompt.",
        "security": [
          {
            "BearerAuth": []
          },
          {
            "SessionAuth": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/VoiceRemixRequest"
              }
            }
          }
        },
        "responses": {
          "202": {
            "description": "Remix queued",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/VoiceRemixCreated"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized — missing or invalid API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "402": {
            "description": "Payment required — quota or plan limit exceeded",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Conflict — e.g. voice clone still training or video not ready",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/voices/community": {
      "get": {
        "tags": [
          "Marketplace"
        ],
        "operationId": "listCommunityVoices",
        "summary": "Browse community marketplace",
        "security": [
          {
            "BearerAuth": []
          },
          {
            "SessionAuth": []
          }
        ],
        "parameters": [
          {
            "name": "query",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "language",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "tag",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "sort",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "featured",
                "popular",
                "recent"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Published listings",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CommunityVoiceList"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized — missing or invalid API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/voices/community/{id}": {
      "get": {
        "tags": [
          "Marketplace"
        ],
        "operationId": "getCommunityVoice",
        "summary": "Get community listing",
        "security": [
          {
            "BearerAuth": []
          },
          {
            "SessionAuth": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Listing",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CommunityVoice"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized — missing or invalid API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "post": {
        "tags": [
          "Marketplace"
        ],
        "operationId": "acquireCommunityVoice",
        "summary": "License a community voice",
        "description": "Adds a usage grant. Pass the listing id as voice_id in TTS. May include a per-use credit fee.",
        "security": [
          {
            "BearerAuth": []
          },
          {
            "SessionAuth": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Licensed",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CommunityVoiceAcquired"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized — missing or invalid API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/voices/community/{id}/reviews": {
      "get": {
        "tags": [
          "Marketplace"
        ],
        "operationId": "listCommunityReviews",
        "summary": "List listing reviews",
        "security": [
          {
            "BearerAuth": []
          },
          {
            "SessionAuth": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Reviews",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CommunityReviewList"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized — missing or invalid API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "post": {
        "tags": [
          "Marketplace"
        ],
        "operationId": "reviewCommunityVoice",
        "summary": "Rate a licensed community voice",
        "description": "One rating per licensed user. Updates featured ranking.",
        "security": [
          {
            "BearerAuth": []
          },
          {
            "SessionAuth": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CommunityReviewCreate"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Review saved",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CommunityReviewSaved"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized — missing or invalid API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/voices/community/{id}/preview": {
      "get": {
        "tags": [
          "Marketplace"
        ],
        "operationId": "previewCommunityVoice",
        "summary": "Preview community listing audio",
        "security": [
          {
            "BearerAuth": []
          },
          {
            "SessionAuth": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "WAV preview",
            "content": {
              "audio/wav": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized — missing or invalid API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/voices/design": {
      "get": {
        "tags": [
          "Voice design"
        ],
        "operationId": "listVoiceDesigns",
        "summary": "List voice designs",
        "security": [
          {
            "BearerAuth": []
          },
          {
            "SessionAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "Design list",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/VoiceDesignList"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized — missing or invalid API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "post": {
        "tags": [
          "Voice design"
        ],
        "operationId": "createVoiceDesign",
        "summary": "Create voice design",
        "description": "JSON body with prompt (8–2000 chars). Optional webhook_url for design.ready / design.failed.",
        "security": [
          {
            "BearerAuth": []
          },
          {
            "SessionAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/VoiceDesignCreate"
              }
            }
          }
        },
        "responses": {
          "202": {
            "description": "Design queued",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/VoiceDesignCreated"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized — missing or invalid API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "402": {
            "description": "Payment required — quota or plan limit exceeded",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/voices/design/preview": {
      "post": {
        "tags": [
          "Voice design"
        ],
        "operationId": "previewVoiceDesign",
        "summary": "Preview voice design",
        "description": "Sync preview WAV — does not consume a custom voice slot.",
        "security": [
          {
            "BearerAuth": []
          },
          {
            "SessionAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/VoiceDesignCreate"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Preview WAV",
            "content": {
              "audio/wav": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized — missing or invalid API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "502": {
            "description": "Bad gateway — inference or worker unavailable",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/voices/design/{id}": {
      "delete": {
        "tags": [
          "Voice design"
        ],
        "operationId": "deleteVoiceDesign",
        "summary": "Delete voice design",
        "description": "Removes design artifacts and frees a custom voice slot.",
        "security": [
          {
            "BearerAuth": []
          },
          {
            "SessionAuth": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Design deleted",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/VoiceDesignDeleted"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized — missing or invalid API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/avatar": {
      "get": {
        "tags": [
          "Avatars & jobs"
        ],
        "operationId": "listAvatarJobs",
        "summary": "List avatar jobs",
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "Job list",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AvatarJobList"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized — missing or invalid API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "post": {
        "tags": [
          "Avatars & jobs"
        ],
        "operationId": "createAvatarJob",
        "summary": "Create avatar video job",
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/AvatarJobRequest"
              },
              "example": {
                "text": "Welcome to our product launch.",
                "voice_id": "aurora",
                "avatar_id": "studio-host",
                "video_model": "musetalk"
              }
            }
          }
        },
        "responses": {
          "202": {
            "description": "Job queued",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AvatarJobCreated"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized — missing or invalid API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "402": {
            "description": "Payment required — quota or plan limit exceeded",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "502": {
            "description": "Bad gateway — inference or worker unavailable",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/jobs/{id}": {
      "get": {
        "tags": [
          "Avatars & jobs"
        ],
        "operationId": "getJob",
        "summary": "Get job status",
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Job status",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/JobStatus"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized — missing or invalid API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "502": {
            "description": "Bad gateway — inference or worker unavailable",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/jobs/{id}/events": {
      "get": {
        "tags": [
          "Avatars & jobs"
        ],
        "operationId": "streamJobEvents",
        "summary": "Stream job events (SSE)",
        "description": "Server-sent events for pipeline progress: tts → lipsync → render.",
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "text/event-stream",
            "content": {
              "text/event-stream": {
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized — missing or invalid API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/avatar/{id}/video": {
      "get": {
        "tags": [
          "Avatars & jobs"
        ],
        "operationId": "downloadAvatarVideo",
        "summary": "Download completed MP4",
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "MP4 video",
            "content": {
              "video/mp4": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized — missing or invalid API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Conflict — e.g. voice clone still training or video not ready",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/avatar/{id}": {
      "get": {
        "tags": [
          "Avatars & jobs"
        ],
        "operationId": "getAvatarJob",
        "summary": "Get avatar job by ID",
        "description": "Alias of job status — same payload shape as GET /api/v1/jobs/{id}.",
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Avatar job",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/JobStatus"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized — missing or invalid API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/voices/clone/{id}/sample": {
      "get": {
        "tags": [
          "Voice cloning"
        ],
        "operationId": "downloadCloneSample",
        "summary": "Download clone training sample",
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "WAV sample",
            "content": {
              "audio/wav": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized — missing or invalid API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/avatar/source/{id}": {
      "get": {
        "tags": [
          "Avatars & jobs"
        ],
        "operationId": "downloadAvatarSource",
        "summary": "Download uploaded avatar source",
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Source image or video",
            "content": {
              "image/jpeg": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              },
              "image/png": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              },
              "video/mp4": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized — missing or invalid API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/avatars": {
      "get": {
        "tags": [
          "Avatars & jobs"
        ],
        "operationId": "listAvatars",
        "summary": "List avatar presets",
        "security": [],
        "responses": {
          "200": {
            "description": "Avatar presets",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AvatarCatalog"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/avatar/source": {
      "post": {
        "tags": [
          "Avatars & jobs"
        ],
        "operationId": "uploadAvatarSource",
        "summary": "Upload avatar source media",
        "security": [
          {
            "SessionAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "multipart/form-data": {
              "schema": {
                "type": "object",
                "required": [
                  "source"
                ],
                "properties": {
                  "source": {
                    "type": "string",
                    "format": "binary",
                    "description": "JPG, PNG, WebP, MP4, or WebM"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Source saved",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AvatarSourceCreated"
                }
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized — missing or invalid API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/agents/turn": {
      "post": {
        "tags": [
          "Agents"
        ],
        "operationId": "agentTurn",
        "summary": "Agent turn",
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/AgentTurnRequest"
              },
              "example": {
                "message": "What is included in the free plan?",
                "agent_id": "support",
                "voice_id": "aurora"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Agent reply",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AgentTurnResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized — missing or invalid API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "402": {
            "description": "Payment required — quota or plan limit exceeded",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Conflict — e.g. voice clone still training or video not ready",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/billing/checkout": {
      "post": {
        "tags": [
          "Billing"
        ],
        "operationId": "createCheckout",
        "summary": "Create checkout session",
        "security": [
          {
            "SessionAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CheckoutRequest"
              },
              "example": {
                "plan": "creator",
                "provider": "paystack",
                "region": "africa"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Checkout initiated",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CheckoutResponse"
                }
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized — missing or invalid API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/billing/topup": {
      "post": {
        "tags": [
          "Billing"
        ],
        "operationId": "createTopUp",
        "summary": "PAYG wallet top-up",
        "security": [
          {
            "SessionAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "amountUsd"
                ],
                "properties": {
                  "amountUsd": {
                    "type": "number",
                    "minimum": 5
                  },
                  "provider": {
                    "type": "string"
                  }
                }
              },
              "example": {
                "amountUsd": 20,
                "provider": "stripe"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Top-up initiated",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CheckoutResponse"
                }
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized — missing or invalid API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/billing/payg-settings": {
      "get": {
        "tags": [
          "Billing"
        ],
        "operationId": "getPaygSettings",
        "summary": "Get auto top-up settings",
        "security": [
          {
            "SessionAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "PAYG settings",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized — missing or invalid API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "put": {
        "tags": [
          "Billing"
        ],
        "operationId": "updatePaygSettings",
        "summary": "Update auto top-up settings",
        "security": [
          {
            "SessionAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              },
              "example": {
                "autoTopUpEnabled": true,
                "autoTopUpAmountCents": 2000,
                "lowBalanceThresholdCents": 1000
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Settings updated",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized — missing or invalid API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/webhooks/stripe": {
      "post": {
        "tags": [
          "Webhooks"
        ],
        "operationId": "webhookStripe",
        "summary": "Stripe webhook",
        "description": "Verifies stripe-signature (STRIPE_WEBHOOK_SECRET). Handles checkout.session.completed, invoice.paid, invoice.payment_failed, subscription lifecycle, payment_intent.succeeded. See /docs/api/webhooks for payload schemas.",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Acknowledged"
          }
        }
      }
    },
    "/api/webhooks/paystack": {
      "post": {
        "tags": [
          "Webhooks"
        ],
        "operationId": "webhookPaystack",
        "summary": "Paystack webhook",
        "description": "Requires PAYSTACK_SECRET_KEY or PAYSTACK_WEBHOOK_SECRET (503 if missing). Validates x-paystack-signature. charge.success upgrades plan and credits by customer email. See /docs/api/webhooks.",
        "responses": {
          "200": {
            "description": "Acknowledged"
          }
        }
      }
    },
    "/api/webhooks/flutterwave": {
      "post": {
        "tags": [
          "Webhooks"
        ],
        "operationId": "webhookFlutterwave",
        "summary": "Flutterwave webhook",
        "description": "Requires FLUTTERWAVE_WEBHOOK_SECRET (503 if missing). Validates verif-hash. charge.completed maps customer email → plan/credits. See /docs/api/webhooks.",
        "responses": {
          "200": {
            "description": "Acknowledged"
          }
        }
      }
    },
    "/api/webhooks/dlocal": {
      "post": {
        "tags": [
          "Webhooks"
        ],
        "operationId": "webhookDlocal",
        "summary": "dLocal webhook",
        "description": "Requires DLOCAL_WEBHOOK_SECRET (503 if missing). Validates x-dlocal-signature. payment.approved maps payer.email → plan/credits. See /docs/api/webhooks.",
        "responses": {
          "200": {
            "description": "Acknowledged"
          }
        }
      }
    },
    "/api/analytics": {
      "get": {
        "tags": [
          "Dashboard"
        ],
        "operationId": "getAnalytics",
        "summary": "Usage analytics",
        "security": [
          {
            "SessionAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "Analytics summary",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized — missing or invalid API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/settings": {
      "patch": {
        "tags": [
          "Dashboard"
        ],
        "operationId": "updateSettings",
        "summary": "Update account settings",
        "description": "Configure webhook_url for avatar job completion callbacks.",
        "security": [
          {
            "SessionAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "webhookUrl": {
                    "type": "string",
                    "format": "uri",
                    "nullable": true
                  }
                }
              },
              "example": {
                "webhookUrl": "https://example.com/webhooks/audivra"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Settings updated",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean"
                    },
                    "webhookUrl": {
                      "type": "string",
                      "nullable": true
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized — missing or invalid API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/me": {
      "get": {
        "tags": [
          "Dashboard"
        ],
        "operationId": "getCurrentUser",
        "summary": "Current user profile",
        "security": [
          {
            "SessionAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "User profile or null when signed out",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MeResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/keys": {
      "get": {
        "tags": [
          "Dashboard"
        ],
        "operationId": "listApiKeys",
        "summary": "List API keys",
        "security": [
          {
            "SessionAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "API keys",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiKeyList"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized — missing or invalid API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "post": {
        "tags": [
          "Dashboard"
        ],
        "operationId": "createApiKey",
        "summary": "Mint API key",
        "security": [
          {
            "SessionAuth": []
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Key minted (secret shown once)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiKeyCreated"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized — missing or invalid API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "delete": {
        "tags": [
          "Dashboard"
        ],
        "operationId": "revokeApiKey",
        "summary": "Revoke API key",
        "security": [
          {
            "SessionAuth": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Revoked",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized — missing or invalid API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/usage": {
      "get": {
        "tags": [
          "Dashboard"
        ],
        "operationId": "getUsage",
        "summary": "Usage summary",
        "security": [
          {
            "SessionAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "Usage metrics",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized — missing or invalid API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/health": {
      "get": {
        "tags": [
          "Dashboard"
        ],
        "operationId": "getHealth",
        "summary": "Readiness probe",
        "description": "Returns 503 in production when Supabase, Redis, inference, or payments are missing.",
        "responses": {
          "200": {
            "description": "Health",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean"
                    },
                    "supabase": {
                      "type": "boolean"
                    },
                    "redis": {
                      "type": "boolean"
                    },
                    "inference": {
                      "type": "boolean"
                    },
                    "payments": {
                      "type": "boolean"
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/api/voices/kyc": {
      "get": {
        "tags": [
          "Marketplace"
        ],
        "operationId": "getSellerKyc",
        "summary": "Seller KYC status",
        "security": [
          {
            "BearerAuth": []
          },
          {
            "SessionAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "KYC",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized — missing or invalid API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "post": {
        "tags": [
          "Marketplace"
        ],
        "operationId": "submitSellerKyc",
        "summary": "Submit seller KYC",
        "security": [
          {
            "BearerAuth": []
          },
          {
            "SessionAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "legal_name",
                  "country"
                ],
                "properties": {
                  "legal_name": {
                    "type": "string"
                  },
                  "country": {
                    "type": "string",
                    "description": "ISO-2 country code"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "KYC submitted",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized — missing or invalid API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/voices/payouts": {
      "get": {
        "tags": [
          "Marketplace"
        ],
        "operationId": "listSellerPayouts",
        "summary": "List seller payouts",
        "security": [
          {
            "BearerAuth": []
          },
          {
            "SessionAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "Payouts",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized — missing or invalid API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "post": {
        "tags": [
          "Marketplace"
        ],
        "operationId": "requestSellerPayout",
        "summary": "Request seller payout",
        "security": [
          {
            "BearerAuth": []
          },
          {
            "SessionAuth": []
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "credits": {
                    "type": "integer"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Payout requested",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized — missing or invalid API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/admin/moderation": {
      "get": {
        "tags": [
          "Dashboard"
        ],
        "operationId": "listModerationQueue",
        "summary": "Pending marketplace listings",
        "security": [
          {
            "SessionAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "Pending listings",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized — missing or invalid API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden — paid plan required or batch cap exceeded",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "post": {
        "tags": [
          "Dashboard"
        ],
        "operationId": "applyModeration",
        "summary": "Approve listing, set KYC, or hide a review",
        "security": [
          {
            "SessionAuth": []
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "listing_id": {
                    "type": "string"
                  },
                  "listing_status": {
                    "type": "string",
                    "enum": [
                      "published",
                      "rejected"
                    ]
                  },
                  "kyc_user_id": {
                    "type": "string"
                  },
                  "kyc_status": {
                    "type": "string",
                    "enum": [
                      "none",
                      "pending",
                      "verified",
                      "rejected"
                    ]
                  },
                  "hide_review_id": {
                    "type": "string"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Moderation applied",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized — missing or invalid API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden — paid plan required or batch cap exceeded",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "BearerAuth": {
        "type": "http",
        "scheme": "bearer",
        "description": "sk_live_ followed by 48 hex characters"
      },
      "SessionAuth": {
        "type": "apiKey",
        "in": "cookie",
        "name": "session",
        "description": "Dashboard cookie session (browser). API routes also accept BearerAuth."
      }
    },
    "schemas": {
      "Error": {
        "type": "object",
        "properties": {
          "error": {
            "type": "string"
          }
        }
      },
      "TtsRequest": {
        "type": "object",
        "required": [
          "text"
        ],
        "properties": {
          "text": {
            "type": "string",
            "maxLength": 5000
          },
          "voice_id": {
            "type": "string",
            "enum": [
              "aurora",
              "holloway",
              "mira",
              "kenji",
              "solenne",
              "nile",
              "zuri-sw",
              "umar-ha",
              "ezinne-yo",
              "mekdes-am",
              "swara-hi",
              "tanishaa-bn",
              "klara-de",
              "marco-it",
              "lotte-nl",
              "thando-zu"
            ],
            "default": "aurora"
          },
          "model": {
            "type": "string",
            "enum": [
              "kokoro-82m",
              "kokoro",
              "f5-tts",
              "xtts-v2",
              "cosyvoice-2"
            ],
            "default": "kokoro-82m"
          }
        }
      },
      "TtsStreamRequest": {
        "allOf": [
          {
            "$ref": "#/components/schemas/TtsRequest"
          },
          {
            "type": "object",
            "properties": {
              "format": {
                "type": "string",
                "enum": [
                  "opus",
                  "aac",
                  "wav"
                ],
                "default": "opus"
              }
            }
          }
        ]
      },
      "MusicRequest": {
        "type": "object",
        "required": [
          "prompt"
        ],
        "properties": {
          "prompt": {
            "type": "string",
            "minLength": 4,
            "maxLength": 160
          },
          "seconds": {
            "type": "integer",
            "minimum": 2,
            "maximum": 20,
            "default": 8
          }
        }
      },
      "SfxRequest": {
        "type": "object",
        "required": [
          "prompt"
        ],
        "properties": {
          "prompt": {
            "type": "string",
            "minLength": 4,
            "maxLength": 160
          }
        }
      },
      "GenerateRequest": {
        "type": "object",
        "properties": {
          "text": {
            "type": "string",
            "maxLength": 5000
          },
          "prompt": {
            "type": "string",
            "description": "Alias for text"
          },
          "input": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "type": {
                  "type": "string",
                  "enum": [
                    "video",
                    "audio"
                  ]
                },
                "url": {
                  "type": "string"
                },
                "asset_id": {
                  "type": "string"
                }
              }
            }
          },
          "options": {
            "type": "object",
            "properties": {
              "sync_mode": {
                "type": "string",
                "enum": [
                  "cut_off",
                  "loop",
                  "bounce",
                  "silence",
                  "remap"
                ]
              }
            }
          },
          "voice_id": {
            "type": "string"
          },
          "avatar_id": {
            "type": "string",
            "default": "default"
          },
          "model": {
            "type": "string",
            "enum": [
              "kokoro-82m",
              "kokoro",
              "f5-tts",
              "xtts-v2",
              "cosyvoice-2"
            ]
          },
          "video_model": {
            "type": "string",
            "default": "musetalk"
          },
          "taskType": {
            "type": "string",
            "enum": [
              "tts",
              "llm_inference",
              "lip_sync",
              "unified"
            ],
            "default": "unified"
          },
          "forceCloud": {
            "type": "boolean",
            "default": false
          }
        }
      },
      "GenerateSyncResponse": {
        "type": "object",
        "properties": {
          "success": {
            "type": "boolean"
          },
          "data": {},
          "meta": {
            "type": "object",
            "properties": {
              "executedBy": {
                "type": "string",
                "enum": [
                  "local_worker"
                ]
              },
              "creditsDeducted": {
                "type": "integer"
              }
            }
          }
        }
      },
      "GenerateAsyncResponse": {
        "type": "object",
        "properties": {
          "success": {
            "type": "boolean"
          },
          "job_id": {
            "type": "string"
          },
          "status": {
            "type": "string",
            "example": "PROCESSING"
          },
          "poll": {
            "type": "string"
          },
          "meta": {
            "type": "object"
          }
        }
      },
      "BatchGenerateRequest": {
        "type": "object",
        "properties": {
          "items": {
            "type": "array",
            "minItems": 1,
            "maxItems": 500,
            "items": {
              "type": "object",
              "properties": {
                "text": {
                  "type": "string"
                },
                "voice_id": {
                  "type": "string"
                },
                "avatar_id": {
                  "type": "string"
                },
                "model": {
                  "type": "string"
                },
                "video_model": {
                  "type": "string"
                },
                "input": {
                  "type": "array"
                },
                "options": {
                  "type": "object"
                }
              }
            }
          },
          "jsonl": {
            "type": "string"
          },
          "dry_run": {
            "type": "boolean"
          },
          "webhook_url": {
            "type": "string"
          }
        }
      },
      "BatchGenerateResponse": {
        "type": "object",
        "properties": {
          "batch_size": {
            "type": "integer"
          },
          "jobs": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "job_id": {
                  "type": "string"
                },
                "status": {
                  "type": "string"
                },
                "poll": {
                  "type": "string"
                }
              }
            }
          }
        }
      },
      "EstimateRequest": {
        "type": "object",
        "properties": {
          "kind": {
            "type": "string",
            "enum": [
              "tts",
              "stt",
              "video",
              "dub",
              "lipsync"
            ]
          },
          "text": {
            "type": "string"
          },
          "duration_seconds": {
            "type": "number"
          }
        }
      },
      "EstimateResponse": {
        "type": "object",
        "properties": {
          "kind": {
            "type": "string"
          },
          "duration_seconds": {
            "type": "integer"
          },
          "characters": {
            "type": "integer"
          },
          "credits": {
            "type": "integer"
          },
          "media_seconds_cap": {
            "type": "integer"
          },
          "generate_per_minute": {
            "type": "integer"
          },
          "batch_max": {
            "type": "integer"
          }
        }
      },
      "VoiceCatalog": {
        "type": "object",
        "properties": {
          "voices": {
            "type": "array",
            "items": {
              "type": "object"
            }
          },
          "models": {
            "type": "array",
            "items": {
              "type": "object"
            }
          },
          "clones": {
            "type": "array",
            "items": {
              "type": "object"
            }
          },
          "designs": {
            "type": "array",
            "items": {
              "type": "object"
            }
          }
        }
      },
      "VoiceCloneUpload": {
        "type": "object",
        "required": [
          "sample"
        ],
        "properties": {
          "name": {
            "type": "string"
          },
          "sample": {
            "type": "string",
            "format": "binary",
            "description": "Primary audio sample"
          },
          "samples": {
            "type": "array",
            "items": {
              "type": "string",
              "format": "binary"
            },
            "description": "Audio samples — instant 1–5 files; professional 5–25 files"
          },
          "kind": {
            "type": "string",
            "enum": [
              "instant",
              "professional"
            ],
            "default": "instant"
          },
          "engine": {
            "type": "string",
            "enum": [
              "f5-tts",
              "xtts-v2"
            ],
            "default": "f5-tts"
          },
          "language": {
            "type": "string",
            "default": "en"
          },
          "webhook_url": {
            "type": "string",
            "format": "uri",
            "description": "POST target for clone.ready / clone.failed"
          },
          "consent": {
            "type": "string",
            "description": "Must be on/true — records voice-consent version"
          }
        }
      },
      "VoiceCloneList": {
        "type": "object",
        "properties": {
          "clones": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/VoiceClone"
            }
          }
        }
      },
      "VoiceClone": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "name": {
            "type": "string"
          },
          "status": {
            "type": "string",
            "enum": [
              "queued",
              "training",
              "ready",
              "failed"
            ]
          },
          "engine": {
            "type": "string"
          },
          "kind": {
            "type": "string",
            "enum": [
              "instant",
              "professional"
            ]
          },
          "source": {
            "type": "string",
            "enum": [
              "clone",
              "remix",
              "community"
            ]
          },
          "progress": {
            "type": "integer"
          }
        }
      },
      "VoiceCloneCreated": {
        "type": "object",
        "properties": {
          "clone": {
            "$ref": "#/components/schemas/VoiceClone"
          },
          "voice_id": {
            "type": "string"
          },
          "poll": {
            "type": "string"
          },
          "samples_uploaded": {
            "type": "integer"
          },
          "webhook_url": {
            "type": "string",
            "nullable": true
          }
        }
      },
      "VoiceCloneDeleted": {
        "type": "object",
        "properties": {
          "deleted": {
            "type": "boolean"
          },
          "id": {
            "type": "string",
            "format": "uuid"
          }
        }
      },
      "VoiceCloneRename": {
        "type": "object",
        "required": [
          "name"
        ],
        "properties": {
          "name": {
            "type": "string",
            "minLength": 2,
            "maxLength": 80
          }
        }
      },
      "VoiceCloneRenamed": {
        "type": "object",
        "properties": {
          "clone": {
            "$ref": "#/components/schemas/VoiceClone"
          }
        }
      },
      "CommunityReviewCreate": {
        "type": "object",
        "required": [
          "rating"
        ],
        "properties": {
          "rating": {
            "type": "integer",
            "minimum": 1,
            "maximum": 5
          },
          "comment": {
            "type": "string",
            "maxLength": 280
          }
        }
      },
      "CommunityReviewList": {
        "type": "object",
        "properties": {
          "reviews": {
            "type": "array",
            "items": {
              "type": "object"
            }
          }
        }
      },
      "CommunityReviewSaved": {
        "type": "object",
        "properties": {
          "review": {
            "type": "object"
          }
        }
      },
      "VoiceRemixRequest": {
        "type": "object",
        "required": [
          "prompt"
        ],
        "properties": {
          "prompt": {
            "type": "string",
            "minLength": 8,
            "maxLength": 500
          },
          "name": {
            "type": "string"
          }
        }
      },
      "VoiceRemixCreated": {
        "type": "object",
        "properties": {
          "clone": {
            "$ref": "#/components/schemas/VoiceClone"
          },
          "voice_id": {
            "type": "string"
          },
          "parent_id": {
            "type": "string"
          },
          "status": {
            "type": "string"
          },
          "poll": {
            "type": "string"
          }
        }
      },
      "VoiceListingPublish": {
        "type": "object",
        "required": [
          "title",
          "consent"
        ],
        "properties": {
          "title": {
            "type": "string"
          },
          "description": {
            "type": "string"
          },
          "tags": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "price_credits": {
            "type": "integer",
            "minimum": 0
          },
          "consent": {
            "type": "boolean"
          }
        }
      },
      "VoiceListingPublished": {
        "type": "object",
        "properties": {
          "listing": {
            "type": "object"
          },
          "voice_id": {
            "type": "string"
          },
          "unlisted": {
            "type": "boolean"
          }
        }
      },
      "CommunityVoiceList": {
        "type": "object",
        "properties": {
          "listings": {
            "type": "array",
            "items": {
              "type": "object"
            }
          },
          "voices": {
            "type": "array",
            "items": {
              "type": "object"
            }
          }
        }
      },
      "CommunityVoice": {
        "type": "object",
        "properties": {
          "listing": {
            "type": "object"
          },
          "voice": {
            "type": "object"
          }
        }
      },
      "CommunityVoiceAcquired": {
        "type": "object",
        "properties": {
          "grant": {
            "type": "object"
          },
          "listing": {
            "type": "object"
          },
          "voice_id": {
            "type": "string"
          }
        }
      },
      "VoiceDesignCreate": {
        "type": "object",
        "required": [
          "prompt"
        ],
        "properties": {
          "prompt": {
            "type": "string",
            "minLength": 8,
            "maxLength": 2000
          },
          "name": {
            "type": "string"
          },
          "language": {
            "type": "string",
            "default": "en"
          },
          "gender": {
            "type": "string",
            "enum": [
              "male",
              "female",
              "neutral"
            ],
            "default": "neutral"
          },
          "age": {
            "type": "string",
            "enum": [
              "young",
              "adult",
              "mature"
            ],
            "default": "adult"
          },
          "accent": {
            "type": "string"
          },
          "preview_text": {
            "type": "string",
            "maxLength": 500
          },
          "engine": {
            "type": "string",
            "enum": [
              "f5-tts",
              "xtts-v2"
            ],
            "default": "f5-tts"
          },
          "webhook_url": {
            "type": "string",
            "format": "uri"
          }
        }
      },
      "VoiceDesignList": {
        "type": "object",
        "properties": {
          "designs": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/VoiceDesign"
            }
          }
        }
      },
      "VoiceDesign": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "name": {
            "type": "string"
          },
          "status": {
            "type": "string",
            "enum": [
              "queued",
              "generating",
              "ready",
              "failed"
            ]
          },
          "prompt": {
            "type": "string"
          },
          "engine": {
            "type": "string"
          }
        }
      },
      "VoiceDesignCreated": {
        "type": "object",
        "properties": {
          "design": {
            "$ref": "#/components/schemas/VoiceDesign"
          },
          "voice_id": {
            "type": "string"
          },
          "poll": {
            "type": "string"
          },
          "webhook_url": {
            "type": "string",
            "nullable": true
          }
        }
      },
      "VoiceDesignDeleted": {
        "type": "object",
        "properties": {
          "deleted": {
            "type": "boolean"
          },
          "id": {
            "type": "string",
            "format": "uuid"
          }
        }
      },
      "AvatarJobRequest": {
        "type": "object",
        "required": [
          "text"
        ],
        "properties": {
          "text": {
            "type": "string",
            "maxLength": 5000
          },
          "voice_id": {
            "type": "string"
          },
          "avatar_id": {
            "type": "string"
          },
          "model": {
            "type": "string"
          },
          "video_model": {
            "type": "string"
          },
          "expression": {
            "type": "string"
          },
          "expression_intensity": {
            "type": "number"
          },
          "enhance_face": {
            "type": "boolean"
          },
          "source_url": {
            "type": "string",
            "format": "uri"
          },
          "webhook_url": {
            "type": "string",
            "format": "uri"
          }
        }
      },
      "AvatarJobCreated": {
        "type": "object",
        "properties": {
          "job_id": {
            "type": "string"
          },
          "status": {
            "type": "string"
          },
          "poll": {
            "type": "string"
          },
          "download": {
            "type": "string"
          }
        }
      },
      "AvatarJobList": {
        "type": "object",
        "properties": {
          "jobs": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/JobStatus"
            }
          }
        }
      },
      "JobStatus": {
        "type": "object",
        "properties": {
          "job_id": {
            "type": "string"
          },
          "status": {
            "type": "string",
            "enum": [
              "queued",
              "processing",
              "completed",
              "failed"
            ]
          },
          "text": {
            "type": "string"
          },
          "voice_id": {
            "type": "string"
          },
          "avatar_id": {
            "type": "string"
          },
          "video_model": {
            "type": "string"
          },
          "characters": {
            "type": "integer"
          },
          "duration_seconds": {
            "type": "number"
          },
          "output_url": {
            "type": "string",
            "nullable": true
          },
          "download": {
            "type": "string",
            "nullable": true
          },
          "error": {
            "type": "string",
            "nullable": true
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "updated_at": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "AvatarCatalog": {
        "type": "object",
        "properties": {
          "avatars": {
            "type": "array",
            "items": {
              "type": "object"
            }
          },
          "video_models": {
            "type": "array",
            "items": {
              "type": "object"
            }
          }
        }
      },
      "AvatarSourceCreated": {
        "type": "object",
        "properties": {
          "source_id": {
            "type": "string"
          },
          "source_url": {
            "type": "string"
          },
          "mime": {
            "type": "string"
          }
        }
      },
      "SttCatalog": {
        "type": "object",
        "properties": {
          "languages": {
            "type": "array",
            "items": {
              "type": "object"
            }
          },
          "max_seconds": {
            "type": "integer"
          },
          "max_bytes": {
            "type": "integer"
          }
        }
      },
      "SttUpload": {
        "type": "object",
        "properties": {
          "audio": {
            "type": "string",
            "format": "binary"
          },
          "language": {
            "type": "string"
          }
        }
      },
      "SttJsonRequest": {
        "type": "object",
        "required": [
          "audio_url"
        ],
        "properties": {
          "audio_url": {
            "type": "string",
            "format": "uri"
          },
          "language": {
            "type": "string"
          }
        }
      },
      "SttResponse": {
        "type": "object",
        "properties": {
          "text": {
            "type": "string"
          },
          "language": {
            "type": "string"
          },
          "duration_seconds": {
            "type": "number"
          },
          "engine": {
            "type": "string"
          },
          "credits": {
            "type": "integer"
          },
          "words": {
            "type": "array",
            "items": {
              "type": "object"
            }
          }
        }
      },
      "DubUpload": {
        "type": "object",
        "required": [
          "source"
        ],
        "properties": {
          "source": {
            "type": "string",
            "format": "binary"
          },
          "target_language": {
            "type": "string"
          },
          "voice_id": {
            "type": "string"
          },
          "avatar_id": {
            "type": "string"
          },
          "script": {
            "type": "string"
          },
          "webhook_url": {
            "type": "string"
          }
        }
      },
      "DubJobCreated": {
        "type": "object",
        "properties": {
          "job_id": {
            "type": "string"
          },
          "status": {
            "type": "string"
          },
          "transcript": {
            "type": "string"
          },
          "translation": {
            "type": "string"
          },
          "target_language": {
            "type": "string"
          },
          "source_language": {
            "type": "string"
          },
          "poll": {
            "type": "string"
          },
          "events": {
            "type": "string"
          }
        }
      },
      "AgentTurnRequest": {
        "type": "object",
        "required": [
          "message"
        ],
        "properties": {
          "message": {
            "type": "string"
          },
          "agent_id": {
            "type": "string",
            "enum": [
              "support",
              "sales"
            ]
          },
          "voice_id": {
            "type": "string"
          },
          "model": {
            "type": "string"
          },
          "speak": {
            "type": "boolean",
            "default": true
          }
        }
      },
      "AgentTurnResponse": {
        "type": "object",
        "properties": {
          "reply": {
            "type": "string"
          },
          "audio_base64": {
            "type": "string"
          },
          "characters": {
            "type": "integer"
          },
          "engine": {
            "type": "string"
          }
        }
      },
      "CheckoutRequest": {
        "type": "object",
        "required": [
          "plan"
        ],
        "properties": {
          "plan": {
            "type": "string",
            "enum": [
              "free",
              "starter",
              "creator",
              "developer"
            ]
          },
          "provider": {
            "type": "string",
            "enum": [
              "stripe",
              "dlocal",
              "paystack",
              "flutterwave",
              "ebanx",
              "yellowcard"
            ]
          },
          "region": {
            "type": "string",
            "enum": [
              "africa",
              "latam",
              "south-asia"
            ]
          }
        }
      },
      "CheckoutResponse": {
        "type": "object",
        "properties": {
          "ok": {
            "type": "boolean"
          },
          "url": {
            "type": "string",
            "format": "uri"
          },
          "mode": {
            "type": "string",
            "enum": [
              "stripe",
              "redirect",
              "demo"
            ]
          },
          "provider": {
            "type": "string"
          },
          "note": {
            "type": "string"
          }
        }
      },
      "MeResponse": {
        "type": "object",
        "properties": {
          "user": {
            "type": "object",
            "nullable": true
          }
        }
      },
      "ApiKeyList": {
        "type": "object",
        "properties": {
          "keys": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "id": {
                  "type": "string"
                },
                "name": {
                  "type": "string"
                },
                "prefix": {
                  "type": "string"
                },
                "lastUsedAt": {
                  "type": "string",
                  "nullable": true
                },
                "createdAt": {
                  "type": "string"
                }
              }
            }
          }
        }
      },
      "ApiKeyCreated": {
        "type": "object",
        "properties": {
          "key": {
            "type": "object",
            "properties": {
              "id": {
                "type": "string"
              },
              "name": {
                "type": "string"
              },
              "prefix": {
                "type": "string"
              },
              "secret": {
                "type": "string",
                "description": "Full sk_live_ key — shown once"
              }
            }
          }
        }
      }
    }
  }
}