{
  "openapi": "3.1.0",
  "info": {
    "title": "Voice1 API",
    "version": "1.0.0",
    "contact": {
      "url": "https://voice1.pro/docs"
    },
    "description": "The Voice1 REST API: generate speech from text, track progress and download output files. Full documentation: https://voice1.pro/docs"
  },
  "servers": [
    {
      "url": "https://voice1.pro/api"
    }
  ],
  "security": [
    {
      "bearerAuth": []
    }
  ],
  "tags": [
    {
      "name": "Authentication",
      "x-displayName": "Authentication"
    },
    {
      "name": "Voices",
      "x-displayName": "Voices"
    },
    {
      "name": "TextToSpeech",
      "x-displayName": "Text to speech"
    },
    {
      "name": "History",
      "x-displayName": "History"
    },
    {
      "name": "Files",
      "x-displayName": "Output files"
    },
    {
      "name": "Account",
      "x-displayName": "Account"
    },
    {
      "name": "Dialogue",
      "x-displayName": "Dialogue"
    }
  ],
  "paths": {
    "/v1/auth/me": {
      "get": {
        "operationId": "authMe",
        "tags": [
          "Authentication"
        ],
        "summary": "Get account",
        "description": "Returns the profile and current credit balance of the API key's owner. Call this endpoint to check that your key works.",
        "responses": {
          "200": {
            "description": "Success.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string"
                    },
                    "name": {
                      "type": "string"
                    },
                    "email": {
                      "type": "string"
                    },
                    "credits": {
                      "type": "integer"
                    },
                    "createdAt": {
                      "type": "string",
                      "format": "date-time"
                    }
                  }
                },
                "example": {
                  "id": "u_3b91d2c07a5e4f18b6d9a0c2",
                  "name": "Nguyễn Minh Anh",
                  "email": "minhanh@example.com",
                  "credits": 128450,
                  "createdAt": "2026-03-14T08:00:00.000Z"
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized` — The API key is missing, invalid or revoked, or the account is locked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/voices": {
      "get": {
        "operationId": "voicesList",
        "tags": [
          "Voices"
        ],
        "summary": "List voices",
        "description": "Browse the voice library by language, gender, age and other filters. This is your first step: get a voiceId to generate speech with.\n\nPublic endpoint, no API key required. The voice list changes rarely — you may cache it for a few minutes.\n\nFilter parameters with invalid values are ignored (treated as no filter) instead of returning an error — double-check spelling if the results aren't what you expect.\n\nA voice's `id` is an alphanumeric string (up to 64 characters) — pass it unchanged as `voiceId` when creating a task. `previewUrl` is a public preview link and may change — don't store it long-term.",
        "security": [],
        "parameters": [
          {
            "name": "provider",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string",
              "enum": [
                "elevenlabs"
              ]
            },
            "description": "Required. Any other engine returns 404.",
            "example": "elevenlabs"
          },
          {
            "name": "language",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": "ISO language code, e.g. vi, en.",
            "example": "vi"
          },
          {
            "name": "gender",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "male",
                "female",
                "neutral"
              ]
            },
            "description": "Voice gender."
          },
          {
            "name": "age",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "young",
                "middle_aged",
                "old"
              ]
            },
            "description": "Age group."
          },
          {
            "name": "accent",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": "Regional accent, e.g. northern, southern."
          },
          {
            "name": "useCase",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "conversational",
                "narrative_story",
                "characters_animation",
                "social_media",
                "entertainment_tv",
                "advertisement",
                "informative_educational"
              ]
            },
            "description": "Intended use case."
          },
          {
            "name": "quality",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "standard",
                "high"
              ]
            },
            "description": "Voice quality tier."
          },
          {
            "name": "sort",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "trending",
                "latest",
                "most_used"
              ]
            },
            "description": "Sort order. Defaults to trending."
          },
          {
            "name": "page",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer"
            },
            "description": "Page to return, from 1 to 500. Out-of-range values fall back to page 1.",
            "example": 1
          },
          {
            "name": "pageSize",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer"
            },
            "description": "Voices per page, from 1 to 100. Defaults to 24; out-of-range values also fall back to 24.",
            "example": 24
          },
          {
            "name": "search",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": "Search by name or description (up to 100 characters)."
          }
        ],
        "responses": {
          "200": {
            "description": "Success.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "items": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string"
                          },
                          "provider": {
                            "type": "string"
                          },
                          "name": {
                            "type": "string"
                          },
                          "description": {
                            "type": "string"
                          },
                          "previewUrl": {
                            "type": "string"
                          },
                          "gender": {
                            "type": "string"
                          },
                          "age": {
                            "type": "string"
                          },
                          "language": {
                            "type": "string"
                          },
                          "accent": {
                            "type": "string"
                          },
                          "tags": {
                            "type": "array",
                            "items": {
                              "type": "string"
                            }
                          },
                          "languages": {
                            "type": "array",
                            "items": {
                              "type": "object",
                              "properties": {
                                "language": {
                                  "type": "string"
                                },
                                "accent": {
                                  "type": "string"
                                },
                                "previewUrl": {
                                  "type": "string"
                                }
                              }
                            }
                          },
                          "useCase": {
                            "type": "string"
                          },
                          "category": {
                            "type": "string"
                          },
                          "quality": {
                            "type": "string"
                          }
                        }
                      }
                    },
                    "total": {
                      "type": "integer"
                    },
                    "page": {
                      "type": "integer"
                    },
                    "pageSize": {
                      "type": "integer"
                    },
                    "hasMore": {
                      "type": "boolean"
                    }
                  }
                },
                "example": {
                  "items": [
                    {
                      "id": "jdlxsPOZOHdGEfcItXVu",
                      "provider": "elevenlabs",
                      "name": "Hiền",
                      "description": "Giọng nữ miền Bắc, ấm áp, hợp kể chuyện.",
                      "previewUrl": "https://cdn.example.com/previews/hien.mp3",
                      "gender": "female",
                      "age": "young",
                      "language": "vi",
                      "accent": "northern",
                      "tags": [
                        "warm",
                        "narrative_story"
                      ],
                      "languages": [
                        {
                          "language": "vi",
                          "accent": "northern",
                          "previewUrl": "https://cdn.example.com/previews/hien.mp3"
                        }
                      ],
                      "useCase": "narrative_story",
                      "category": "narrative_story",
                      "quality": "high"
                    }
                  ],
                  "total": 1,
                  "page": 1,
                  "pageSize": 24,
                  "hasMore": false
                }
              }
            }
          },
          "400": {
            "description": "`bad_request` — Rare: invalid filter values (gender, sort…) are usually ignored rather than rejected.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "`unsupported_provider` — Unsupported engine. Only provider=elevenlabs is currently accepted.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited` — Too many requests. Wait the number of seconds in the Retry-After header.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds to wait."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "`voices_unavailable` — The voice library is temporarily unavailable. Please try again later.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/voices/trending": {
      "get": {
        "operationId": "voicesTrending",
        "tags": [
          "Voices"
        ],
        "summary": "Most-used voices",
        "description": "A short list of popular voices — a good set of default suggestions for new users.\n\nThe list is already sorted by popularity: the first item is the most popular voice.",
        "security": [],
        "responses": {
          "200": {
            "description": "Success.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "type": "object",
                    "properties": {
                      "id": {
                        "type": "string"
                      },
                      "provider": {
                        "type": "string"
                      },
                      "name": {
                        "type": "string"
                      },
                      "description": {
                        "type": "string"
                      },
                      "previewUrl": {
                        "type": "string"
                      },
                      "gender": {
                        "type": "string"
                      },
                      "age": {
                        "type": "string"
                      },
                      "language": {
                        "type": "string"
                      },
                      "accent": {
                        "type": "string"
                      },
                      "tags": {
                        "type": "array",
                        "items": {
                          "type": "string"
                        }
                      },
                      "languages": {
                        "type": "array",
                        "items": {
                          "type": "object",
                          "properties": {
                            "language": {
                              "type": "string"
                            },
                            "accent": {
                              "type": "string"
                            },
                            "previewUrl": {
                              "type": "string"
                            }
                          }
                        }
                      },
                      "useCase": {
                        "type": "string"
                      },
                      "category": {
                        "type": "string"
                      },
                      "quality": {
                        "type": "string"
                      }
                    }
                  }
                },
                "example": [
                  {
                    "id": "jdlxsPOZOHdGEfcItXVu",
                    "provider": "elevenlabs",
                    "name": "Hiền",
                    "description": "Giọng nữ miền Bắc, ấm áp, hợp kể chuyện.",
                    "previewUrl": "https://cdn.example.com/previews/hien.mp3",
                    "gender": "female",
                    "age": "young",
                    "language": "vi",
                    "accent": "northern",
                    "tags": [
                      "warm",
                      "narrative_story"
                    ],
                    "languages": [
                      {
                        "language": "vi",
                        "accent": "northern",
                        "previewUrl": "https://cdn.example.com/previews/hien.mp3"
                      }
                    ],
                    "useCase": "narrative_story",
                    "category": "narrative_story",
                    "quality": "high"
                  }
                ]
              }
            }
          }
        }
      }
    },
    "/v1/text-to-speech/{provider}": {
      "post": {
        "operationId": "ttsCreate",
        "tags": [
          "TextToSpeech"
        ],
        "summary": "Create speech",
        "description": "Creates a text-to-speech task. Tasks run asynchronously — use the History endpoints to track status and fetch the files.\n\nReturns 201 when a new task is created. Credits are charged immediately and refunded automatically if the task fails.\n\nSend an `Idempotency-Key` header to avoid duplicates on unreliable networks: resending with the same key returns the original task (200 + `Idempotent-Replay: true` header) without charging credits a second time. The same key with a different text / voice / model → 409 `idempotency_key_reused`.",
        "parameters": [
          {
            "name": "provider",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "enum": [
                "elevenlabs"
              ]
            },
            "description": "Engine used to generate speech.",
            "example": "elevenlabs"
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string",
              "minLength": 8,
              "maxLength": 128,
              "pattern": "^[A-Za-z0-9._:-]+$"
            },
            "description": "Resending the same key returns the task already created, without charging again."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string",
                    "description": "A friendly name for the recording (up to 120 characters). If omitted, the first 48 characters of the text are used."
                  },
                  "text": {
                    "type": "string",
                    "description": "The text to speak. Up to 250,000 characters of spoken text and 600,000 characters of raw input."
                  },
                  "voiceId": {
                    "type": "string",
                    "description": "Voice ID from GET /v1/voices (an alphanumeric string — use it unchanged). A malformed ID → 400 bad_request, with no credits charged."
                  },
                  "voiceName": {
                    "type": "string",
                    "description": "Voice name shown in history (up to 120 characters). Optional: if omitted, it is filled in from `voiceId` when possible."
                  },
                  "modelId": {
                    "type": "string",
                    "description": "Model ID, e.g. eleven_v4. The model must belong to the engine in the path."
                  },
                  "settings": {
                    "type": "object",
                    "properties": {
                      "speed": {
                        "type": "integer"
                      },
                      "stability": {
                        "type": "number"
                      },
                      "similarity": {
                        "type": "number"
                      },
                      "style": {
                        "type": "integer"
                      },
                      "speakerBoost": {
                        "type": "boolean"
                      },
                      "language": {
                        "type": "string"
                      },
                      "leveling": {
                        "type": "integer"
                      }
                    },
                    "description": "Voice settings: speed, stability, similarity, style, language, leveling. Up to 4,096 bytes of JSON. If omitted, defaults apply."
                  },
                  "exportTranscript": {
                    "type": "boolean",
                    "description": "Also export SRT subtitles (5% surcharge). Defaults to false."
                  },
                  "inputFormat": {
                    "type": "string",
                    "enum": [
                      "text"
                    ],
                    "description": "Defaults to 'text'. SRT input ('srt') is temporarily disabled — sending 'srt' returns 503 feature_disabled."
                  }
                },
                "required": [
                  "text",
                  "voiceId",
                  "modelId"
                ]
              },
              "example": {
                "name": "Lời chào buổi sáng",
                "text": "Xin chào, chúc bạn một ngày làm việc hiệu quả!",
                "voiceId": "jdlxsPOZOHdGEfcItXVu",
                "voiceName": "Hiền",
                "modelId": "eleven_v4",
                "settings": {
                  "speed": 1,
                  "stability": 0.5,
                  "similarity": 0.75,
                  "style": 0,
                  "speakerBoost": true,
                  "language": "vi",
                  "leveling": 0
                },
                "exportTranscript": true
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Replay: the task created earlier with the same Idempotency-Key (batch: every file matched a requestKey, created = 0). No extra credits charged.",
            "headers": {
              "Idempotent-Replay": {
                "schema": {
                  "type": "string",
                  "enum": [
                    "true"
                  ]
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string"
                    },
                    "kind": {
                      "type": "string"
                    },
                    "provider": {
                      "type": "string"
                    },
                    "name": {
                      "type": "string"
                    },
                    "text": {
                      "type": "string"
                    },
                    "status": {
                      "type": "string"
                    },
                    "progress": {
                      "type": "integer"
                    },
                    "voiceId": {
                      "type": "string"
                    },
                    "voiceName": {
                      "type": "string"
                    },
                    "modelId": {
                      "type": "string"
                    },
                    "language": {
                      "type": "string"
                    },
                    "settings": {
                      "type": "object",
                      "properties": {
                        "speed": {
                          "type": "integer"
                        },
                        "stability": {
                          "type": "number"
                        },
                        "similarity": {
                          "type": "number"
                        },
                        "style": {
                          "type": "integer"
                        },
                        "speakerBoost": {
                          "type": "boolean"
                        },
                        "language": {
                          "type": "string"
                        },
                        "leveling": {
                          "type": "integer"
                        }
                      }
                    },
                    "creditsCost": {
                      "type": "integer"
                    },
                    "exportTranscript": {
                      "type": "boolean"
                    },
                    "createdAt": {
                      "type": "string",
                      "format": "date-time"
                    }
                  }
                },
                "example": {
                  "id": "tsk_24598d03cfcac9a82eec36f0",
                  "kind": "tts",
                  "provider": "elevenlabs",
                  "name": "Lời chào buổi sáng",
                  "text": "Xin chào, chúc bạn một ngày làm việc hiệu quả!",
                  "status": "queued",
                  "progress": 0,
                  "voiceId": "jdlxsPOZOHdGEfcItXVu",
                  "voiceName": "Hiền",
                  "modelId": "eleven_v4",
                  "language": "vi",
                  "settings": {
                    "speed": 1,
                    "stability": 0.5,
                    "similarity": 0.75,
                    "style": 0,
                    "speakerBoost": true,
                    "language": "vi",
                    "leveling": 0
                  },
                  "creditsCost": 500,
                  "exportTranscript": true,
                  "createdAt": "2026-10-02T08:00:00.000Z"
                }
              }
            }
          },
          "201": {
            "description": "Success.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string"
                    },
                    "kind": {
                      "type": "string"
                    },
                    "provider": {
                      "type": "string"
                    },
                    "name": {
                      "type": "string"
                    },
                    "text": {
                      "type": "string"
                    },
                    "status": {
                      "type": "string"
                    },
                    "progress": {
                      "type": "integer"
                    },
                    "voiceId": {
                      "type": "string"
                    },
                    "voiceName": {
                      "type": "string"
                    },
                    "modelId": {
                      "type": "string"
                    },
                    "language": {
                      "type": "string"
                    },
                    "settings": {
                      "type": "object",
                      "properties": {
                        "speed": {
                          "type": "integer"
                        },
                        "stability": {
                          "type": "number"
                        },
                        "similarity": {
                          "type": "number"
                        },
                        "style": {
                          "type": "integer"
                        },
                        "speakerBoost": {
                          "type": "boolean"
                        },
                        "language": {
                          "type": "string"
                        },
                        "leveling": {
                          "type": "integer"
                        }
                      }
                    },
                    "creditsCost": {
                      "type": "integer"
                    },
                    "exportTranscript": {
                      "type": "boolean"
                    },
                    "createdAt": {
                      "type": "string",
                      "format": "date-time"
                    }
                  }
                },
                "example": {
                  "id": "tsk_24598d03cfcac9a82eec36f0",
                  "kind": "tts",
                  "provider": "elevenlabs",
                  "name": "Lời chào buổi sáng",
                  "text": "Xin chào, chúc bạn một ngày làm việc hiệu quả!",
                  "status": "queued",
                  "progress": 0,
                  "voiceId": "jdlxsPOZOHdGEfcItXVu",
                  "voiceName": "Hiền",
                  "modelId": "eleven_v4",
                  "language": "vi",
                  "settings": {
                    "speed": 1,
                    "stability": 0.5,
                    "similarity": 0.75,
                    "style": 0,
                    "speakerBoost": true,
                    "language": "vi",
                    "leveling": 0
                  },
                  "creditsCost": 500,
                  "exportTranscript": true,
                  "createdAt": "2026-10-02T08:00:00.000Z"
                }
              }
            }
          },
          "400": {
            "description": "`bad_request` — A required field is missing, a value has the wrong type, or a limit was exceeded (including text that is too long). `message` explains what is wrong.\n\n`invalid_provider` — The engine in the path is not supported.\n\n`invalid_model` — `modelId` does not exist or does not belong to the selected engine.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized` — The API key is missing, invalid or revoked, or the account is locked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "402": {
            "description": "`insufficient_credits` — Not enough credits. No task is created and no credits are charged.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "`forbidden_origin` — Only seen when calling from a browser: a write request (POST, DELETE) that did not come from our website. Call from your server.\n\n`content_hold` — Task creation via the API is paused because many recent requests were rejected for their text content (`content_blocked` errors). No credits are charged — review your text and retry after the `Retry-After` seconds (15 minutes, longer if it repeats).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "`idempotency_key_reused` — This Idempotency-Key was already used for a different request (different text, voice or model). Nothing is created and no credits are charged — use a new key for each new request.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "413": {
            "description": "`payload_too_large` — The body exceeds 10 MB. Text over the character limit returns 400 bad_request, not 413.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "415": {
            "description": "`unsupported_media_type` — `Content-Type: application/json` is missing.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited` — More than about 600 tasks created per minute (test keys `vs_test_`: 30). Wait the number of seconds in the `Retry-After` header, then resend.\n\n`queue_full` — 1,000 tasks created with API keys are already waiting (for batch creation: waiting tasks + files in the batch exceed this). Nothing is created and no credits are charged — wait for some to finish, then resend after the `Retry-After` seconds.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds to wait."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "`tasks_disabled` — Speech generation is temporarily paused for maintenance. No credits are charged — try again later.\n\n`system_busy` — The system is overloaded and is temporarily not accepting new tasks via the API. No credits are charged — retry after the `Retry-After` seconds, with increasing delays.\n\n`feature_disabled` — SRT input (inputFormat: 'srt') is temporarily disabled. No credits are charged — send plain text instead.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/text-to-speech/{provider}/batch": {
      "post": {
        "operationId": "ttsBatch",
        "tags": [
          "TextToSpeech"
        ],
        "summary": "Create speech in batch",
        "description": "Create up to 25 recordings in a single request. Each file has its own voice, model and settings.\n\nAll or nothing: if credits run short or you would exceed the queued-task limit, no files are created and nothing is charged.\n\n`created` is the number of tasks actually created. If you resend the whole batch with the same `requestKey`s, files that already exist are returned (and not charged again); if no new file is created, the response is 200 with `created: 0`.\n\nRate limits count each request once, regardless of the number of files.",
        "parameters": [
          {
            "name": "provider",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "enum": [
                "elevenlabs"
              ]
            },
            "description": "Engine used to generate speech.",
            "example": "elevenlabs"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "items": {
                    "type": "array",
                    "items": {
                      "type": "object",
                      "properties": {
                        "requestKey": {
                          "type": "string",
                          "description": "Per-file idempotency key (optional, same format as `Idempotency-Key`)."
                        },
                        "inputFormat": {
                          "type": "string",
                          "enum": [
                            "text"
                          ],
                          "description": "Defaults to 'text'. SRT input ('srt') is temporarily disabled — sending 'srt' returns 503 feature_disabled."
                        },
                        "name": {
                          "type": "string"
                        },
                        "text": {
                          "type": "string"
                        },
                        "voiceId": {
                          "type": "string"
                        },
                        "modelId": {
                          "type": "string"
                        },
                        "settings": {
                          "type": "object",
                          "properties": {
                            "speed": {
                              "type": "integer"
                            },
                            "stability": {
                              "type": "number"
                            },
                            "similarity": {
                              "type": "number"
                            },
                            "style": {
                              "type": "integer"
                            },
                            "speakerBoost": {
                              "type": "boolean"
                            },
                            "language": {
                              "type": "string"
                            },
                            "leveling": {
                              "type": "integer"
                            }
                          }
                        },
                        "exportTranscript": {
                          "type": "boolean"
                        }
                      }
                    },
                    "description": "The files to create, from 1 to 25. Each item has the same shape as the Create speech request body."
                  }
                },
                "required": [
                  "items"
                ]
              },
              "example": {
                "items": [
                  {
                    "name": "Chương 1",
                    "text": "Chương một: khởi đầu.",
                    "voiceId": "jdlxsPOZOHdGEfcItXVu",
                    "modelId": "eleven_v4",
                    "settings": {
                      "speed": 1,
                      "stability": 0.5,
                      "similarity": 0.75,
                      "style": 0,
                      "speakerBoost": true,
                      "language": "vi",
                      "leveling": 0
                    },
                    "exportTranscript": false,
                    "requestKey": "book-42-ch-01"
                  },
                  {
                    "name": "Chương 2",
                    "text": "Chương hai: tiếp nối.",
                    "voiceId": "ZsjEJaLQy3sgvwxicmDx",
                    "modelId": "eleven_v4",
                    "settings": {
                      "speed": 1,
                      "stability": 0.5,
                      "similarity": 0.75,
                      "style": 0,
                      "speakerBoost": true,
                      "language": "vi",
                      "leveling": 0
                    },
                    "exportTranscript": false,
                    "requestKey": "book-42-ch-02"
                  }
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Replay: the task created earlier with the same Idempotency-Key (batch: every file matched a requestKey, created = 0). No extra credits charged.",
            "headers": {
              "Idempotent-Replay": {
                "schema": {
                  "type": "string",
                  "enum": [
                    "true"
                  ]
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "tasks": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string"
                          },
                          "kind": {
                            "type": "string"
                          },
                          "provider": {
                            "type": "string"
                          },
                          "name": {
                            "type": "string"
                          },
                          "text": {
                            "type": "string"
                          },
                          "status": {
                            "type": "string"
                          },
                          "progress": {
                            "type": "integer"
                          },
                          "voiceId": {
                            "type": "string"
                          },
                          "voiceName": {
                            "type": "string"
                          },
                          "modelId": {
                            "type": "string"
                          },
                          "language": {
                            "type": "string"
                          },
                          "settings": {
                            "type": "object",
                            "properties": {
                              "speed": {
                                "type": "integer"
                              },
                              "stability": {
                                "type": "number"
                              },
                              "similarity": {
                                "type": "number"
                              },
                              "style": {
                                "type": "integer"
                              },
                              "speakerBoost": {
                                "type": "boolean"
                              },
                              "language": {
                                "type": "string"
                              },
                              "leveling": {
                                "type": "integer"
                              }
                            }
                          },
                          "creditsCost": {
                            "type": "integer"
                          },
                          "exportTranscript": {
                            "type": "boolean"
                          },
                          "createdAt": {
                            "type": "string",
                            "format": "date-time"
                          }
                        }
                      }
                    },
                    "created": {
                      "type": "integer"
                    }
                  }
                },
                "example": {
                  "tasks": [
                    {
                      "id": "tsk_5e0c2a7b9d1f3e4a6b8c0d2e",
                      "kind": "tts",
                      "provider": "elevenlabs",
                      "name": "Chương 1",
                      "text": "Chương một: khởi đầu.",
                      "status": "queued",
                      "progress": 0,
                      "voiceId": "jdlxsPOZOHdGEfcItXVu",
                      "voiceName": "",
                      "modelId": "eleven_v4",
                      "language": "vi",
                      "settings": {
                        "speed": 1,
                        "stability": 0.5,
                        "similarity": 0.75,
                        "style": 0,
                        "speakerBoost": true,
                        "language": "vi",
                        "leveling": 0
                      },
                      "creditsCost": 500,
                      "exportTranscript": false,
                      "createdAt": "2026-10-02T08:00:00.000Z"
                    },
                    {
                      "id": "tsk_8a3f1c6e2b9d4f7a0c5e1b3d",
                      "kind": "tts",
                      "provider": "elevenlabs",
                      "name": "Chương 2",
                      "text": "Chương hai: tiếp nối.",
                      "status": "queued",
                      "progress": 0,
                      "voiceId": "ZsjEJaLQy3sgvwxicmDx",
                      "voiceName": "",
                      "modelId": "eleven_v4",
                      "language": "vi",
                      "settings": {
                        "speed": 1,
                        "stability": 0.5,
                        "similarity": 0.75,
                        "style": 0,
                        "speakerBoost": true,
                        "language": "vi",
                        "leveling": 0
                      },
                      "creditsCost": 500,
                      "exportTranscript": false,
                      "createdAt": "2026-10-02T08:00:00.000Z"
                    }
                  ],
                  "created": 2
                }
              }
            }
          },
          "201": {
            "description": "Success.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "tasks": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string"
                          },
                          "kind": {
                            "type": "string"
                          },
                          "provider": {
                            "type": "string"
                          },
                          "name": {
                            "type": "string"
                          },
                          "text": {
                            "type": "string"
                          },
                          "status": {
                            "type": "string"
                          },
                          "progress": {
                            "type": "integer"
                          },
                          "voiceId": {
                            "type": "string"
                          },
                          "voiceName": {
                            "type": "string"
                          },
                          "modelId": {
                            "type": "string"
                          },
                          "language": {
                            "type": "string"
                          },
                          "settings": {
                            "type": "object",
                            "properties": {
                              "speed": {
                                "type": "integer"
                              },
                              "stability": {
                                "type": "number"
                              },
                              "similarity": {
                                "type": "number"
                              },
                              "style": {
                                "type": "integer"
                              },
                              "speakerBoost": {
                                "type": "boolean"
                              },
                              "language": {
                                "type": "string"
                              },
                              "leveling": {
                                "type": "integer"
                              }
                            }
                          },
                          "creditsCost": {
                            "type": "integer"
                          },
                          "exportTranscript": {
                            "type": "boolean"
                          },
                          "createdAt": {
                            "type": "string",
                            "format": "date-time"
                          }
                        }
                      }
                    },
                    "created": {
                      "type": "integer"
                    }
                  }
                },
                "example": {
                  "tasks": [
                    {
                      "id": "tsk_5e0c2a7b9d1f3e4a6b8c0d2e",
                      "kind": "tts",
                      "provider": "elevenlabs",
                      "name": "Chương 1",
                      "text": "Chương một: khởi đầu.",
                      "status": "queued",
                      "progress": 0,
                      "voiceId": "jdlxsPOZOHdGEfcItXVu",
                      "voiceName": "",
                      "modelId": "eleven_v4",
                      "language": "vi",
                      "settings": {
                        "speed": 1,
                        "stability": 0.5,
                        "similarity": 0.75,
                        "style": 0,
                        "speakerBoost": true,
                        "language": "vi",
                        "leveling": 0
                      },
                      "creditsCost": 500,
                      "exportTranscript": false,
                      "createdAt": "2026-10-02T08:00:00.000Z"
                    },
                    {
                      "id": "tsk_8a3f1c6e2b9d4f7a0c5e1b3d",
                      "kind": "tts",
                      "provider": "elevenlabs",
                      "name": "Chương 2",
                      "text": "Chương hai: tiếp nối.",
                      "status": "queued",
                      "progress": 0,
                      "voiceId": "ZsjEJaLQy3sgvwxicmDx",
                      "voiceName": "",
                      "modelId": "eleven_v4",
                      "language": "vi",
                      "settings": {
                        "speed": 1,
                        "stability": 0.5,
                        "similarity": 0.75,
                        "style": 0,
                        "speakerBoost": true,
                        "language": "vi",
                        "leveling": 0
                      },
                      "creditsCost": 500,
                      "exportTranscript": false,
                      "createdAt": "2026-10-02T08:00:00.000Z"
                    }
                  ],
                  "created": 2
                }
              }
            }
          },
          "400": {
            "description": "`bad_request` — If any file has invalid data (including its model or settings), the error names its position, e.g. \"File 2 (Chương 2): …\". No files are created.\n\n`invalid_provider` — The engine in the path is not supported.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized` — The API key is missing, invalid or revoked, or the account is locked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "402": {
            "description": "`insufficient_credits` — Not enough credits. No task is created and no credits are charged.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "`forbidden_origin` — Only seen when calling from a browser: a write request (POST, DELETE) that did not come from our website. Call from your server.\n\n`content_hold` — Task creation via the API is paused because many recent requests were rejected for their text content (`content_blocked` errors). No credits are charged — review your text and retry after the `Retry-After` seconds (15 minutes, longer if it repeats).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "`idempotency_key_reused` — This Idempotency-Key was already used for a different request (different text, voice or model). Nothing is created and no credits are charged — use a new key for each new request.\n\n`task_conflict` — Rare: the task changed state because of another request running concurrently. No credits are charged — reload and try again.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "413": {
            "description": "`payload_too_large` — The body exceeds 10 MB. Text over the character limit returns 400 bad_request, not 413.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "415": {
            "description": "`unsupported_media_type` — `Content-Type: application/json` is missing.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited` — More than about 600 tasks created per minute (test keys `vs_test_`: 30). Wait the number of seconds in the `Retry-After` header, then resend.\n\n`queue_full` — 1,000 tasks created with API keys are already waiting (for batch creation: waiting tasks + files in the batch exceed this). Nothing is created and no credits are charged — wait for some to finish, then resend after the `Retry-After` seconds.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds to wait."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "`tasks_disabled` — Speech generation is temporarily paused for maintenance. No credits are charged — try again later.\n\n`system_busy` — The system is overloaded and is temporarily not accepting new tasks via the API. No credits are charged — retry after the `Retry-After` seconds, with increasing delays.\n\n`feature_disabled` — SRT input (inputFormat: 'srt') is temporarily disabled. No credits are charged — send plain text instead.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/history": {
      "get": {
        "operationId": "historyList",
        "tags": [
          "History"
        ],
        "summary": "List tasks",
        "description": "Lists the tasks you have created, newest first, with optional filters by kind and status. Long text may be truncated to 2,000 characters (textTruncated: true); fetch the full text with Get task.\n\nThere is no search-by-name parameter. Tasks you delete while they are running are removed entirely, so they no longer appear in the list.\n\n`total` is counted up to 1,000 tasks (or up to the end of the requested page if that is further). Beyond that, `total` is a lower bound and the response also has `totalCapped: true` — use `hasMore` to know whether another page exists.",
        "parameters": [
          {
            "name": "kind",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "tts",
                "srt",
                "dialogue",
                "voice_changer",
                "dubbing"
              ]
            },
            "description": "Filter by task kind. Invalid values are ignored (no filtering).",
            "example": "tts"
          },
          {
            "name": "status",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "queued",
                "processing",
                "completed",
                "failed"
              ]
            },
            "description": "Filter by status. Lifecycle: 'queued' (received, not started yet) → 'processing' → 'completed' | 'failed'. Invalid values are ignored."
          },
          {
            "name": "page",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer"
            },
            "description": "Page to return, starting at 1.",
            "example": 1
          },
          {
            "name": "pageSize",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer"
            },
            "description": "Tasks per page, from 1 to 100. Defaults to 10. Out-of-range values are clamped to 1 or 100.",
            "example": 10
          }
        ],
        "responses": {
          "200": {
            "description": "Success.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "items": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string"
                          },
                          "kind": {
                            "type": "string"
                          },
                          "provider": {
                            "type": "string"
                          },
                          "name": {
                            "type": "string"
                          },
                          "text": {
                            "type": "string"
                          },
                          "status": {
                            "type": "string"
                          },
                          "progress": {
                            "type": "integer"
                          },
                          "voiceId": {
                            "type": "string"
                          },
                          "voiceName": {
                            "type": "string"
                          },
                          "modelId": {
                            "type": "string"
                          },
                          "language": {
                            "type": "string"
                          },
                          "settings": {
                            "type": "object",
                            "properties": {
                              "speed": {
                                "type": "integer"
                              },
                              "stability": {
                                "type": "number"
                              },
                              "similarity": {
                                "type": "number"
                              },
                              "style": {
                                "type": "integer"
                              },
                              "speakerBoost": {
                                "type": "boolean"
                              },
                              "language": {
                                "type": "string"
                              },
                              "leveling": {
                                "type": "integer"
                              }
                            }
                          },
                          "creditsCost": {
                            "type": "integer"
                          },
                          "exportTranscript": {
                            "type": "boolean"
                          },
                          "createdAt": {
                            "type": "string",
                            "format": "date-time"
                          },
                          "output": {
                            "type": "object",
                            "properties": {
                              "audioUrl": {
                                "type": "string"
                              },
                              "srtUrl": {
                                "type": "string"
                              },
                              "wordsUrl": {
                                "type": "string"
                              },
                              "durationSec": {
                                "type": "number"
                              },
                              "downloadUrl": {
                                "type": "string"
                              },
                              "downloadUrlExpiresAt": {
                                "type": "string",
                                "format": "date-time"
                              }
                            }
                          },
                          "completedAt": {
                            "type": "string",
                            "format": "date-time"
                          },
                          "filesExpireAt": {
                            "type": "string",
                            "format": "date-time"
                          }
                        }
                      }
                    },
                    "total": {
                      "type": "integer"
                    },
                    "page": {
                      "type": "integer"
                    },
                    "pageSize": {
                      "type": "integer"
                    },
                    "hasMore": {
                      "type": "boolean"
                    }
                  }
                },
                "example": {
                  "items": [
                    {
                      "id": "tsk_24598d03cfcac9a82eec36f0",
                      "kind": "tts",
                      "provider": "elevenlabs",
                      "name": "Lời chào buổi sáng",
                      "text": "Xin chào, chúc bạn một ngày làm việc hiệu quả!",
                      "status": "completed",
                      "progress": 100,
                      "voiceId": "jdlxsPOZOHdGEfcItXVu",
                      "voiceName": "Hiền",
                      "modelId": "eleven_v4",
                      "language": "vi",
                      "settings": {
                        "speed": 1,
                        "stability": 0.5,
                        "similarity": 0.75,
                        "style": 0,
                        "speakerBoost": true,
                        "language": "vi",
                        "leveling": 0
                      },
                      "creditsCost": 500,
                      "exportTranscript": true,
                      "createdAt": "2026-10-02T08:00:00.000Z",
                      "output": {
                        "audioUrl": "/api/v1/audio/tsk_24598d03cfcac9a82eec36f0/audio.mp3",
                        "srtUrl": "/api/v1/audio/tsk_24598d03cfcac9a82eec36f0/transcript.srt",
                        "wordsUrl": "/api/v1/audio/tsk_24598d03cfcac9a82eec36f0/transcript.json",
                        "durationSec": 3.8,
                        "downloadUrl": "https://voice1.pro/api/v1/download/tsk_24598d03cfcac9a82eec36f0/audio.mp3?e=1791536400&s=8c1f0e5a2b7d4c9e3f6a1b8d0c5e2f7a9b4d6c1e3f8a0b5d2c7e9f1a4b6d8c0e",
                        "downloadUrlExpiresAt": "2026-10-09T09:00:00.000Z"
                      },
                      "completedAt": "2026-10-02T08:01:00.000Z",
                      "filesExpireAt": "2026-10-09T08:01:00.000Z"
                    }
                  ],
                  "total": 1,
                  "page": 1,
                  "pageSize": 10,
                  "hasMore": false
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized` — The API key is missing, invalid or revoked, or the account is locked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/history/{id}": {
      "get": {
        "operationId": "historyGet",
        "tags": [
          "History"
        ],
        "summary": "Get task",
        "description": "Returns the status, progress and file paths of a single task. To track progress, use Get task statuses instead of polling this endpoint.\n\nQueued or running tasks include `etaDoneMinSec` and `etaDoneMaxSec` — an estimated time range until completion, meant only for display and for spacing out polling. The failure reason is in `error`.\n\n`output.downloadUrl`: a full audio download link that opens directly with no Authorization header (for Make, Zapier, n8n, an <audio> tag). It expires at `output.downloadUrlExpiresAt` (at most 7 days) — call this endpoint again for a fresh link. Treat the link like a password: anyone who has it can download the file.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Task ID.",
            "example": "tsk_24598d03cfcac9a82eec36f0"
          }
        ],
        "responses": {
          "200": {
            "description": "Success.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string"
                    },
                    "kind": {
                      "type": "string"
                    },
                    "provider": {
                      "type": "string"
                    },
                    "name": {
                      "type": "string"
                    },
                    "text": {
                      "type": "string"
                    },
                    "status": {
                      "type": "string"
                    },
                    "progress": {
                      "type": "integer"
                    },
                    "voiceId": {
                      "type": "string"
                    },
                    "voiceName": {
                      "type": "string"
                    },
                    "modelId": {
                      "type": "string"
                    },
                    "language": {
                      "type": "string"
                    },
                    "settings": {
                      "type": "object",
                      "properties": {
                        "speed": {
                          "type": "integer"
                        },
                        "stability": {
                          "type": "number"
                        },
                        "similarity": {
                          "type": "number"
                        },
                        "style": {
                          "type": "integer"
                        },
                        "speakerBoost": {
                          "type": "boolean"
                        },
                        "language": {
                          "type": "string"
                        },
                        "leveling": {
                          "type": "integer"
                        }
                      }
                    },
                    "creditsCost": {
                      "type": "integer"
                    },
                    "exportTranscript": {
                      "type": "boolean"
                    },
                    "createdAt": {
                      "type": "string",
                      "format": "date-time"
                    },
                    "output": {
                      "type": "object",
                      "properties": {
                        "audioUrl": {
                          "type": "string"
                        },
                        "srtUrl": {
                          "type": "string"
                        },
                        "wordsUrl": {
                          "type": "string"
                        },
                        "durationSec": {
                          "type": "number"
                        },
                        "downloadUrl": {
                          "type": "string"
                        },
                        "downloadUrlExpiresAt": {
                          "type": "string",
                          "format": "date-time"
                        }
                      }
                    },
                    "completedAt": {
                      "type": "string",
                      "format": "date-time"
                    },
                    "filesExpireAt": {
                      "type": "string",
                      "format": "date-time"
                    }
                  }
                },
                "example": {
                  "id": "tsk_24598d03cfcac9a82eec36f0",
                  "kind": "tts",
                  "provider": "elevenlabs",
                  "name": "Lời chào buổi sáng",
                  "text": "Xin chào, chúc bạn một ngày làm việc hiệu quả!",
                  "status": "completed",
                  "progress": 100,
                  "voiceId": "jdlxsPOZOHdGEfcItXVu",
                  "voiceName": "Hiền",
                  "modelId": "eleven_v4",
                  "language": "vi",
                  "settings": {
                    "speed": 1,
                    "stability": 0.5,
                    "similarity": 0.75,
                    "style": 0,
                    "speakerBoost": true,
                    "language": "vi",
                    "leveling": 0
                  },
                  "creditsCost": 500,
                  "exportTranscript": true,
                  "createdAt": "2026-10-02T08:00:00.000Z",
                  "output": {
                    "audioUrl": "/api/v1/audio/tsk_24598d03cfcac9a82eec36f0/audio.mp3",
                    "srtUrl": "/api/v1/audio/tsk_24598d03cfcac9a82eec36f0/transcript.srt",
                    "wordsUrl": "/api/v1/audio/tsk_24598d03cfcac9a82eec36f0/transcript.json",
                    "durationSec": 3.8,
                    "downloadUrl": "https://voice1.pro/api/v1/download/tsk_24598d03cfcac9a82eec36f0/audio.mp3?e=1791536400&s=8c1f0e5a2b7d4c9e3f6a1b8d0c5e2f7a9b4d6c1e3f8a0b5d2c7e9f1a4b6d8c0e",
                    "downloadUrlExpiresAt": "2026-10-09T09:00:00.000Z"
                  },
                  "completedAt": "2026-10-02T08:01:00.000Z",
                  "filesExpireAt": "2026-10-09T08:01:00.000Z"
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized` — The API key is missing, invalid or revoked, or the account is locked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "`task_not_found` — No task with this ID: the ID is wrong, the task belongs to another account, or it was deleted.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "delete": {
        "operationId": "historyDelete",
        "tags": [
          "History"
        ],
        "summary": "Delete task",
        "description": "Permanently deletes a task and its files.\n\nA queued or running task is cancelled, fully refunded and then deleted outright — there is no 'cancelled' status to track. Afterwards GET /v1/history/{id} returns 404 task_not_found and /v1/history/status no longer returns this ID.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Task ID.",
            "example": "tsk_24598d03cfcac9a82eec36f0"
          }
        ],
        "responses": {
          "204": {
            "description": "Success, no content."
          },
          "401": {
            "description": "`unauthorized` — The API key is missing, invalid or revoked, or the account is locked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "`forbidden_origin` — Only seen when calling from a browser: a write request (POST, DELETE) that did not come from our website. Call from your server.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "`task_not_found` — No task with this ID: the ID is wrong, the task belongs to another account, or it was deleted.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/history/{id}/retry": {
      "post": {
        "operationId": "historyRetry",
        "tags": [
          "History"
        ],
        "summary": "Retry task",
        "description": "Re-runs a failed task with the same parameters. Credits are charged again as for a new task (the previous charge was refunded).\n\nIf the task is already queued or running (for example, another request just retried it), it is returned as is with 200 + `Idempotent-Replay: true` header, and no credits are charged.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Task ID.",
            "example": "tsk_24598d03cfcac9a82eec36f0"
          }
        ],
        "responses": {
          "200": {
            "description": "Success.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string"
                    },
                    "kind": {
                      "type": "string"
                    },
                    "provider": {
                      "type": "string"
                    },
                    "name": {
                      "type": "string"
                    },
                    "text": {
                      "type": "string"
                    },
                    "status": {
                      "type": "string"
                    },
                    "progress": {
                      "type": "integer"
                    },
                    "voiceId": {
                      "type": "string"
                    },
                    "voiceName": {
                      "type": "string"
                    },
                    "modelId": {
                      "type": "string"
                    },
                    "language": {
                      "type": "string"
                    },
                    "settings": {
                      "type": "object",
                      "properties": {
                        "speed": {
                          "type": "integer"
                        },
                        "stability": {
                          "type": "number"
                        },
                        "similarity": {
                          "type": "number"
                        },
                        "style": {
                          "type": "integer"
                        },
                        "speakerBoost": {
                          "type": "boolean"
                        },
                        "language": {
                          "type": "string"
                        },
                        "leveling": {
                          "type": "integer"
                        }
                      }
                    },
                    "creditsCost": {
                      "type": "integer"
                    },
                    "exportTranscript": {
                      "type": "boolean"
                    },
                    "createdAt": {
                      "type": "string",
                      "format": "date-time"
                    }
                  }
                },
                "example": {
                  "id": "tsk_24598d03cfcac9a82eec36f0",
                  "kind": "tts",
                  "provider": "elevenlabs",
                  "name": "Lời chào buổi sáng",
                  "text": "Xin chào, chúc bạn một ngày làm việc hiệu quả!",
                  "status": "queued",
                  "progress": 0,
                  "voiceId": "jdlxsPOZOHdGEfcItXVu",
                  "voiceName": "Hiền",
                  "modelId": "eleven_v4",
                  "language": "vi",
                  "settings": {
                    "speed": 1,
                    "stability": 0.5,
                    "similarity": 0.75,
                    "style": 0,
                    "speakerBoost": true,
                    "language": "vi",
                    "leveling": 0
                  },
                  "creditsCost": 500,
                  "exportTranscript": true,
                  "createdAt": "2026-10-02T08:00:00.000Z"
                }
              }
            }
          },
          "400": {
            "description": "`task_not_retryable` — Only `failed` tasks can be retried. For a completed task, create a new one.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized` — The API key is missing, invalid or revoked, or the account is locked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "402": {
            "description": "`insufficient_credits` — Not enough credits. No task is created and no credits are charged.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "`forbidden_origin` — Only seen when calling from a browser: a write request (POST, DELETE) that did not come from our website. Call from your server.\n\n`content_hold` — Task creation via the API is paused because many recent requests were rejected for their text content (`content_blocked` errors). No credits are charged — review your text and retry after the `Retry-After` seconds (15 minutes, longer if it repeats).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "`task_not_found` — No task with this ID: the ID is wrong, the task belongs to another account, or it was deleted.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "`task_conflict` — Rare: the task changed state because of another request running concurrently. No credits are charged — reload and try again.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited` — More than about 600 tasks created per minute (test keys `vs_test_`: 30). Wait the number of seconds in the `Retry-After` header, then resend.\n\n`queue_full` — 1,000 tasks created with API keys are already waiting (for batch creation: waiting tasks + files in the batch exceed this). Nothing is created and no credits are charged — wait for some to finish, then resend after the `Retry-After` seconds.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds to wait."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "`tasks_disabled` — Speech generation is temporarily paused for maintenance. No credits are charged — try again later.\n\n`system_busy` — The system is overloaded and is temporarily not accepting new tasks via the API. No credits are charged — retry after the `Retry-After` seconds, with increasing delays.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/history/status": {
      "post": {
        "operationId": "historyStatus",
        "tags": [
          "History"
        ],
        "summary": "Get task statuses",
        "description": "The recommended way to track progress: fetch a compact status for up to 300 tasks in a single call.\n\nUse this endpoint instead of polling /v1/history/{id} for each task.\n\nWhile a task is queued or running, the response includes `etaDoneMinSec` and `etaDoneMaxSec` (seconds, rounded estimates) — use them to space out your polling instead of polling at a fixed interval.\n\nOnce `completed`, the response includes `audioUrl` (plus `srtUrl` and `wordsUrl` if subtitles were exported) — relative paths to join with the API origin — and `downloadUrl`: a full download link that needs no Authorization header. These fields disappear once the files have expired.\n\nDeleted tasks are left out of `items` — your polling loop needs to handle this case.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "ids": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    },
                    "description": "From 1 to 300 task IDs, each of the form tsk_ + 24 hex characters (test keys: tsk_test_ + 24 hex). A single malformed ID fails the whole request with 400. IDs that don't exist or belong to another account are ignored."
                  }
                },
                "required": [
                  "ids"
                ]
              },
              "example": {
                "ids": [
                  "tsk_24598d03cfcac9a82eec36f0",
                  "tsk_8a3f1c6e2b9d4f7a0c5e1b3d"
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Success.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "items": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string"
                          },
                          "status": {
                            "type": "string"
                          },
                          "progress": {
                            "type": "integer"
                          },
                          "name": {
                            "type": "string"
                          },
                          "audioUrl": {
                            "type": "string"
                          },
                          "srtUrl": {
                            "type": "string"
                          },
                          "wordsUrl": {
                            "type": "string"
                          },
                          "durationSec": {
                            "type": "integer"
                          },
                          "downloadUrl": {
                            "type": "string"
                          },
                          "downloadUrlExpiresAt": {
                            "type": "string",
                            "format": "date-time"
                          },
                          "etaDoneMinSec": {
                            "type": "integer"
                          },
                          "etaDoneMaxSec": {
                            "type": "integer"
                          },
                          "error": {
                            "type": "string"
                          },
                          "creditsRefunded": {
                            "type": "integer"
                          }
                        }
                      }
                    }
                  }
                },
                "example": {
                  "items": [
                    {
                      "id": "tsk_24598d03cfcac9a82eec36f0",
                      "status": "completed",
                      "progress": 100,
                      "name": "Lời chào buổi sáng",
                      "audioUrl": "/api/v1/audio/tsk_24598d03cfcac9a82eec36f0/audio.mp3",
                      "srtUrl": "/api/v1/audio/tsk_24598d03cfcac9a82eec36f0/transcript.srt",
                      "wordsUrl": "/api/v1/audio/tsk_24598d03cfcac9a82eec36f0/transcript.json",
                      "durationSec": 47,
                      "downloadUrl": "https://voice1.pro/api/v1/download/tsk_24598d03cfcac9a82eec36f0/audio.mp3?e=1791536400&s=8c1f0e5a2b7d4c9e3f6a1b8d0c5e2f7a9b4d6c1e3f8a0b5d2c7e9f1a4b6d8c0e",
                      "downloadUrlExpiresAt": "2026-10-09T09:00:00.000Z"
                    },
                    {
                      "id": "tsk_8a3f1c6e2b9d4f7a0c5e1b3d",
                      "status": "processing",
                      "progress": 40,
                      "name": "Chương 2",
                      "etaDoneMinSec": 30,
                      "etaDoneMaxSec": 60
                    },
                    {
                      "id": "tsk_3c7e9a1b5d2f8e0a4c6b9d1e",
                      "status": "failed",
                      "progress": 0,
                      "name": "Chương 3",
                      "error": "Chưa tạo được bản thu lúc này, vui lòng thử lại sau. Credits đã được hoàn lại.",
                      "creditsRefunded": 1520
                    }
                  ]
                }
              }
            }
          },
          "400": {
            "description": "`bad_request` — A required field is missing, a value has the wrong type, or a limit was exceeded (including text that is too long). `message` explains what is wrong.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized` — The API key is missing, invalid or revoked, or the account is locked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "`forbidden_origin` — Only seen when calling from a browser: a write request (POST, DELETE) that did not come from our website. Call from your server.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "413": {
            "description": "`payload_too_large` — The body exceeds 10 KB. 300 IDs as compact JSON (no indentation) take only about 9.3 KB, but pretty-printed JSON with indentation and line breaks can go over the limit — send compact JSON or split the list.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "415": {
            "description": "`unsupported_media_type` — `Content-Type: application/json` is missing.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/history/queue": {
      "get": {
        "operationId": "historyQueue",
        "tags": [
          "History"
        ],
        "summary": "Get your queue",
        "description": "Your queued tasks (up to 200), in the order they will be processed.\n\n`voiceName` may be null when the task was created without a voice name. `chars` is the number of spoken-text characters.",
        "responses": {
          "200": {
            "description": "Success.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "items": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string"
                          },
                          "kind": {
                            "type": "string"
                          },
                          "name": {
                            "type": "string"
                          },
                          "voiceName": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "chars": {
                            "type": "integer"
                          },
                          "position": {
                            "type": "integer"
                          }
                        }
                      }
                    }
                  }
                },
                "example": {
                  "items": [
                    {
                      "id": "tsk_5e0c2a7b9d1f3e4a6b8c0d2e",
                      "kind": "tts",
                      "name": "Chương 1",
                      "voiceName": "Hiền",
                      "chars": 21,
                      "position": 1
                    },
                    {
                      "id": "tsk_8a3f1c6e2b9d4f7a0c5e1b3d",
                      "kind": "tts",
                      "name": "Chương 2",
                      "voiceName": null,
                      "chars": 21,
                      "position": 2
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized` — The API key is missing, invalid or revoked, or the account is locked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/history/queue-order": {
      "post": {
        "operationId": "historyQueueOrder",
        "tags": [
          "History"
        ],
        "summary": "Reorder queue",
        "description": "Changes the processing order of your queued tasks.\n\nThe response is the full queue after reordering, in the same shape as GET /v1/history/queue.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "ids": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    },
                    "description": "The desired order: from 2 to 200 IDs of the form tsk_ + 24 hex characters (test keys: tsk_test_…). Malformed IDs → 400; tasks that have already started or belong to another account are ignored."
                  }
                },
                "required": [
                  "ids"
                ]
              },
              "example": {
                "ids": [
                  "tsk_8a3f1c6e2b9d4f7a0c5e1b3d",
                  "tsk_5e0c2a7b9d1f3e4a6b8c0d2e"
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Success.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "items": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string"
                          },
                          "kind": {
                            "type": "string"
                          },
                          "name": {
                            "type": "string"
                          },
                          "voiceName": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "chars": {
                            "type": "integer"
                          },
                          "position": {
                            "type": "integer"
                          }
                        }
                      }
                    }
                  }
                },
                "example": {
                  "items": [
                    {
                      "id": "tsk_8a3f1c6e2b9d4f7a0c5e1b3d",
                      "kind": "tts",
                      "name": "Chương 2",
                      "voiceName": null,
                      "chars": 21,
                      "position": 1
                    },
                    {
                      "id": "tsk_5e0c2a7b9d1f3e4a6b8c0d2e",
                      "kind": "tts",
                      "name": "Chương 1",
                      "voiceName": "Hiền",
                      "chars": 21,
                      "position": 2
                    }
                  ]
                }
              }
            }
          },
          "400": {
            "description": "`bad_request` — A required field is missing, a value has the wrong type, or a limit was exceeded (including text that is too long). `message` explains what is wrong.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized` — The API key is missing, invalid or revoked, or the account is locked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "`forbidden_origin` — Only seen when calling from a browser: a write request (POST, DELETE) that did not come from our website. Call from your server.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "415": {
            "description": "`unsupported_media_type` — `Content-Type: application/json` is missing.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/history/bulk-delete": {
      "post": {
        "operationId": "historyBulkDelete",
        "tags": [
          "History"
        ],
        "summary": "Delete tasks in bulk",
        "description": "Delete up to 100 tasks in a single call.\n\nQueued or running tasks are cancelled, fully refunded and deleted outright — same as Delete task.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "ids": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    },
                    "description": "From 1 to 100 IDs of the form tsk_ + 24 hex characters (test keys: tsk_test_…). Malformed IDs → 400; IDs that don't exist or belong to another account are ignored."
                  }
                },
                "required": [
                  "ids"
                ]
              },
              "example": {
                "ids": [
                  "tsk_24598d03cfcac9a82eec36f0"
                ]
              }
            }
          }
        },
        "responses": {
          "204": {
            "description": "Success, no content."
          },
          "400": {
            "description": "`bad_request` — A required field is missing, a value has the wrong type, or a limit was exceeded (including text that is too long). `message` explains what is wrong.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized` — The API key is missing, invalid or revoked, or the account is locked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "`forbidden_origin` — Only seen when calling from a browser: a write request (POST, DELETE) that did not come from our website. Call from your server.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "415": {
            "description": "`unsupported_media_type` — `Content-Type: application/json` is missing.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/audio/{taskId}/{file}": {
      "get": {
        "operationId": "audioGet",
        "tags": [
          "Files"
        ],
        "summary": "Download output file",
        "description": "Downloads the audio, subtitles or word-level timestamps of a completed task.\n\nAlways check the HTTP status before writing the file: on error, the body is JSON, not audio.\n\nCan't send headers (Make, Zapier, n8n, a browser)? Use the task's `output.downloadUrl` — a full download link that needs no key.\n\nSupports resuming downloads with the `Range` header (returns 206) and change detection with `ETag` / `If-None-Match` (returns 304).\n\nFiles are deleted automatically 7 days after the task completes — download and store any you want to keep.",
        "parameters": [
          {
            "name": "taskId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Task ID.",
            "example": "tsk_24598d03cfcac9a82eec36f0"
          },
          {
            "name": "file",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^(audio\\.mp3|audio\\.wav|transcript\\.srt|transcript\\.json|turn-[1-9][0-9]*\\.mp3|turn-[1-9][0-9]*\\.wav)$",
              "examples": [
                "audio.mp3",
                "audio.wav",
                "transcript.srt",
                "transcript.json"
              ]
            },
            "description": "File name. `audio.mp3` or `audio.wav` is the recording — the recording may be MP3 or WAV, so always use the exact path in `audioUrl` instead of building the name yourself; `transcript.srt` is the subtitles; `transcript.json` holds word-level timestamps. `turn-<n>.mp3` or `turn-<n>.wav` is a single dialogue turn, numbered from 1 (the paths are listed in `output.turnUrls`).",
            "example": "audio.mp3"
          },
          {
            "name": "download",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": "File name to save as (the response includes Content-Disposition: attachment)."
          }
        ],
        "responses": {
          "200": {
            "description": "The output file.",
            "content": {
              "audio/mpeg": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              },
              "audio/wav": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              },
              "application/x-subrip": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              },
              "application/json": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized` — The API key is missing, invalid or revoked, or the account is locked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "`not_found` — The file doesn't exist: the ID is wrong, the task belongs to another account, isn't complete or failed, or subtitles weren't exported.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "410": {
            "description": "`files_expired` — The file passed its 7-day retention period and was deleted. The history entry remains.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "`audio_unavailable` — The file is temporarily unavailable (rare). Try again later.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/packages": {
      "get": {
        "operationId": "packagesList",
        "tags": [
          "Account"
        ],
        "summary": "List credit packages",
        "description": "Credit packages currently on sale, with their credit amounts and prices in VND.\n\nCredits received on purchase = `credits` + `bonusCredits`. `isPopular` is only present on the recommended package. `name`, `description` and `features` are Vietnamese display text; the optional `en` holds English versions (fall back to Vietnamese for missing fields). The optional `audioHours` is an approximate hours-of-audio figure. Packages and prices can change at any time — always read them from this endpoint instead of hard-coding them. The example shows only 2 of the packages on sale.\n\n1 credit = 1 character, minimum 500 credits per task created with an API key (see Limits & pricing for how characters are counted). New accounts get 3,000 free credits to try the API. Packages can only be purchased on the web.",
        "security": [],
        "responses": {
          "200": {
            "description": "Success.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "type": "object",
                    "properties": {
                      "id": {
                        "type": "string"
                      },
                      "name": {
                        "type": "string"
                      },
                      "description": {
                        "type": "string"
                      },
                      "credits": {
                        "type": "integer"
                      },
                      "bonusCredits": {
                        "type": "integer"
                      },
                      "price": {
                        "type": "integer"
                      },
                      "currency": {
                        "type": "string"
                      },
                      "audioHours": {
                        "type": "integer"
                      },
                      "en": {
                        "type": "object",
                        "properties": {
                          "name": {
                            "type": "string"
                          },
                          "description": {
                            "type": "string"
                          }
                        }
                      },
                      "features": {
                        "type": "array",
                        "items": {
                          "type": "string"
                        }
                      },
                      "isPopular": {
                        "type": "boolean"
                      }
                    }
                  }
                },
                "example": [
                  {
                    "id": "pkg-khoi-dau",
                    "name": "Khởi đầu",
                    "description": "Vừa đủ để thử mọi công cụ và làm vài video đầu tiên.",
                    "credits": 300000,
                    "bonusCredits": 0,
                    "price": 99000,
                    "currency": "VND",
                    "audioHours": 6,
                    "en": {
                      "name": "Starter",
                      "description": "Just enough to try every tool and make your first few videos."
                    },
                    "features": [
                      "Giọng ElevenLabs chất lượng cao",
                      "Dùng mọi công cụ giọng nói trên Voice1",
                      "Xuất MP3 và phụ đề SRT",
                      "Dùng được qua API",
                      "Credits không hết hạn"
                    ]
                  },
                  {
                    "id": "pkg-sang-tao",
                    "name": "Sáng tạo",
                    "description": "Lựa chọn của đa số nhà sáng tạo nội dung đăng bài đều đặn.",
                    "credits": 900000,
                    "bonusCredits": 100000,
                    "price": 249000,
                    "currency": "VND",
                    "isPopular": true,
                    "audioHours": 20,
                    "features": [
                      "Bao gồm mọi tính năng gói Khởi đầu",
                      "Dùng được qua API",
                      "Credits không hết hạn"
                    ]
                  }
                ]
              }
            }
          }
        }
      }
    },
    "/v1/dialogue": {
      "post": {
        "operationId": "dialogueCreate",
        "tags": [
          "Dialogue"
        ],
        "summary": "Create dialogue",
        "description": "Turns a multi-character script into a single audio file. Each line has the form \"Name: line\".\n\nReturns 201 when a new task is created. Supports the `Idempotency-Key` header just like Create speech: resending with the same key → 200 + `Idempotent-Replay: true`, with no second charge.\n\nCost is based on the spoken text (for lines matched to a speaker, the \"Name:\" prefix is not counted). Each line is billed at least 200 characters: shorter lines count as 200, longer lines are billed by their actual length. Each line is rounded up, then summed; the total is still at least 500 credits per task.",
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string",
              "minLength": 8,
              "maxLength": 128,
              "pattern": "^[A-Za-z0-9._:-]+$"
            },
            "description": "Resending the same key returns the task already created, without charging again."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string",
                    "description": "Recording name (up to 120 characters). If omitted, a name is generated from the speaker names, e.g. \"Hội thoại An & Bình\"."
                  },
                  "script": {
                    "type": "string",
                    "description": "The script, one turn per line, in the form \"Name: line\" or \"[Name] line\". Up to 200 turns and 250,000 characters of spoken text."
                  },
                  "speakers": {
                    "type": "array",
                    "items": {
                      "type": "object",
                      "properties": {
                        "provider": {
                          "type": "string",
                          "enum": [
                            "elevenlabs"
                          ],
                          "description": "The engine of the speaker's voice."
                        },
                        "voiceId": {
                          "type": "string",
                          "description": "Voice ID from GET /v1/voices."
                        },
                        "modelId": {
                          "type": "string",
                          "description": "Model ID; must belong to the speaker's engine."
                        },
                        "name": {
                          "type": "string",
                          "description": "The name used in the script (up to 40 characters). Matching ignores case and Vietnamese diacritics; an empty name matches no lines. Labels in the script must match this name (e.g. speaker \"Lan\" → write \"Lan:\", not \"Nữ:\")."
                        },
                        "id": {
                          "type": "string",
                          "description": "Speaker ID (up to 64 characters). Script lines that use this exact ID are also assigned to this speaker."
                        },
                        "voiceName": {
                          "type": "string",
                          "description": "Voice display name (up to 120 characters)."
                        },
                        "settings": {
                          "type": "object",
                          "properties": {
                            "speed": {
                              "type": "integer"
                            },
                            "stability": {
                              "type": "number"
                            },
                            "similarity": {
                              "type": "number"
                            },
                            "style": {
                              "type": "integer"
                            },
                            "speakerBoost": {
                              "type": "boolean"
                            },
                            "language": {
                              "type": "string"
                            },
                            "leveling": {
                              "type": "integer"
                            }
                          },
                          "description": "Voice settings, as in Create speech. Up to 4,096 bytes of JSON per speaker; larger settings → 400."
                        }
                      },
                      "required": [
                        "provider",
                        "voiceId",
                        "modelId"
                      ]
                    },
                    "description": "From 1 to 20 speakers. Speakers without a voiceId are ignored."
                  },
                  "pauseBetweenTurns": {
                    "type": "number",
                    "description": "Pause between turns, from 0 to 5 seconds. Out-of-range or non-numeric values → 400. Omit to use the default."
                  },
                  "exportTranscript": {
                    "type": "boolean",
                    "description": "Also export SRT subtitles (5% surcharge). Defaults to false."
                  },
                  "unmatchedLines": {
                    "type": "string",
                    "enum": [
                      "reject",
                      "read"
                    ],
                    "description": "Defaults to 'reject': if some lines would be read wrong (a label matching no speaker, a time / number before the name, SRT lines, [..] tags on a model that does not support them) → 400 dialogue_script_issues, no credits charged. 'read': read those lines as written (label included) with the rotating voice. [..] tags only work on Eleven v4 / v4 Turbo / v3 and must come after \"Name:\"; text in round brackets (..) is always read aloud."
                  }
                },
                "required": [
                  "script",
                  "speakers"
                ]
              },
              "example": {
                "name": "Podcast cà phê sáng",
                "script": "An: Hôm nay mình nói về cà phê nhé?\nBình: Tuyệt, mình mang phin theo rồi!",
                "speakers": [
                  {
                    "id": "an",
                    "name": "An",
                    "provider": "elevenlabs",
                    "voiceId": "jdlxsPOZOHdGEfcItXVu",
                    "voiceName": "Hiền",
                    "modelId": "eleven_v4",
                    "settings": {
                      "speed": 1,
                      "stability": 0.5,
                      "similarity": 0.75,
                      "style": 0,
                      "speakerBoost": true,
                      "language": "vi",
                      "leveling": 0
                    }
                  },
                  {
                    "id": "binh",
                    "name": "Bình",
                    "provider": "elevenlabs",
                    "voiceId": "ZsjEJaLQy3sgvwxicmDx",
                    "voiceName": "Quang Toàn",
                    "modelId": "eleven_v4",
                    "settings": {
                      "speed": 1,
                      "stability": 0.5,
                      "similarity": 0.75,
                      "style": 0,
                      "speakerBoost": true,
                      "language": "vi",
                      "leveling": 0
                    }
                  }
                ],
                "pauseBetweenTurns": 0.4,
                "exportTranscript": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Replay: the task created earlier with the same Idempotency-Key (batch: every file matched a requestKey, created = 0). No extra credits charged.",
            "headers": {
              "Idempotent-Replay": {
                "schema": {
                  "type": "string",
                  "enum": [
                    "true"
                  ]
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string"
                    },
                    "kind": {
                      "type": "string"
                    },
                    "provider": {
                      "type": "string"
                    },
                    "name": {
                      "type": "string"
                    },
                    "text": {
                      "type": "string"
                    },
                    "status": {
                      "type": "string"
                    },
                    "progress": {
                      "type": "integer"
                    },
                    "voiceId": {
                      "type": "string"
                    },
                    "voiceName": {
                      "type": "string"
                    },
                    "modelId": {
                      "type": "string"
                    },
                    "language": {
                      "type": "string"
                    },
                    "settings": {
                      "type": "object",
                      "properties": {
                        "speed": {
                          "type": "integer"
                        },
                        "stability": {
                          "type": "number"
                        },
                        "similarity": {
                          "type": "number"
                        },
                        "style": {
                          "type": "integer"
                        },
                        "speakerBoost": {
                          "type": "boolean"
                        },
                        "language": {
                          "type": "string"
                        },
                        "leveling": {
                          "type": "integer"
                        }
                      }
                    },
                    "creditsCost": {
                      "type": "integer"
                    },
                    "exportTranscript": {
                      "type": "boolean"
                    },
                    "createdAt": {
                      "type": "string",
                      "format": "date-time"
                    }
                  }
                },
                "example": {
                  "id": "tsk_3d9b7e1f5a2c8e0b4d6f1a3c",
                  "kind": "dialogue",
                  "provider": "elevenlabs",
                  "name": "Podcast cà phê sáng",
                  "text": "An: Hôm nay mình nói về cà phê nhé?\nBình: Tuyệt, mình mang phin theo rồi!",
                  "status": "queued",
                  "progress": 0,
                  "voiceId": "jdlxsPOZOHdGEfcItXVu",
                  "voiceName": "An & Bình",
                  "modelId": "eleven_v4",
                  "language": "vi",
                  "settings": {
                    "speed": 1,
                    "stability": 0.5,
                    "similarity": 0.75,
                    "style": 0,
                    "speakerBoost": true,
                    "language": "vi",
                    "leveling": 0
                  },
                  "creditsCost": 500,
                  "exportTranscript": false,
                  "createdAt": "2026-10-02T08:00:00.000Z"
                }
              }
            }
          },
          "201": {
            "description": "Success.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string"
                    },
                    "kind": {
                      "type": "string"
                    },
                    "provider": {
                      "type": "string"
                    },
                    "name": {
                      "type": "string"
                    },
                    "text": {
                      "type": "string"
                    },
                    "status": {
                      "type": "string"
                    },
                    "progress": {
                      "type": "integer"
                    },
                    "voiceId": {
                      "type": "string"
                    },
                    "voiceName": {
                      "type": "string"
                    },
                    "modelId": {
                      "type": "string"
                    },
                    "language": {
                      "type": "string"
                    },
                    "settings": {
                      "type": "object",
                      "properties": {
                        "speed": {
                          "type": "integer"
                        },
                        "stability": {
                          "type": "number"
                        },
                        "similarity": {
                          "type": "number"
                        },
                        "style": {
                          "type": "integer"
                        },
                        "speakerBoost": {
                          "type": "boolean"
                        },
                        "language": {
                          "type": "string"
                        },
                        "leveling": {
                          "type": "integer"
                        }
                      }
                    },
                    "creditsCost": {
                      "type": "integer"
                    },
                    "exportTranscript": {
                      "type": "boolean"
                    },
                    "createdAt": {
                      "type": "string",
                      "format": "date-time"
                    }
                  }
                },
                "example": {
                  "id": "tsk_3d9b7e1f5a2c8e0b4d6f1a3c",
                  "kind": "dialogue",
                  "provider": "elevenlabs",
                  "name": "Podcast cà phê sáng",
                  "text": "An: Hôm nay mình nói về cà phê nhé?\nBình: Tuyệt, mình mang phin theo rồi!",
                  "status": "queued",
                  "progress": 0,
                  "voiceId": "jdlxsPOZOHdGEfcItXVu",
                  "voiceName": "An & Bình",
                  "modelId": "eleven_v4",
                  "language": "vi",
                  "settings": {
                    "speed": 1,
                    "stability": 0.5,
                    "similarity": 0.75,
                    "style": 0,
                    "speakerBoost": true,
                    "language": "vi",
                    "leveling": 0
                  },
                  "creditsCost": 500,
                  "exportTranscript": false,
                  "createdAt": "2026-10-02T08:00:00.000Z"
                }
              }
            }
          },
          "400": {
            "description": "`bad_request` — A required field is missing, a value has the wrong type, or a limit was exceeded (including text that is too long). `message` explains what is wrong.\n\n`dialogue_script_issues` — Some lines would be read wrong: a label matching no speaker (the word \"Nữ:\" itself would be spoken), a time / number before the name, SRT subtitle lines, or [..] tags on a model that does not support them. The message lists the line numbers. No credits are charged. Fix the script, or send unmatchedLines: \"read\" to read them as written.\n\n`invalid_model` — `modelId` does not exist or does not belong to the selected engine.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized` — The API key is missing, invalid or revoked, or the account is locked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "402": {
            "description": "`insufficient_credits` — Not enough credits. No task is created and no credits are charged.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "`forbidden_origin` — Only seen when calling from a browser: a write request (POST, DELETE) that did not come from our website. Call from your server.\n\n`content_hold` — Task creation via the API is paused because many recent requests were rejected for their text content (`content_blocked` errors). No credits are charged — review your text and retry after the `Retry-After` seconds (15 minutes, longer if it repeats).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "`idempotency_key_reused` — This Idempotency-Key was already used for a different request (different text, voice or model). Nothing is created and no credits are charged — use a new key for each new request.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "413": {
            "description": "`payload_too_large` — The body exceeds 10 MB. Text over the character limit returns 400 bad_request, not 413.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "415": {
            "description": "`unsupported_media_type` — `Content-Type: application/json` is missing.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited` — More than about 600 tasks created per minute (test keys `vs_test_`: 30). Wait the number of seconds in the `Retry-After` header, then resend.\n\n`queue_full` — 1,000 tasks created with API keys are already waiting (for batch creation: waiting tasks + files in the batch exceed this). Nothing is created and no credits are charged — wait for some to finish, then resend after the `Retry-After` seconds.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds to wait."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "`tasks_disabled` — Speech generation is temporarily paused for maintenance. No credits are charged — try again later.\n\n`system_busy` — The system is overloaded and is temporarily not accepting new tasks via the API. No credits are charged — retry after the `Retry-After` seconds, with increasing delays.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    }
  },
  "webhooks": {
    "task.completed": {
      "post": {
        "operationId": "taskCompletedWebhook",
        "summary": "task.completed",
        "parameters": [
          {
            "name": "Voice1-Signature",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "t=<unix seconds>,v1=<hex HMAC-SHA256>"
          },
          {
            "name": "Voice1-Event",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Voice1-Delivery",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "description": "Sent to the account webhook URL. Header Voice1-Signature: t=<seconds>,v1=<HMAC-SHA256 hex of \"<t>.<body>\" with the whsec_… secret>. Answer 2xx within 10 seconds.",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "id",
                  "type",
                  "createdAt",
                  "data"
                ],
                "properties": {
                  "id": {
                    "type": "string",
                    "example": "evt_9f2c41d07a3b5e8c1d6f0a24"
                  },
                  "type": {
                    "type": "string",
                    "enum": [
                      "task.completed"
                    ]
                  },
                  "createdAt": {
                    "type": "string",
                    "format": "date-time"
                  },
                  "data": {
                    "type": "object",
                    "properties": {
                      "task": {
                        "$ref": "#/components/schemas/Task"
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Received."
          }
        }
      }
    },
    "task.failed": {
      "post": {
        "operationId": "taskFailedWebhook",
        "summary": "task.failed",
        "parameters": [
          {
            "name": "Voice1-Signature",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "t=<unix seconds>,v1=<hex HMAC-SHA256>"
          },
          {
            "name": "Voice1-Event",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Voice1-Delivery",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "description": "Sent to the account webhook URL. Header Voice1-Signature: t=<seconds>,v1=<HMAC-SHA256 hex of \"<t>.<body>\" with the whsec_… secret>. Answer 2xx within 10 seconds.",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "id",
                  "type",
                  "createdAt",
                  "data"
                ],
                "properties": {
                  "id": {
                    "type": "string",
                    "example": "evt_9f2c41d07a3b5e8c1d6f0a24"
                  },
                  "type": {
                    "type": "string",
                    "enum": [
                      "task.failed"
                    ]
                  },
                  "createdAt": {
                    "type": "string",
                    "format": "date-time"
                  },
                  "data": {
                    "type": "object",
                    "properties": {
                      "task": {
                        "$ref": "#/components/schemas/Task"
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Received."
          }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "bearerAuth": {
        "type": "http",
        "scheme": "bearer",
        "description": "API key: vs_live_… (live) or vs_test_… (sandbox, free)."
      }
    },
    "schemas": {
      "Task": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "kind": {
            "type": "string"
          },
          "provider": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "text": {
            "type": "string"
          },
          "status": {
            "type": "string"
          },
          "progress": {
            "type": "integer"
          },
          "voiceId": {
            "type": "string"
          },
          "voiceName": {
            "type": "string"
          },
          "modelId": {
            "type": "string"
          },
          "language": {
            "type": "string"
          },
          "settings": {
            "type": "object",
            "properties": {
              "speed": {
                "type": "integer"
              },
              "stability": {
                "type": "number"
              },
              "similarity": {
                "type": "number"
              },
              "style": {
                "type": "integer"
              },
              "speakerBoost": {
                "type": "boolean"
              },
              "language": {
                "type": "string"
              },
              "leveling": {
                "type": "integer"
              }
            }
          },
          "creditsCost": {
            "type": "integer"
          },
          "exportTranscript": {
            "type": "boolean"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "output": {
            "type": "object",
            "properties": {
              "audioUrl": {
                "type": "string"
              },
              "srtUrl": {
                "type": "string"
              },
              "wordsUrl": {
                "type": "string"
              },
              "durationSec": {
                "type": "number"
              },
              "downloadUrl": {
                "type": "string"
              },
              "downloadUrlExpiresAt": {
                "type": "string",
                "format": "date-time"
              }
            }
          },
          "completedAt": {
            "type": "string",
            "format": "date-time"
          },
          "filesExpireAt": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "Error": {
        "type": "object",
        "required": [
          "code",
          "message"
        ],
        "properties": {
          "code": {
            "type": "string",
            "description": "Stable error code — use it in your logic."
          },
          "message": {
            "type": "string",
            "description": "Display message, follows Accept-Language."
          }
        }
      }
    }
  }
}
