curl --request GET \
--url https://api.voicedub.ai/v1/openapi.json \
--header 'Authorization: <api-key>'{
"openapi": "3.1.0",
"info": {
"title": "VoiceDub API",
"description": "API for creating AI voice dubs and training custom voice models",
"version": "1.0.0",
"contact": {
"name": "VoiceDub Support",
"email": "[email protected]",
"url": "https://voicedub.ai"
}
},
"servers": [
{
"url": "https://api.voicedub.ai",
"description": "Production server"
}
],
"security": [
{
"apiKeyAuth": []
}
],
"tags": [
{
"name": "Dubs",
"description": "Operations for creating and managing voice dubs"
},
{
"name": "Voices",
"description": "Operations for creating and managing voice models"
},
{
"name": "User",
"description": "Operations for managing user account and settings"
}
],
"paths": {
"/v1/me/dubs/{dubId}": {
"get": {
"summary": "Get dub by ID",
"description": "Retrieve a specific dub by its ID. Only returns dubs created via API by the authenticated user. You should poll this a maximum of once every 3 seconds while waiting for a dub to complete.",
"operationId": "getDubById",
"tags": [
"Dubs"
],
"parameters": [
{
"in": "path",
"name": "dubId",
"description": "UUID of the dub to retrieve",
"schema": {
"type": "string",
"format": "uuid",
"description": "UUID of the dub to retrieve",
"example": "123e4567-e89b-12d3-a456-426614174000"
},
"required": true
}
],
"responses": {
"200": {
"description": "Dub retrieved successfully",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"dub": {
"$ref": "#/components/schemas/DubPrivate"
}
},
"required": [
"dub"
]
}
}
}
},
"404": {
"description": "Dub not found",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/DubNotFoundError"
}
}
}
}
}
}
},
"/v1/me/dubs": {
"post": {
"summary": "Create new dub",
"description": "Create a new dub by providing a voice ID and either a link or uploading audio. Returns upload URL if no link provided. Dubs are currently limited to 30 minutes.",
"operationId": "createDub",
"tags": [
"Dubs"
],
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/CreateDubRequest"
}
}
}
},
"responses": {
"200": {
"description": "Dub created successfully",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/CreateDubResponse"
}
}
}
},
"400": {
"description": "Bad request - voice not found or invalid parameters",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/DubVoiceNotFoundError"
}
}
}
}
}
}
},
"/v1/me/dubs/{dubId}/preprocess": {
"post": {
"summary": "Preprocess dub",
"description": "Start preprocessing a dub. Must be called after creating the dub and before generation.",
"operationId": "preprocessDub",
"tags": [
"Dubs"
],
"parameters": [
{
"in": "path",
"name": "dubId",
"description": "UUID of the dub to preprocess",
"schema": {
"type": "string",
"format": "uuid",
"description": "UUID of the dub to preprocess",
"example": "123e4567-e89b-12d3-a456-426614174000"
},
"required": true
}
],
"responses": {
"200": {
"description": "Preprocessing started successfully",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/PreprocessDubResponse"
}
}
}
},
"400": {
"description": "Bad request - dub is not in new status",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/DubNotNewError"
}
}
}
},
"404": {
"description": "Dub not found",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/DubNotFoundError"
}
}
}
}
}
}
},
"/v1/me/dubs/{dubId}/generate": {
"post": {
"summary": "Generate dub",
"description": "Start generating the final dub. Requires the dub to be preprocessed first. Consumes 10 API credits per minute of audio. Check requiredCredits after /preprocess finishes.",
"operationId": "generateDub",
"tags": [
"Dubs"
],
"parameters": [
{
"in": "path",
"name": "dubId",
"description": "UUID of the dub to generate",
"schema": {
"type": "string",
"format": "uuid",
"description": "UUID of the dub to generate",
"example": "123e4567-e89b-12d3-a456-426614174000"
},
"required": true
}
],
"responses": {
"200": {
"description": "Generation started successfully",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/GenerateDubResponse"
}
}
}
},
"400": {
"description": "Bad request - dub is not preprocessed",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/DubNotPreprocessedError"
}
}
}
},
"404": {
"description": "Dub not found",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/DubNotFoundError"
}
}
}
}
}
}
},
"/v1/me/voices/{voiceId}": {
"get": {
"summary": "Get voice by ID",
"description": "Retrieve a specific voice by its ID. Only returns voices created via API by the authenticated user. You should poll this a maximum of once every 3 seconds while waiting for a voice to complete.",
"operationId": "getVoiceById",
"tags": [
"Voices"
],
"parameters": [
{
"in": "path",
"name": "voiceId",
"description": "UUID of the voice to retrieve",
"schema": {
"type": "string",
"format": "uuid",
"description": "UUID of the voice to retrieve",
"example": "123e4567-e89b-12d3-a456-426614174000"
},
"required": true
}
],
"responses": {
"200": {
"description": "Voice retrieved successfully",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/GetVoiceResponse"
}
}
}
},
"404": {
"description": "Voice not found",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/VoiceNotFoundError"
}
}
}
}
}
}
},
"/v1/voices": {
"get": {
"summary": "Get public voices",
"description": "Retrieve a paginated list of public voices available for use. Supports filtering by search, genres, languages, and styles.\n\nFilter logic: Multiple values inside the same filter are OR'd (e.g., languages=[english, spanish] matches voices that support English OR Spanish). Different filters are combined with AND (e.g., languages AND genres AND styles must all match).",
"operationId": "getPublicVoices",
"tags": [
"Voices"
],
"parameters": [
{
"in": "query",
"name": "search",
"description": "Search term to filter voices by name",
"schema": {
"type": "string",
"minLength": 1,
"maxLength": 50,
"description": "Search term to filter voices by name",
"example": "plankton"
}
},
{
"in": "query",
"name": "genres",
"description": "Filter by musical genres. Multiple values are OR'd within this filter and combined with other filters using AND.",
"schema": {
"type": "array",
"items": {
"type": "string",
"enum": [
"pop",
"rap",
"rock",
"country",
"rnb",
"alternative",
"jazz"
]
},
"description": "Filter by musical genres. Multiple values are OR'd within this filter and combined with other filters using AND.",
"example": [
"pop",
"country"
]
}
},
{
"in": "query",
"name": "languages",
"description": "Filter by supported languages. Multiple values are OR'd within this filter and combined with other filters using AND.",
"schema": {
"type": "array",
"items": {
"type": "string",
"enum": [
"english",
"spanish",
"korean",
"japanese",
"french",
"russian",
"thai"
]
},
"description": "Filter by supported languages. Multiple values are OR'd within this filter and combined with other filters using AND.",
"example": [
"english"
]
}
},
{
"in": "query",
"name": "styles",
"description": "Filter by voice styles. Multiple values are OR'd within this filter and combined with other filters using AND.",
"schema": {
"type": "array",
"items": {
"type": "string",
"enum": [
"singing",
"rapping",
"speaking",
"character",
"other"
]
},
"description": "Filter by voice styles. Multiple values are OR'd within this filter and combined with other filters using AND.",
"example": [
"singing"
]
}
},
{
"in": "query",
"name": "limit",
"description": "Number of voices to return (8-50)",
"schema": {
"type": "integer",
"minimum": 8,
"maximum": 50,
"default": 50,
"description": "Number of voices to return (8-50)",
"example": 20
}
},
{
"in": "query",
"name": "cursor",
"description": "Pagination cursor for next page",
"schema": {
"type": "string",
"description": "Pagination cursor for next page",
"example": "1_123e4567-e89b-12d3-a456-426614174000"
}
}
],
"responses": {
"200": {
"description": "Voices retrieved successfully",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/GetPublicVoicesResponse"
}
}
}
}
}
}
},
"/v1/me/voices": {
"post": {
"summary": "Create new voice",
"description": "Create a new voice for training. Returns presigned URLs for uploading training audio files.",
"operationId": "createVoice",
"tags": [
"Voices"
],
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/CreateVoiceRequest"
}
}
}
},
"responses": {
"200": {
"description": "Voice created successfully",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/CreateVoiceResponse"
}
}
}
}
}
}
},
"/v1/me/voices/{voiceId}/clone": {
"post": {
"summary": "Start voice training",
"description": "Start training/cloning a voice after uploading training files. Consumes 10 API credits per maxMinute. Check requiredCredits after creating the voice.",
"operationId": "cloneVoice",
"tags": [
"Voices"
],
"parameters": [
{
"in": "path",
"name": "voiceId",
"description": "UUID of the voice to start training",
"schema": {
"type": "string",
"format": "uuid",
"description": "UUID of the voice to start training",
"example": "123e4567-e89b-12d3-a456-426614174000"
},
"required": true
}
],
"responses": {
"200": {
"description": "Voice training started successfully",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/CloneVoiceResponse"
}
}
}
},
"400": {
"description": "Bad request - voice is not in new status",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/VoiceNotNewError"
}
}
}
},
"404": {
"description": "Voice not found",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/VoiceNotFoundError"
}
}
}
}
}
}
},
"/v1/me": {
"get": {
"summary": "Get your account details",
"description": "Retrieve your information including profile details and account settings.",
"operationId": "getMe",
"tags": [
"User"
],
"responses": {
"200": {
"description": "Your information was retrieved successfully",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/GetMeResponse"
}
}
}
}
}
}
}
},
"components": {
"securitySchemes": {
"apiKeyAuth": {
"type": "apiKey",
"in": "header",
"name": "Authorization",
"description": "API key in the format: \"Api-Key <your-api-key>\""
}
},
"schemas": {
"DubPrivate": {
"type": "object",
"properties": {
"id": {
"type": "string",
"format": "uuid",
"description": "Unique identifier for the dub",
"example": "123e4567-e89b-12d3-a456-426614174000"
},
"voiceId": {
"type": [
"string",
"null"
],
"format": "uuid",
"description": "Voice model used for the dub",
"example": "123e4567-e89b-12d3-a456-426614174001"
},
"link": {
"type": [
"string",
"null"
],
"description": "Original audio/video link if provided (null if not provided)",
"example": "https://example.com/audio.mp3"
},
"separate": {
"type": "boolean",
"description": "Whether vocals were separated from backing track",
"example": true
},
"status": {
"type": "string",
"enum": [
"new",
"preprocessing",
"preprocessed",
"queued",
"starting",
"processing",
"finalizing",
"done",
"error"
],
"description": "Current processing status of the dub",
"example": "done"
},
"inputDuration": {
"type": [
"integer",
"null"
],
"description": "Duration of input audio in milliseconds (null before preprocessed)",
"example": 180000
},
"inputSource": {
"type": "string",
"enum": [
"upload",
"link"
],
"description": "Source type of the input audio",
"example": "upload"
},
"pitchShift": {
"type": "integer",
"description": "Pitch shift applied in semitones",
"example": 0
},
"errorCode": {
"type": [
"string",
"null"
],
"description": "Error code if processing failed (null for now)",
"example": null
},
"errorMessage": {
"type": [
"string",
"null"
],
"description": "Error message if processing failed (null for now)",
"example": null
},
"apiCreditsUsed": {
"type": "integer",
"description": "API credits consumed for this dub (0 before /generate is called)",
"example": 30
},
"apiCreditsLeft": {
"type": [
"integer",
"null"
],
"description": "Remaining API credits after this dub (null before /generate is called)",
"example": 90
},
"completedAt": {
"type": [
"string",
"null"
],
"description": "Timestamp when dub processing completed (null if status is not \"done\" or \"error\")",
"example": "2024-01-15T10:30:00.000Z"
},
"createdAt": {
"type": "string",
"description": "Timestamp when dub was created",
"example": "2024-01-15T10:00:00.000Z"
},
"updatedAt": {
"type": "string",
"description": "Timestamp when dub was last updated",
"example": "2024-01-15T10:30:00.000Z"
},
"dubUrl": {
"type": [
"string",
"null"
],
"default": null,
"description": "Download URL for the completed dub (null if status is not done)",
"example": "https://example.com/dubs/123e4567-e89b-12d3-a456-426614174000.mp3"
},
"requiredCredits": {
"type": [
"number",
"null"
],
"default": null,
"description": "Number of credits required to process this dub (null before preprocessed)",
"example": 30
}
},
"required": [
"id",
"voiceId",
"link",
"separate",
"status",
"inputDuration",
"inputSource",
"pitchShift",
"errorCode",
"errorMessage",
"apiCreditsUsed",
"apiCreditsLeft",
"completedAt",
"createdAt",
"updatedAt",
"dubUrl",
"requiredCredits"
]
},
"VoicePublic": {
"type": "object",
"properties": {
"id": {
"type": "string",
"format": "uuid",
"description": "Unique identifier for the voice",
"example": "123e4567-e89b-12d3-a456-426614174000"
},
"name": {
"type": "string",
"description": "Display name of the voice",
"example": "Plankton"
},
"languages": {
"type": "array",
"items": {
"type": "string",
"enum": [
"english",
"spanish",
"korean",
"japanese",
"french",
"russian",
"thai"
]
},
"description": "Languages this voice supports",
"example": [
"english",
"spanish"
]
},
"genres": {
"type": "array",
"items": {
"type": "string",
"enum": [
"pop",
"rap",
"rock",
"country",
"rnb",
"alternative",
"jazz"
]
},
"description": "Musical genres this voice is suitable for",
"example": [
"pop",
"country"
]
},
"styles": {
"type": "array",
"items": {
"type": "string",
"enum": [
"singing",
"rapping",
"speaking",
"character",
"other"
]
},
"description": "Voice styles and use cases",
"example": [
"singing",
"speaking"
]
},
"avatarFormat": {
"type": "string",
"enum": [
"webp",
"gif"
],
"description": "Format of the voice avatar image",
"example": "webp"
},
"createdAt": {
"type": "string",
"description": "Timestamp when voice was created",
"example": "2024-01-15T10:00:00.000Z"
},
"updatedAt": {
"type": "string",
"description": "Timestamp when voice was last updated",
"example": "2024-01-15T10:30:00.000Z"
},
"avatarUrl": {
"type": "string",
"description": "Download URL for the voice avatar",
"example": "https://example.com/voices/123e4567-e89b-12d3-a456-426614174000.webp"
}
},
"required": [
"id",
"name",
"languages",
"genres",
"styles",
"avatarFormat",
"createdAt",
"updatedAt",
"avatarUrl"
]
},
"DubNotFoundError": {
"type": "object",
"properties": {
"code": {
"type": "string",
"const": "not_found",
"description": "Error code",
"example": "not_found"
},
"message": {
"type": "string",
"description": "Human-readable error message",
"example": "Dub not found"
}
},
"required": [
"code",
"message"
]
},
"CreateDubRequest": {
"type": "object",
"properties": {
"voiceId": {
"type": "string",
"format": "uuid",
"description": "UUID of the voice model to use for dubbing",
"example": "123e4567-e89b-12d3-a456-426614174001"
},
"link": {
"type": "string",
"format": "uri",
"description": "URL of audio/video to dub (alternative to file upload)",
"example": "https://example.com/audio.mp3"
},
"pitchShift": {
"type": "integer",
"minimum": -24,
"maximum": 24,
"default": 0,
"description": "Pitch shift in semitones (-24 to +24)",
"example": 0
},
"separate": {
"type": "boolean",
"default": true,
"description": "Whether to separate vocals from backing track",
"example": true
}
},
"required": [
"voiceId"
]
},
"CreateDubResponse": {
"type": "object",
"properties": {
"dub": {
"type": "object",
"properties": {
"id": {
"type": "string",
"format": "uuid",
"description": "Unique identifier for the dub",
"example": "123e4567-e89b-12d3-a456-426614174000"
},
"voiceId": {
"type": [
"string",
"null"
],
"format": "uuid",
"description": "Voice model used for the dub",
"example": "123e4567-e89b-12d3-a456-426614174001"
},
"link": {
"type": [
"string",
"null"
],
"description": "Original audio/video link if provided (null if not provided)",
"example": "https://example.com/audio.mp3"
},
"separate": {
"type": "boolean",
"description": "Whether vocals were separated from backing track",
"example": true
},
"status": {
"type": "string",
"enum": [
"new",
"preprocessing",
"preprocessed",
"queued",
"starting",
"processing",
"finalizing",
"done",
"error"
],
"description": "Current processing status of the dub",
"example": "new",
"openapi": {
"description": "Current processing status of the dub",
"example": "done"
}
},
"inputDuration": {
"type": [
"integer",
"null"
],
"description": "Duration of input audio in milliseconds (null before preprocessed)",
"example": null,
"openapi": {
"description": "Duration of input audio in milliseconds (null before preprocessed)",
"example": 180000
}
},
"inputSource": {
"type": "string",
"enum": [
"upload",
"link"
],
"description": "Source type of the input audio",
"example": "upload"
},
"pitchShift": {
"type": "integer",
"description": "Pitch shift applied in semitones",
"example": 0
},
"errorCode": {
"type": [
"string",
"null"
],
"description": "Error code if processing failed (null for now)",
"example": null
},
"errorMessage": {
"type": [
"string",
"null"
],
"description": "Error message if processing failed (null for now)",
"example": null
},
"apiCreditsUsed": {
"type": "integer",
"description": "API credits consumed for this dub (0 before /generate is called)",
"example": 0,
"openapi": {
"description": "API credits consumed for this dub (0 before /generate is called)",
"example": 30
}
},
"apiCreditsLeft": {
"type": [
"integer",
"null"
],
"description": "Remaining API credits after this dub (null before /generate is called)",
"example": null,
"openapi": {
"description": "Remaining API credits after this dub (null before /generate is called)",
"example": 90
}
},
"completedAt": {
"type": [
"string",
"null"
],
"description": "Timestamp when dub processing completed (null if status is not \"done\" or \"error\")",
"example": null,
"openapi": {
"description": "Timestamp when dub processing completed (null if status is not \"done\" or \"error\")",
"example": "2024-01-15T10:30:00.000Z"
}
},
"createdAt": {
"type": "string",
"description": "Timestamp when dub was created",
"example": "2024-01-15T10:00:00.000Z"
},
"updatedAt": {
"type": "string",
"description": "Timestamp when dub was last updated",
"example": "2024-01-15T10:30:00.000Z"
},
"dubUrl": {
"type": [
"string",
"null"
],
"default": null,
"description": "Download URL for the completed dub (null if status is not done)",
"example": null,
"openapi": {
"description": "Download URL for the completed dub (null if status is not done)",
"example": "https://example.com/dubs/123e4567-e89b-12d3-a456-426614174000.mp3"
}
},
"requiredCredits": {
"type": [
"number",
"null"
],
"default": null,
"description": "Number of credits required to process this dub (null before preprocessed)",
"example": null,
"openapi": {
"description": "Number of credits required to process this dub (null before preprocessed)",
"example": 30
}
}
},
"required": [
"id",
"voiceId",
"link",
"separate",
"status",
"inputDuration",
"inputSource",
"pitchShift",
"errorCode",
"errorMessage",
"apiCreditsUsed",
"apiCreditsLeft",
"completedAt",
"createdAt",
"updatedAt",
"dubUrl",
"requiredCredits"
]
},
"uploadUrl": {
"type": [
"string",
"null"
],
"format": "uri",
"description": "Presigned URL for uploading audio file (only when link not provided)",
"example": "https://s3.amazonaws.com/bucket/uploads/123e4567-e89b-12d3-a456-426614174000?X-Amz-Signature=..."
}
},
"required": [
"dub",
"uploadUrl"
]
},
"DubVoiceNotFoundError": {
"type": "object",
"properties": {
"code": {
"type": "string",
"const": "voice_not_found",
"description": "Error code",
"example": "voice_not_found"
},
"message": {
"type": "string",
"description": "Human-readable error message",
"example": "Voice not found or not accessible"
}
},
"required": [
"code",
"message"
]
},
"PreprocessDubResponse": {
"type": "object",
"properties": {
"dub": {
"type": "object",
"properties": {
"id": {
"type": "string",
"format": "uuid",
"description": "Unique identifier for the dub",
"example": "123e4567-e89b-12d3-a456-426614174000"
},
"voiceId": {
"type": [
"string",
"null"
],
"format": "uuid",
"description": "Voice model used for the dub",
"example": "123e4567-e89b-12d3-a456-426614174001"
},
"link": {
"type": [
"string",
"null"
],
"description": "Original audio/video link if provided (null if not provided)",
"example": "https://example.com/audio.mp3"
},
"separate": {
"type": "boolean",
"description": "Whether vocals were separated from backing track",
"example": true
},
"status": {
"type": "string",
"enum": [
"new",
"preprocessing",
"preprocessed",
"queued",
"starting",
"processing",
"finalizing",
"done",
"error"
],
"description": "Current processing status of the dub",
"example": "preprocessing",
"openapi": {
"description": "Current processing status of the dub",
"example": "done"
}
},
"inputDuration": {
"type": [
"integer",
"null"
],
"description": "Duration of input audio in milliseconds (null before preprocessed)",
"example": null,
"openapi": {
"description": "Duration of input audio in milliseconds (null before preprocessed)",
"example": 180000
}
},
"inputSource": {
"type": "string",
"enum": [
"upload",
"link"
],
"description": "Source type of the input audio",
"example": "upload"
},
"pitchShift": {
"type": "integer",
"description": "Pitch shift applied in semitones",
"example": 0
},
"errorCode": {
"type": [
"string",
"null"
],
"description": "Error code if processing failed (null for now)",
"example": null
},
"errorMessage": {
"type": [
"string",
"null"
],
"description": "Error message if processing failed (null for now)",
"example": null
},
"apiCreditsUsed": {
"type": "integer",
"description": "API credits consumed for this dub (0 before /generate is called)",
"example": 0,
"openapi": {
"description": "API credits consumed for this dub (0 before /generate is called)",
"example": 30
}
},
"apiCreditsLeft": {
"type": [
"integer",
"null"
],
"description": "Remaining API credits after this dub (null before /generate is called)",
"example": null,
"openapi": {
"description": "Remaining API credits after this dub (null before /generate is called)",
"example": 90
}
},
"completedAt": {
"type": [
"string",
"null"
],
"description": "Timestamp when dub processing completed (null if status is not \"done\" or \"error\")",
"example": null,
"openapi": {
"description": "Timestamp when dub processing completed (null if status is not \"done\" or \"error\")",
"example": "2024-01-15T10:30:00.000Z"
}
},
"createdAt": {
"type": "string",
"description": "Timestamp when dub was created",
"example": "2024-01-15T10:00:00.000Z"
},
"updatedAt": {
"type": "string",
"description": "Timestamp when dub was last updated",
"example": "2024-01-15T10:30:00.000Z"
},
"dubUrl": {
"type": [
"string",
"null"
],
"default": null,
"description": "Download URL for the completed dub (null if status is not done)",
"example": null,
"openapi": {
"description": "Download URL for the completed dub (null if status is not done)",
"example": "https://example.com/dubs/123e4567-e89b-12d3-a456-426614174000.mp3"
}
},
"requiredCredits": {
"type": [
"number",
"null"
],
"default": null,
"description": "Number of credits required to process this dub (null before preprocessed)",
"example": null,
"openapi": {
"description": "Number of credits required to process this dub (null before preprocessed)",
"example": 30
}
}
},
"required": [
"id",
"voiceId",
"link",
"separate",
"status",
"inputDuration",
"inputSource",
"pitchShift",
"errorCode",
"errorMessage",
"apiCreditsUsed",
"apiCreditsLeft",
"completedAt",
"createdAt",
"updatedAt",
"dubUrl",
"requiredCredits"
]
}
},
"required": [
"dub"
]
},
"DubNotNewError": {
"type": "object",
"properties": {
"code": {
"type": "string",
"const": "dub_is_not_new",
"description": "Error code",
"example": "dub_is_not_new"
},
"message": {
"type": "string",
"description": "Human-readable error message",
"example": "Dub is not new"
}
},
"required": [
"code",
"message"
]
},
"GenerateDubResponse": {
"type": "object",
"properties": {
"dub": {
"type": "object",
"properties": {
"id": {
"type": "string",
"format": "uuid",
"description": "Unique identifier for the dub",
"example": "123e4567-e89b-12d3-a456-426614174000"
},
"voiceId": {
"type": [
"string",
"null"
],
"format": "uuid",
"description": "Voice model used for the dub",
"example": "123e4567-e89b-12d3-a456-426614174001"
},
"link": {
"type": [
"string",
"null"
],
"description": "Original audio/video link if provided (null if not provided)",
"example": "https://example.com/audio.mp3"
},
"separate": {
"type": "boolean",
"description": "Whether vocals were separated from backing track",
"example": true
},
"status": {
"type": "string",
"enum": [
"new",
"preprocessing",
"preprocessed",
"queued",
"starting",
"processing",
"finalizing",
"done",
"error"
],
"description": "Current processing status of the dub",
"example": "queued",
"openapi": {
"description": "Current processing status of the dub",
"example": "done"
}
},
"inputDuration": {
"type": [
"integer",
"null"
],
"description": "Duration of input audio in milliseconds (null before preprocessed)",
"example": 180000,
"openapi": {
"description": "Duration of input audio in milliseconds (null before preprocessed)",
"example": 180000
}
},
"inputSource": {
"type": "string",
"enum": [
"upload",
"link"
],
"description": "Source type of the input audio",
"example": "upload"
},
"pitchShift": {
"type": "integer",
"description": "Pitch shift applied in semitones",
"example": 0
},
"errorCode": {
"type": [
"string",
"null"
],
"description": "Error code if processing failed (null for now)",
"example": null
},
"errorMessage": {
"type": [
"string",
"null"
],
"description": "Error message if processing failed (null for now)",
"example": null
},
"apiCreditsUsed": {
"type": "integer",
"description": "API credits consumed for this dub (0 before /generate is called)",
"example": 30,
"openapi": {
"description": "API credits consumed for this dub (0 before /generate is called)",
"example": 30
}
},
"apiCreditsLeft": {
"type": [
"integer",
"null"
],
"description": "Remaining API credits after this dub (null before /generate is called)",
"example": 90,
"openapi": {
"description": "Remaining API credits after this dub (null before /generate is called)",
"example": 90
}
},
"completedAt": {
"type": [
"string",
"null"
],
"description": "Timestamp when dub processing completed (null if status is not \"done\" or \"error\")",
"example": null,
"openapi": {
"description": "Timestamp when dub processing completed (null if status is not \"done\" or \"error\")",
"example": "2024-01-15T10:30:00.000Z"
}
},
"createdAt": {
"type": "string",
"description": "Timestamp when dub was created",
"example": "2024-01-15T10:00:00.000Z"
},
"updatedAt": {
"type": "string",
"description": "Timestamp when dub was last updated",
"example": "2024-01-15T10:30:00.000Z"
},
"dubUrl": {
"type": [
"string",
"null"
],
"default": null,
"description": "Download URL for the completed dub (null if status is not done)",
"example": null,
"openapi": {
"description": "Download URL for the completed dub (null if status is not done)",
"example": "https://example.com/dubs/123e4567-e89b-12d3-a456-426614174000.mp3"
}
},
"requiredCredits": {
"type": [
"number",
"null"
],
"default": null,
"description": "Number of credits required to process this dub (null before preprocessed)",
"example": 30,
"openapi": {
"description": "Number of credits required to process this dub (null before preprocessed)",
"example": 30
}
}
},
"required": [
"id",
"voiceId",
"link",
"separate",
"status",
"inputDuration",
"inputSource",
"pitchShift",
"errorCode",
"errorMessage",
"apiCreditsUsed",
"apiCreditsLeft",
"completedAt",
"createdAt",
"updatedAt",
"dubUrl",
"requiredCredits"
]
}
},
"required": [
"dub"
]
},
"DubNotPreprocessedError": {
"type": "object",
"properties": {
"code": {
"type": "string",
"const": "dub_is_not_in_preprocessed_state",
"description": "Error code",
"example": "dub_is_not_in_preprocessed_state"
},
"message": {
"type": "string",
"description": "Human-readable error message",
"example": "Dub must be in preprocessed state before generating"
}
},
"required": [
"code",
"message"
]
},
"GetVoiceResponse": {
"type": "object",
"properties": {
"voice": {
"type": "object",
"properties": {
"id": {
"type": "string",
"format": "uuid",
"description": "Unique identifier for the voice",
"example": "123e4567-e89b-12d3-a456-426614174000"
},
"name": {
"type": "string",
"description": "Display name of the voice",
"example": "My Custom Voice"
},
"status": {
"type": "string",
"enum": [
"new",
"queued",
"starting",
"processing",
"finalizing",
"done",
"error"
],
"description": "Current training/processing status of the voice",
"example": "done"
},
"separate": {
"type": "boolean",
"description": "Whether vocals separation was used during training",
"example": true
},
"maxMinutes": {
"type": "integer",
"description": "Maximum duration of training audio in minutes",
"example": 10
},
"errorCode": {
"type": [
"string",
"null"
],
"description": "Error code if training failed (null for now)",
"example": null
},
"errorMessage": {
"type": [
"string",
"null"
],
"description": "Error message if training failed (null for now)",
"example": null
},
"apiCreditsUsed": {
"type": "integer",
"description": "API credits consumed for training this voice (0 before /clone is called)",
"example": 100
},
"apiCreditsLeft": {
"type": [
"integer",
"null"
],
"description": "Remaining API credits after training (null before /clone is called)",
"example": 450
},
"completedAt": {
"type": [
"string",
"null"
],
"description": "Timestamp when voice training completed (null if status is not \"done\" or \"error\")",
"example": "2024-01-15T10:30:00.000Z"
},
"createdAt": {
"type": "string",
"description": "Timestamp when voice was created",
"example": "2024-01-15T10:00:00.000Z"
},
"updatedAt": {
"type": "string",
"description": "Timestamp when voice was last updated",
"example": "2024-01-15T10:30:00.000Z"
},
"requiredCredits": {
"type": "number",
"description": "Number of credits required to process this voice",
"example": 100
}
},
"required": [
"id",
"name",
"status",
"separate",
"maxMinutes",
"errorCode",
"errorMessage",
"apiCreditsUsed",
"apiCreditsLeft",
"completedAt",
"createdAt",
"updatedAt",
"requiredCredits"
]
}
},
"required": [
"voice"
]
},
"VoicePrivate": {
"type": "object",
"properties": {
"id": {
"type": "string",
"format": "uuid",
"description": "Unique identifier for the voice",
"example": "123e4567-e89b-12d3-a456-426614174000"
},
"name": {
"type": "string",
"description": "Display name of the voice",
"example": "My Custom Voice"
},
"status": {
"type": "string",
"enum": [
"new",
"queued",
"starting",
"processing",
"finalizing",
"done",
"error"
],
"description": "Current training/processing status of the voice",
"example": "done"
},
"separate": {
"type": "boolean",
"description": "Whether vocals separation was used during training",
"example": true
},
"maxMinutes": {
"type": "integer",
"description": "Maximum duration of training audio in minutes",
"example": 10
},
"errorCode": {
"type": [
"string",
"null"
],
"description": "Error code if training failed (null for now)",
"example": null
},
"errorMessage": {
"type": [
"string",
"null"
],
"description": "Error message if training failed (null for now)",
"example": null
},
"apiCreditsUsed": {
"type": "integer",
"description": "API credits consumed for training this voice (0 before /clone is called)",
"example": 100
},
"apiCreditsLeft": {
"type": [
"integer",
"null"
],
"description": "Remaining API credits after training (null before /clone is called)",
"example": 450
},
"completedAt": {
"type": [
"string",
"null"
],
"description": "Timestamp when voice training completed (null if status is not \"done\" or \"error\")",
"example": "2024-01-15T10:30:00.000Z"
},
"createdAt": {
"type": "string",
"description": "Timestamp when voice was created",
"example": "2024-01-15T10:00:00.000Z"
},
"updatedAt": {
"type": "string",
"description": "Timestamp when voice was last updated",
"example": "2024-01-15T10:30:00.000Z"
},
"requiredCredits": {
"type": [
"number",
"null"
],
"default": null,
"description": "Number of credits required to process this voice",
"example": 100
}
},
"required": [
"id",
"name",
"status",
"separate",
"maxMinutes",
"errorCode",
"errorMessage",
"apiCreditsUsed",
"apiCreditsLeft",
"completedAt",
"createdAt",
"updatedAt",
"requiredCredits"
]
},
"VoiceNotFoundError": {
"type": "object",
"properties": {
"code": {
"type": "string",
"const": "not_found",
"description": "Error code",
"example": "not_found"
},
"message": {
"type": "string",
"description": "Human-readable error message",
"example": "Voice not found"
}
},
"required": [
"code",
"message"
]
},
"GetPublicVoicesResponse": {
"type": "object",
"properties": {
"voices": {
"type": "array",
"items": {
"$ref": "#/components/schemas/VoicePublic"
}
},
"nextCursor": {
"type": [
"string",
"null"
],
"description": "Cursor for next page, null if no more pages",
"example": "2_123e4567-e89b-12d3-a456-426614174001"
}
},
"required": [
"voices",
"nextCursor"
]
},
"CreateVoiceRequest": {
"type": "object",
"properties": {
"name": {
"type": "string",
"minLength": 1,
"maxLength": 50,
"description": "Display name for the voice (1-50 characters)",
"example": "My Custom Voice"
},
"numberOfFiles": {
"type": "integer",
"minimum": 1,
"maximum": 5,
"description": "Number of audio files to upload for training (1-5)",
"example": 3
},
"maxMinutes": {
"type": "integer",
"minimum": 5,
"maximum": 60,
"default": 10,
"description": "Maximum duration of training audio in minutes (5-60)",
"example": 10
},
"separate": {
"type": "boolean",
"default": true,
"description": "Whether to use vocal separation during training",
"example": true
}
},
"required": [
"name",
"numberOfFiles"
]
},
"CreateVoiceResponse": {
"type": "object",
"properties": {
"voice": {
"type": "object",
"properties": {
"id": {
"type": "string",
"format": "uuid",
"description": "Unique identifier for the voice",
"example": "123e4567-e89b-12d3-a456-426614174000"
},
"name": {
"type": "string",
"description": "Display name of the voice",
"example": "My Custom Voice"
},
"status": {
"type": "string",
"enum": [
"new",
"queued",
"starting",
"processing",
"finalizing",
"done",
"error"
],
"description": "Current training/processing status of the voice",
"example": "new",
"openapi": {
"description": "Current training/processing status of the voice",
"example": "done"
}
},
"separate": {
"type": "boolean",
"description": "Whether vocals separation was used during training",
"example": true
},
"maxMinutes": {
"type": "integer",
"description": "Maximum duration of training audio in minutes",
"example": 10
},
"errorCode": {
"type": [
"string",
"null"
],
"description": "Error code if training failed (null for now)",
"example": null
},
"errorMessage": {
"type": [
"string",
"null"
],
"description": "Error message if training failed (null for now)",
"example": null
},
"apiCreditsUsed": {
"type": "integer",
"description": "API credits consumed for training this voice (0 before /clone is called)",
"example": 0,
"openapi": {
"description": "API credits consumed for training this voice (0 before /clone is called)",
"example": 100
}
},
"apiCreditsLeft": {
"type": [
"integer",
"null"
],
"description": "Remaining API credits after training (null before /clone is called)",
"example": null,
"openapi": {
"description": "Remaining API credits after training (null before /clone is called)",
"example": 450
}
},
"completedAt": {
"type": [
"string",
"null"
],
"description": "Timestamp when voice training completed (null if status is not \"done\" or \"error\")",
"example": null,
"openapi": {
"description": "Timestamp when voice training completed (null if status is not \"done\" or \"error\")",
"example": "2024-01-15T10:30:00.000Z"
}
},
"createdAt": {
"type": "string",
"description": "Timestamp when voice was created",
"example": "2024-01-15T10:00:00.000Z"
},
"updatedAt": {
"type": "string",
"description": "Timestamp when voice was last updated",
"example": "2024-01-15T10:30:00.000Z"
},
"requiredCredits": {
"type": "number",
"description": "Number of credits required to process this voice",
"example": 100
}
},
"required": [
"id",
"name",
"status",
"separate",
"maxMinutes",
"errorCode",
"errorMessage",
"apiCreditsUsed",
"apiCreditsLeft",
"completedAt",
"createdAt",
"updatedAt",
"requiredCredits"
]
},
"uploadUrls": {
"type": "array",
"items": {
"type": "string",
"format": "uri"
},
"description": "Presigned URLs for uploading training audio files",
"example": [
"https://s3.amazonaws.com/bucket/models/123e4567-e89b-12d3-a456-426614174000/vocals/123e4567-e89b-12d3-a456-426614174000_0?X-Amz-Signature=...",
"https://s3.amazonaws.com/bucket/models/123e4567-e89b-12d3-a456-426614174000/vocals/123e4567-e89b-12d3-a456-426614174000_1?X-Amz-Signature=..."
]
}
},
"required": [
"voice",
"uploadUrls"
]
},
"CloneVoiceResponse": {
"type": "object",
"properties": {
"voice": {
"type": "object",
"properties": {
"id": {
"type": "string",
"format": "uuid",
"description": "Unique identifier for the voice",
"example": "123e4567-e89b-12d3-a456-426614174000"
},
"name": {
"type": "string",
"description": "Display name of the voice",
"example": "My Custom Voice"
},
"status": {
"type": "string",
"enum": [
"new",
"queued",
"starting",
"processing",
"finalizing",
"done",
"error"
],
"description": "Current training/processing status of the voice",
"example": "queued",
"openapi": {
"description": "Current training/processing status of the voice",
"example": "done"
}
},
"separate": {
"type": "boolean",
"description": "Whether vocals separation was used during training",
"example": true
},
"maxMinutes": {
"type": "integer",
"description": "Maximum duration of training audio in minutes",
"example": 10
},
"errorCode": {
"type": [
"string",
"null"
],
"description": "Error code if training failed (null for now)",
"example": null
},
"errorMessage": {
"type": [
"string",
"null"
],
"description": "Error message if training failed (null for now)",
"example": null
},
"apiCreditsUsed": {
"type": "integer",
"description": "API credits consumed for training this voice (0 before /clone is called)",
"example": 100,
"openapi": {
"description": "API credits consumed for training this voice (0 before /clone is called)",
"example": 100
}
},
"apiCreditsLeft": {
"type": [
"integer",
"null"
],
"description": "Remaining API credits after training (null before /clone is called)",
"example": 450,
"openapi": {
"description": "Remaining API credits after training (null before /clone is called)",
"example": 450
}
},
"completedAt": {
"type": [
"string",
"null"
],
"description": "Timestamp when voice training completed (null if status is not \"done\" or \"error\")",
"example": null,
"openapi": {
"description": "Timestamp when voice training completed (null if status is not \"done\" or \"error\")",
"example": "2024-01-15T10:30:00.000Z"
}
},
"createdAt": {
"type": "string",
"description": "Timestamp when voice was created",
"example": "2024-01-15T10:00:00.000Z"
},
"updatedAt": {
"type": "string",
"description": "Timestamp when voice was last updated",
"example": "2024-01-15T10:30:00.000Z"
},
"requiredCredits": {
"type": "number",
"description": "Number of credits required to process this voice",
"example": 100
}
},
"required": [
"id",
"name",
"status",
"separate",
"maxMinutes",
"errorCode",
"errorMessage",
"apiCreditsUsed",
"apiCreditsLeft",
"completedAt",
"createdAt",
"updatedAt",
"requiredCredits"
]
}
},
"required": [
"voice"
]
},
"VoiceNotNewError": {
"type": "object",
"properties": {
"code": {
"type": "string",
"const": "voice_is_not_new",
"description": "Error code",
"example": "voice_is_not_new"
},
"message": {
"type": "string",
"description": "Human-readable error message",
"example": "Voice is not new"
}
},
"required": [
"code",
"message"
]
},
"GetMeResponse": {
"type": "object",
"properties": {
"user": {
"$ref": "#/components/schemas/UserPrivate"
}
},
"required": [
"user"
]
},
"UserPrivate": {
"type": "object",
"properties": {
"apiCredits": {
"type": "integer",
"description": "Number of API credits available",
"example": 1000
}
},
"required": [
"apiCredits"
]
}
},
"responses": {
"401": {
"description": "Unauthorized",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/UnauthorizedError"
}
}
}
},
"403": {
"description": "Insufficient credits",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/InsufficientCreditsError"
}
}
}
}
}
}
}Retrieve the OpenAPI specification for the VoiceDub API in JSON format.
curl --request GET \
--url https://api.voicedub.ai/v1/openapi.json \
--header 'Authorization: <api-key>'{
"openapi": "3.1.0",
"info": {
"title": "VoiceDub API",
"description": "API for creating AI voice dubs and training custom voice models",
"version": "1.0.0",
"contact": {
"name": "VoiceDub Support",
"email": "[email protected]",
"url": "https://voicedub.ai"
}
},
"servers": [
{
"url": "https://api.voicedub.ai",
"description": "Production server"
}
],
"security": [
{
"apiKeyAuth": []
}
],
"tags": [
{
"name": "Dubs",
"description": "Operations for creating and managing voice dubs"
},
{
"name": "Voices",
"description": "Operations for creating and managing voice models"
},
{
"name": "User",
"description": "Operations for managing user account and settings"
}
],
"paths": {
"/v1/me/dubs/{dubId}": {
"get": {
"summary": "Get dub by ID",
"description": "Retrieve a specific dub by its ID. Only returns dubs created via API by the authenticated user. You should poll this a maximum of once every 3 seconds while waiting for a dub to complete.",
"operationId": "getDubById",
"tags": [
"Dubs"
],
"parameters": [
{
"in": "path",
"name": "dubId",
"description": "UUID of the dub to retrieve",
"schema": {
"type": "string",
"format": "uuid",
"description": "UUID of the dub to retrieve",
"example": "123e4567-e89b-12d3-a456-426614174000"
},
"required": true
}
],
"responses": {
"200": {
"description": "Dub retrieved successfully",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"dub": {
"$ref": "#/components/schemas/DubPrivate"
}
},
"required": [
"dub"
]
}
}
}
},
"404": {
"description": "Dub not found",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/DubNotFoundError"
}
}
}
}
}
}
},
"/v1/me/dubs": {
"post": {
"summary": "Create new dub",
"description": "Create a new dub by providing a voice ID and either a link or uploading audio. Returns upload URL if no link provided. Dubs are currently limited to 30 minutes.",
"operationId": "createDub",
"tags": [
"Dubs"
],
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/CreateDubRequest"
}
}
}
},
"responses": {
"200": {
"description": "Dub created successfully",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/CreateDubResponse"
}
}
}
},
"400": {
"description": "Bad request - voice not found or invalid parameters",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/DubVoiceNotFoundError"
}
}
}
}
}
}
},
"/v1/me/dubs/{dubId}/preprocess": {
"post": {
"summary": "Preprocess dub",
"description": "Start preprocessing a dub. Must be called after creating the dub and before generation.",
"operationId": "preprocessDub",
"tags": [
"Dubs"
],
"parameters": [
{
"in": "path",
"name": "dubId",
"description": "UUID of the dub to preprocess",
"schema": {
"type": "string",
"format": "uuid",
"description": "UUID of the dub to preprocess",
"example": "123e4567-e89b-12d3-a456-426614174000"
},
"required": true
}
],
"responses": {
"200": {
"description": "Preprocessing started successfully",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/PreprocessDubResponse"
}
}
}
},
"400": {
"description": "Bad request - dub is not in new status",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/DubNotNewError"
}
}
}
},
"404": {
"description": "Dub not found",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/DubNotFoundError"
}
}
}
}
}
}
},
"/v1/me/dubs/{dubId}/generate": {
"post": {
"summary": "Generate dub",
"description": "Start generating the final dub. Requires the dub to be preprocessed first. Consumes 10 API credits per minute of audio. Check requiredCredits after /preprocess finishes.",
"operationId": "generateDub",
"tags": [
"Dubs"
],
"parameters": [
{
"in": "path",
"name": "dubId",
"description": "UUID of the dub to generate",
"schema": {
"type": "string",
"format": "uuid",
"description": "UUID of the dub to generate",
"example": "123e4567-e89b-12d3-a456-426614174000"
},
"required": true
}
],
"responses": {
"200": {
"description": "Generation started successfully",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/GenerateDubResponse"
}
}
}
},
"400": {
"description": "Bad request - dub is not preprocessed",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/DubNotPreprocessedError"
}
}
}
},
"404": {
"description": "Dub not found",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/DubNotFoundError"
}
}
}
}
}
}
},
"/v1/me/voices/{voiceId}": {
"get": {
"summary": "Get voice by ID",
"description": "Retrieve a specific voice by its ID. Only returns voices created via API by the authenticated user. You should poll this a maximum of once every 3 seconds while waiting for a voice to complete.",
"operationId": "getVoiceById",
"tags": [
"Voices"
],
"parameters": [
{
"in": "path",
"name": "voiceId",
"description": "UUID of the voice to retrieve",
"schema": {
"type": "string",
"format": "uuid",
"description": "UUID of the voice to retrieve",
"example": "123e4567-e89b-12d3-a456-426614174000"
},
"required": true
}
],
"responses": {
"200": {
"description": "Voice retrieved successfully",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/GetVoiceResponse"
}
}
}
},
"404": {
"description": "Voice not found",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/VoiceNotFoundError"
}
}
}
}
}
}
},
"/v1/voices": {
"get": {
"summary": "Get public voices",
"description": "Retrieve a paginated list of public voices available for use. Supports filtering by search, genres, languages, and styles.\n\nFilter logic: Multiple values inside the same filter are OR'd (e.g., languages=[english, spanish] matches voices that support English OR Spanish). Different filters are combined with AND (e.g., languages AND genres AND styles must all match).",
"operationId": "getPublicVoices",
"tags": [
"Voices"
],
"parameters": [
{
"in": "query",
"name": "search",
"description": "Search term to filter voices by name",
"schema": {
"type": "string",
"minLength": 1,
"maxLength": 50,
"description": "Search term to filter voices by name",
"example": "plankton"
}
},
{
"in": "query",
"name": "genres",
"description": "Filter by musical genres. Multiple values are OR'd within this filter and combined with other filters using AND.",
"schema": {
"type": "array",
"items": {
"type": "string",
"enum": [
"pop",
"rap",
"rock",
"country",
"rnb",
"alternative",
"jazz"
]
},
"description": "Filter by musical genres. Multiple values are OR'd within this filter and combined with other filters using AND.",
"example": [
"pop",
"country"
]
}
},
{
"in": "query",
"name": "languages",
"description": "Filter by supported languages. Multiple values are OR'd within this filter and combined with other filters using AND.",
"schema": {
"type": "array",
"items": {
"type": "string",
"enum": [
"english",
"spanish",
"korean",
"japanese",
"french",
"russian",
"thai"
]
},
"description": "Filter by supported languages. Multiple values are OR'd within this filter and combined with other filters using AND.",
"example": [
"english"
]
}
},
{
"in": "query",
"name": "styles",
"description": "Filter by voice styles. Multiple values are OR'd within this filter and combined with other filters using AND.",
"schema": {
"type": "array",
"items": {
"type": "string",
"enum": [
"singing",
"rapping",
"speaking",
"character",
"other"
]
},
"description": "Filter by voice styles. Multiple values are OR'd within this filter and combined with other filters using AND.",
"example": [
"singing"
]
}
},
{
"in": "query",
"name": "limit",
"description": "Number of voices to return (8-50)",
"schema": {
"type": "integer",
"minimum": 8,
"maximum": 50,
"default": 50,
"description": "Number of voices to return (8-50)",
"example": 20
}
},
{
"in": "query",
"name": "cursor",
"description": "Pagination cursor for next page",
"schema": {
"type": "string",
"description": "Pagination cursor for next page",
"example": "1_123e4567-e89b-12d3-a456-426614174000"
}
}
],
"responses": {
"200": {
"description": "Voices retrieved successfully",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/GetPublicVoicesResponse"
}
}
}
}
}
}
},
"/v1/me/voices": {
"post": {
"summary": "Create new voice",
"description": "Create a new voice for training. Returns presigned URLs for uploading training audio files.",
"operationId": "createVoice",
"tags": [
"Voices"
],
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/CreateVoiceRequest"
}
}
}
},
"responses": {
"200": {
"description": "Voice created successfully",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/CreateVoiceResponse"
}
}
}
}
}
}
},
"/v1/me/voices/{voiceId}/clone": {
"post": {
"summary": "Start voice training",
"description": "Start training/cloning a voice after uploading training files. Consumes 10 API credits per maxMinute. Check requiredCredits after creating the voice.",
"operationId": "cloneVoice",
"tags": [
"Voices"
],
"parameters": [
{
"in": "path",
"name": "voiceId",
"description": "UUID of the voice to start training",
"schema": {
"type": "string",
"format": "uuid",
"description": "UUID of the voice to start training",
"example": "123e4567-e89b-12d3-a456-426614174000"
},
"required": true
}
],
"responses": {
"200": {
"description": "Voice training started successfully",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/CloneVoiceResponse"
}
}
}
},
"400": {
"description": "Bad request - voice is not in new status",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/VoiceNotNewError"
}
}
}
},
"404": {
"description": "Voice not found",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/VoiceNotFoundError"
}
}
}
}
}
}
},
"/v1/me": {
"get": {
"summary": "Get your account details",
"description": "Retrieve your information including profile details and account settings.",
"operationId": "getMe",
"tags": [
"User"
],
"responses": {
"200": {
"description": "Your information was retrieved successfully",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/GetMeResponse"
}
}
}
}
}
}
}
},
"components": {
"securitySchemes": {
"apiKeyAuth": {
"type": "apiKey",
"in": "header",
"name": "Authorization",
"description": "API key in the format: \"Api-Key <your-api-key>\""
}
},
"schemas": {
"DubPrivate": {
"type": "object",
"properties": {
"id": {
"type": "string",
"format": "uuid",
"description": "Unique identifier for the dub",
"example": "123e4567-e89b-12d3-a456-426614174000"
},
"voiceId": {
"type": [
"string",
"null"
],
"format": "uuid",
"description": "Voice model used for the dub",
"example": "123e4567-e89b-12d3-a456-426614174001"
},
"link": {
"type": [
"string",
"null"
],
"description": "Original audio/video link if provided (null if not provided)",
"example": "https://example.com/audio.mp3"
},
"separate": {
"type": "boolean",
"description": "Whether vocals were separated from backing track",
"example": true
},
"status": {
"type": "string",
"enum": [
"new",
"preprocessing",
"preprocessed",
"queued",
"starting",
"processing",
"finalizing",
"done",
"error"
],
"description": "Current processing status of the dub",
"example": "done"
},
"inputDuration": {
"type": [
"integer",
"null"
],
"description": "Duration of input audio in milliseconds (null before preprocessed)",
"example": 180000
},
"inputSource": {
"type": "string",
"enum": [
"upload",
"link"
],
"description": "Source type of the input audio",
"example": "upload"
},
"pitchShift": {
"type": "integer",
"description": "Pitch shift applied in semitones",
"example": 0
},
"errorCode": {
"type": [
"string",
"null"
],
"description": "Error code if processing failed (null for now)",
"example": null
},
"errorMessage": {
"type": [
"string",
"null"
],
"description": "Error message if processing failed (null for now)",
"example": null
},
"apiCreditsUsed": {
"type": "integer",
"description": "API credits consumed for this dub (0 before /generate is called)",
"example": 30
},
"apiCreditsLeft": {
"type": [
"integer",
"null"
],
"description": "Remaining API credits after this dub (null before /generate is called)",
"example": 90
},
"completedAt": {
"type": [
"string",
"null"
],
"description": "Timestamp when dub processing completed (null if status is not \"done\" or \"error\")",
"example": "2024-01-15T10:30:00.000Z"
},
"createdAt": {
"type": "string",
"description": "Timestamp when dub was created",
"example": "2024-01-15T10:00:00.000Z"
},
"updatedAt": {
"type": "string",
"description": "Timestamp when dub was last updated",
"example": "2024-01-15T10:30:00.000Z"
},
"dubUrl": {
"type": [
"string",
"null"
],
"default": null,
"description": "Download URL for the completed dub (null if status is not done)",
"example": "https://example.com/dubs/123e4567-e89b-12d3-a456-426614174000.mp3"
},
"requiredCredits": {
"type": [
"number",
"null"
],
"default": null,
"description": "Number of credits required to process this dub (null before preprocessed)",
"example": 30
}
},
"required": [
"id",
"voiceId",
"link",
"separate",
"status",
"inputDuration",
"inputSource",
"pitchShift",
"errorCode",
"errorMessage",
"apiCreditsUsed",
"apiCreditsLeft",
"completedAt",
"createdAt",
"updatedAt",
"dubUrl",
"requiredCredits"
]
},
"VoicePublic": {
"type": "object",
"properties": {
"id": {
"type": "string",
"format": "uuid",
"description": "Unique identifier for the voice",
"example": "123e4567-e89b-12d3-a456-426614174000"
},
"name": {
"type": "string",
"description": "Display name of the voice",
"example": "Plankton"
},
"languages": {
"type": "array",
"items": {
"type": "string",
"enum": [
"english",
"spanish",
"korean",
"japanese",
"french",
"russian",
"thai"
]
},
"description": "Languages this voice supports",
"example": [
"english",
"spanish"
]
},
"genres": {
"type": "array",
"items": {
"type": "string",
"enum": [
"pop",
"rap",
"rock",
"country",
"rnb",
"alternative",
"jazz"
]
},
"description": "Musical genres this voice is suitable for",
"example": [
"pop",
"country"
]
},
"styles": {
"type": "array",
"items": {
"type": "string",
"enum": [
"singing",
"rapping",
"speaking",
"character",
"other"
]
},
"description": "Voice styles and use cases",
"example": [
"singing",
"speaking"
]
},
"avatarFormat": {
"type": "string",
"enum": [
"webp",
"gif"
],
"description": "Format of the voice avatar image",
"example": "webp"
},
"createdAt": {
"type": "string",
"description": "Timestamp when voice was created",
"example": "2024-01-15T10:00:00.000Z"
},
"updatedAt": {
"type": "string",
"description": "Timestamp when voice was last updated",
"example": "2024-01-15T10:30:00.000Z"
},
"avatarUrl": {
"type": "string",
"description": "Download URL for the voice avatar",
"example": "https://example.com/voices/123e4567-e89b-12d3-a456-426614174000.webp"
}
},
"required": [
"id",
"name",
"languages",
"genres",
"styles",
"avatarFormat",
"createdAt",
"updatedAt",
"avatarUrl"
]
},
"DubNotFoundError": {
"type": "object",
"properties": {
"code": {
"type": "string",
"const": "not_found",
"description": "Error code",
"example": "not_found"
},
"message": {
"type": "string",
"description": "Human-readable error message",
"example": "Dub not found"
}
},
"required": [
"code",
"message"
]
},
"CreateDubRequest": {
"type": "object",
"properties": {
"voiceId": {
"type": "string",
"format": "uuid",
"description": "UUID of the voice model to use for dubbing",
"example": "123e4567-e89b-12d3-a456-426614174001"
},
"link": {
"type": "string",
"format": "uri",
"description": "URL of audio/video to dub (alternative to file upload)",
"example": "https://example.com/audio.mp3"
},
"pitchShift": {
"type": "integer",
"minimum": -24,
"maximum": 24,
"default": 0,
"description": "Pitch shift in semitones (-24 to +24)",
"example": 0
},
"separate": {
"type": "boolean",
"default": true,
"description": "Whether to separate vocals from backing track",
"example": true
}
},
"required": [
"voiceId"
]
},
"CreateDubResponse": {
"type": "object",
"properties": {
"dub": {
"type": "object",
"properties": {
"id": {
"type": "string",
"format": "uuid",
"description": "Unique identifier for the dub",
"example": "123e4567-e89b-12d3-a456-426614174000"
},
"voiceId": {
"type": [
"string",
"null"
],
"format": "uuid",
"description": "Voice model used for the dub",
"example": "123e4567-e89b-12d3-a456-426614174001"
},
"link": {
"type": [
"string",
"null"
],
"description": "Original audio/video link if provided (null if not provided)",
"example": "https://example.com/audio.mp3"
},
"separate": {
"type": "boolean",
"description": "Whether vocals were separated from backing track",
"example": true
},
"status": {
"type": "string",
"enum": [
"new",
"preprocessing",
"preprocessed",
"queued",
"starting",
"processing",
"finalizing",
"done",
"error"
],
"description": "Current processing status of the dub",
"example": "new",
"openapi": {
"description": "Current processing status of the dub",
"example": "done"
}
},
"inputDuration": {
"type": [
"integer",
"null"
],
"description": "Duration of input audio in milliseconds (null before preprocessed)",
"example": null,
"openapi": {
"description": "Duration of input audio in milliseconds (null before preprocessed)",
"example": 180000
}
},
"inputSource": {
"type": "string",
"enum": [
"upload",
"link"
],
"description": "Source type of the input audio",
"example": "upload"
},
"pitchShift": {
"type": "integer",
"description": "Pitch shift applied in semitones",
"example": 0
},
"errorCode": {
"type": [
"string",
"null"
],
"description": "Error code if processing failed (null for now)",
"example": null
},
"errorMessage": {
"type": [
"string",
"null"
],
"description": "Error message if processing failed (null for now)",
"example": null
},
"apiCreditsUsed": {
"type": "integer",
"description": "API credits consumed for this dub (0 before /generate is called)",
"example": 0,
"openapi": {
"description": "API credits consumed for this dub (0 before /generate is called)",
"example": 30
}
},
"apiCreditsLeft": {
"type": [
"integer",
"null"
],
"description": "Remaining API credits after this dub (null before /generate is called)",
"example": null,
"openapi": {
"description": "Remaining API credits after this dub (null before /generate is called)",
"example": 90
}
},
"completedAt": {
"type": [
"string",
"null"
],
"description": "Timestamp when dub processing completed (null if status is not \"done\" or \"error\")",
"example": null,
"openapi": {
"description": "Timestamp when dub processing completed (null if status is not \"done\" or \"error\")",
"example": "2024-01-15T10:30:00.000Z"
}
},
"createdAt": {
"type": "string",
"description": "Timestamp when dub was created",
"example": "2024-01-15T10:00:00.000Z"
},
"updatedAt": {
"type": "string",
"description": "Timestamp when dub was last updated",
"example": "2024-01-15T10:30:00.000Z"
},
"dubUrl": {
"type": [
"string",
"null"
],
"default": null,
"description": "Download URL for the completed dub (null if status is not done)",
"example": null,
"openapi": {
"description": "Download URL for the completed dub (null if status is not done)",
"example": "https://example.com/dubs/123e4567-e89b-12d3-a456-426614174000.mp3"
}
},
"requiredCredits": {
"type": [
"number",
"null"
],
"default": null,
"description": "Number of credits required to process this dub (null before preprocessed)",
"example": null,
"openapi": {
"description": "Number of credits required to process this dub (null before preprocessed)",
"example": 30
}
}
},
"required": [
"id",
"voiceId",
"link",
"separate",
"status",
"inputDuration",
"inputSource",
"pitchShift",
"errorCode",
"errorMessage",
"apiCreditsUsed",
"apiCreditsLeft",
"completedAt",
"createdAt",
"updatedAt",
"dubUrl",
"requiredCredits"
]
},
"uploadUrl": {
"type": [
"string",
"null"
],
"format": "uri",
"description": "Presigned URL for uploading audio file (only when link not provided)",
"example": "https://s3.amazonaws.com/bucket/uploads/123e4567-e89b-12d3-a456-426614174000?X-Amz-Signature=..."
}
},
"required": [
"dub",
"uploadUrl"
]
},
"DubVoiceNotFoundError": {
"type": "object",
"properties": {
"code": {
"type": "string",
"const": "voice_not_found",
"description": "Error code",
"example": "voice_not_found"
},
"message": {
"type": "string",
"description": "Human-readable error message",
"example": "Voice not found or not accessible"
}
},
"required": [
"code",
"message"
]
},
"PreprocessDubResponse": {
"type": "object",
"properties": {
"dub": {
"type": "object",
"properties": {
"id": {
"type": "string",
"format": "uuid",
"description": "Unique identifier for the dub",
"example": "123e4567-e89b-12d3-a456-426614174000"
},
"voiceId": {
"type": [
"string",
"null"
],
"format": "uuid",
"description": "Voice model used for the dub",
"example": "123e4567-e89b-12d3-a456-426614174001"
},
"link": {
"type": [
"string",
"null"
],
"description": "Original audio/video link if provided (null if not provided)",
"example": "https://example.com/audio.mp3"
},
"separate": {
"type": "boolean",
"description": "Whether vocals were separated from backing track",
"example": true
},
"status": {
"type": "string",
"enum": [
"new",
"preprocessing",
"preprocessed",
"queued",
"starting",
"processing",
"finalizing",
"done",
"error"
],
"description": "Current processing status of the dub",
"example": "preprocessing",
"openapi": {
"description": "Current processing status of the dub",
"example": "done"
}
},
"inputDuration": {
"type": [
"integer",
"null"
],
"description": "Duration of input audio in milliseconds (null before preprocessed)",
"example": null,
"openapi": {
"description": "Duration of input audio in milliseconds (null before preprocessed)",
"example": 180000
}
},
"inputSource": {
"type": "string",
"enum": [
"upload",
"link"
],
"description": "Source type of the input audio",
"example": "upload"
},
"pitchShift": {
"type": "integer",
"description": "Pitch shift applied in semitones",
"example": 0
},
"errorCode": {
"type": [
"string",
"null"
],
"description": "Error code if processing failed (null for now)",
"example": null
},
"errorMessage": {
"type": [
"string",
"null"
],
"description": "Error message if processing failed (null for now)",
"example": null
},
"apiCreditsUsed": {
"type": "integer",
"description": "API credits consumed for this dub (0 before /generate is called)",
"example": 0,
"openapi": {
"description": "API credits consumed for this dub (0 before /generate is called)",
"example": 30
}
},
"apiCreditsLeft": {
"type": [
"integer",
"null"
],
"description": "Remaining API credits after this dub (null before /generate is called)",
"example": null,
"openapi": {
"description": "Remaining API credits after this dub (null before /generate is called)",
"example": 90
}
},
"completedAt": {
"type": [
"string",
"null"
],
"description": "Timestamp when dub processing completed (null if status is not \"done\" or \"error\")",
"example": null,
"openapi": {
"description": "Timestamp when dub processing completed (null if status is not \"done\" or \"error\")",
"example": "2024-01-15T10:30:00.000Z"
}
},
"createdAt": {
"type": "string",
"description": "Timestamp when dub was created",
"example": "2024-01-15T10:00:00.000Z"
},
"updatedAt": {
"type": "string",
"description": "Timestamp when dub was last updated",
"example": "2024-01-15T10:30:00.000Z"
},
"dubUrl": {
"type": [
"string",
"null"
],
"default": null,
"description": "Download URL for the completed dub (null if status is not done)",
"example": null,
"openapi": {
"description": "Download URL for the completed dub (null if status is not done)",
"example": "https://example.com/dubs/123e4567-e89b-12d3-a456-426614174000.mp3"
}
},
"requiredCredits": {
"type": [
"number",
"null"
],
"default": null,
"description": "Number of credits required to process this dub (null before preprocessed)",
"example": null,
"openapi": {
"description": "Number of credits required to process this dub (null before preprocessed)",
"example": 30
}
}
},
"required": [
"id",
"voiceId",
"link",
"separate",
"status",
"inputDuration",
"inputSource",
"pitchShift",
"errorCode",
"errorMessage",
"apiCreditsUsed",
"apiCreditsLeft",
"completedAt",
"createdAt",
"updatedAt",
"dubUrl",
"requiredCredits"
]
}
},
"required": [
"dub"
]
},
"DubNotNewError": {
"type": "object",
"properties": {
"code": {
"type": "string",
"const": "dub_is_not_new",
"description": "Error code",
"example": "dub_is_not_new"
},
"message": {
"type": "string",
"description": "Human-readable error message",
"example": "Dub is not new"
}
},
"required": [
"code",
"message"
]
},
"GenerateDubResponse": {
"type": "object",
"properties": {
"dub": {
"type": "object",
"properties": {
"id": {
"type": "string",
"format": "uuid",
"description": "Unique identifier for the dub",
"example": "123e4567-e89b-12d3-a456-426614174000"
},
"voiceId": {
"type": [
"string",
"null"
],
"format": "uuid",
"description": "Voice model used for the dub",
"example": "123e4567-e89b-12d3-a456-426614174001"
},
"link": {
"type": [
"string",
"null"
],
"description": "Original audio/video link if provided (null if not provided)",
"example": "https://example.com/audio.mp3"
},
"separate": {
"type": "boolean",
"description": "Whether vocals were separated from backing track",
"example": true
},
"status": {
"type": "string",
"enum": [
"new",
"preprocessing",
"preprocessed",
"queued",
"starting",
"processing",
"finalizing",
"done",
"error"
],
"description": "Current processing status of the dub",
"example": "queued",
"openapi": {
"description": "Current processing status of the dub",
"example": "done"
}
},
"inputDuration": {
"type": [
"integer",
"null"
],
"description": "Duration of input audio in milliseconds (null before preprocessed)",
"example": 180000,
"openapi": {
"description": "Duration of input audio in milliseconds (null before preprocessed)",
"example": 180000
}
},
"inputSource": {
"type": "string",
"enum": [
"upload",
"link"
],
"description": "Source type of the input audio",
"example": "upload"
},
"pitchShift": {
"type": "integer",
"description": "Pitch shift applied in semitones",
"example": 0
},
"errorCode": {
"type": [
"string",
"null"
],
"description": "Error code if processing failed (null for now)",
"example": null
},
"errorMessage": {
"type": [
"string",
"null"
],
"description": "Error message if processing failed (null for now)",
"example": null
},
"apiCreditsUsed": {
"type": "integer",
"description": "API credits consumed for this dub (0 before /generate is called)",
"example": 30,
"openapi": {
"description": "API credits consumed for this dub (0 before /generate is called)",
"example": 30
}
},
"apiCreditsLeft": {
"type": [
"integer",
"null"
],
"description": "Remaining API credits after this dub (null before /generate is called)",
"example": 90,
"openapi": {
"description": "Remaining API credits after this dub (null before /generate is called)",
"example": 90
}
},
"completedAt": {
"type": [
"string",
"null"
],
"description": "Timestamp when dub processing completed (null if status is not \"done\" or \"error\")",
"example": null,
"openapi": {
"description": "Timestamp when dub processing completed (null if status is not \"done\" or \"error\")",
"example": "2024-01-15T10:30:00.000Z"
}
},
"createdAt": {
"type": "string",
"description": "Timestamp when dub was created",
"example": "2024-01-15T10:00:00.000Z"
},
"updatedAt": {
"type": "string",
"description": "Timestamp when dub was last updated",
"example": "2024-01-15T10:30:00.000Z"
},
"dubUrl": {
"type": [
"string",
"null"
],
"default": null,
"description": "Download URL for the completed dub (null if status is not done)",
"example": null,
"openapi": {
"description": "Download URL for the completed dub (null if status is not done)",
"example": "https://example.com/dubs/123e4567-e89b-12d3-a456-426614174000.mp3"
}
},
"requiredCredits": {
"type": [
"number",
"null"
],
"default": null,
"description": "Number of credits required to process this dub (null before preprocessed)",
"example": 30,
"openapi": {
"description": "Number of credits required to process this dub (null before preprocessed)",
"example": 30
}
}
},
"required": [
"id",
"voiceId",
"link",
"separate",
"status",
"inputDuration",
"inputSource",
"pitchShift",
"errorCode",
"errorMessage",
"apiCreditsUsed",
"apiCreditsLeft",
"completedAt",
"createdAt",
"updatedAt",
"dubUrl",
"requiredCredits"
]
}
},
"required": [
"dub"
]
},
"DubNotPreprocessedError": {
"type": "object",
"properties": {
"code": {
"type": "string",
"const": "dub_is_not_in_preprocessed_state",
"description": "Error code",
"example": "dub_is_not_in_preprocessed_state"
},
"message": {
"type": "string",
"description": "Human-readable error message",
"example": "Dub must be in preprocessed state before generating"
}
},
"required": [
"code",
"message"
]
},
"GetVoiceResponse": {
"type": "object",
"properties": {
"voice": {
"type": "object",
"properties": {
"id": {
"type": "string",
"format": "uuid",
"description": "Unique identifier for the voice",
"example": "123e4567-e89b-12d3-a456-426614174000"
},
"name": {
"type": "string",
"description": "Display name of the voice",
"example": "My Custom Voice"
},
"status": {
"type": "string",
"enum": [
"new",
"queued",
"starting",
"processing",
"finalizing",
"done",
"error"
],
"description": "Current training/processing status of the voice",
"example": "done"
},
"separate": {
"type": "boolean",
"description": "Whether vocals separation was used during training",
"example": true
},
"maxMinutes": {
"type": "integer",
"description": "Maximum duration of training audio in minutes",
"example": 10
},
"errorCode": {
"type": [
"string",
"null"
],
"description": "Error code if training failed (null for now)",
"example": null
},
"errorMessage": {
"type": [
"string",
"null"
],
"description": "Error message if training failed (null for now)",
"example": null
},
"apiCreditsUsed": {
"type": "integer",
"description": "API credits consumed for training this voice (0 before /clone is called)",
"example": 100
},
"apiCreditsLeft": {
"type": [
"integer",
"null"
],
"description": "Remaining API credits after training (null before /clone is called)",
"example": 450
},
"completedAt": {
"type": [
"string",
"null"
],
"description": "Timestamp when voice training completed (null if status is not \"done\" or \"error\")",
"example": "2024-01-15T10:30:00.000Z"
},
"createdAt": {
"type": "string",
"description": "Timestamp when voice was created",
"example": "2024-01-15T10:00:00.000Z"
},
"updatedAt": {
"type": "string",
"description": "Timestamp when voice was last updated",
"example": "2024-01-15T10:30:00.000Z"
},
"requiredCredits": {
"type": "number",
"description": "Number of credits required to process this voice",
"example": 100
}
},
"required": [
"id",
"name",
"status",
"separate",
"maxMinutes",
"errorCode",
"errorMessage",
"apiCreditsUsed",
"apiCreditsLeft",
"completedAt",
"createdAt",
"updatedAt",
"requiredCredits"
]
}
},
"required": [
"voice"
]
},
"VoicePrivate": {
"type": "object",
"properties": {
"id": {
"type": "string",
"format": "uuid",
"description": "Unique identifier for the voice",
"example": "123e4567-e89b-12d3-a456-426614174000"
},
"name": {
"type": "string",
"description": "Display name of the voice",
"example": "My Custom Voice"
},
"status": {
"type": "string",
"enum": [
"new",
"queued",
"starting",
"processing",
"finalizing",
"done",
"error"
],
"description": "Current training/processing status of the voice",
"example": "done"
},
"separate": {
"type": "boolean",
"description": "Whether vocals separation was used during training",
"example": true
},
"maxMinutes": {
"type": "integer",
"description": "Maximum duration of training audio in minutes",
"example": 10
},
"errorCode": {
"type": [
"string",
"null"
],
"description": "Error code if training failed (null for now)",
"example": null
},
"errorMessage": {
"type": [
"string",
"null"
],
"description": "Error message if training failed (null for now)",
"example": null
},
"apiCreditsUsed": {
"type": "integer",
"description": "API credits consumed for training this voice (0 before /clone is called)",
"example": 100
},
"apiCreditsLeft": {
"type": [
"integer",
"null"
],
"description": "Remaining API credits after training (null before /clone is called)",
"example": 450
},
"completedAt": {
"type": [
"string",
"null"
],
"description": "Timestamp when voice training completed (null if status is not \"done\" or \"error\")",
"example": "2024-01-15T10:30:00.000Z"
},
"createdAt": {
"type": "string",
"description": "Timestamp when voice was created",
"example": "2024-01-15T10:00:00.000Z"
},
"updatedAt": {
"type": "string",
"description": "Timestamp when voice was last updated",
"example": "2024-01-15T10:30:00.000Z"
},
"requiredCredits": {
"type": [
"number",
"null"
],
"default": null,
"description": "Number of credits required to process this voice",
"example": 100
}
},
"required": [
"id",
"name",
"status",
"separate",
"maxMinutes",
"errorCode",
"errorMessage",
"apiCreditsUsed",
"apiCreditsLeft",
"completedAt",
"createdAt",
"updatedAt",
"requiredCredits"
]
},
"VoiceNotFoundError": {
"type": "object",
"properties": {
"code": {
"type": "string",
"const": "not_found",
"description": "Error code",
"example": "not_found"
},
"message": {
"type": "string",
"description": "Human-readable error message",
"example": "Voice not found"
}
},
"required": [
"code",
"message"
]
},
"GetPublicVoicesResponse": {
"type": "object",
"properties": {
"voices": {
"type": "array",
"items": {
"$ref": "#/components/schemas/VoicePublic"
}
},
"nextCursor": {
"type": [
"string",
"null"
],
"description": "Cursor for next page, null if no more pages",
"example": "2_123e4567-e89b-12d3-a456-426614174001"
}
},
"required": [
"voices",
"nextCursor"
]
},
"CreateVoiceRequest": {
"type": "object",
"properties": {
"name": {
"type": "string",
"minLength": 1,
"maxLength": 50,
"description": "Display name for the voice (1-50 characters)",
"example": "My Custom Voice"
},
"numberOfFiles": {
"type": "integer",
"minimum": 1,
"maximum": 5,
"description": "Number of audio files to upload for training (1-5)",
"example": 3
},
"maxMinutes": {
"type": "integer",
"minimum": 5,
"maximum": 60,
"default": 10,
"description": "Maximum duration of training audio in minutes (5-60)",
"example": 10
},
"separate": {
"type": "boolean",
"default": true,
"description": "Whether to use vocal separation during training",
"example": true
}
},
"required": [
"name",
"numberOfFiles"
]
},
"CreateVoiceResponse": {
"type": "object",
"properties": {
"voice": {
"type": "object",
"properties": {
"id": {
"type": "string",
"format": "uuid",
"description": "Unique identifier for the voice",
"example": "123e4567-e89b-12d3-a456-426614174000"
},
"name": {
"type": "string",
"description": "Display name of the voice",
"example": "My Custom Voice"
},
"status": {
"type": "string",
"enum": [
"new",
"queued",
"starting",
"processing",
"finalizing",
"done",
"error"
],
"description": "Current training/processing status of the voice",
"example": "new",
"openapi": {
"description": "Current training/processing status of the voice",
"example": "done"
}
},
"separate": {
"type": "boolean",
"description": "Whether vocals separation was used during training",
"example": true
},
"maxMinutes": {
"type": "integer",
"description": "Maximum duration of training audio in minutes",
"example": 10
},
"errorCode": {
"type": [
"string",
"null"
],
"description": "Error code if training failed (null for now)",
"example": null
},
"errorMessage": {
"type": [
"string",
"null"
],
"description": "Error message if training failed (null for now)",
"example": null
},
"apiCreditsUsed": {
"type": "integer",
"description": "API credits consumed for training this voice (0 before /clone is called)",
"example": 0,
"openapi": {
"description": "API credits consumed for training this voice (0 before /clone is called)",
"example": 100
}
},
"apiCreditsLeft": {
"type": [
"integer",
"null"
],
"description": "Remaining API credits after training (null before /clone is called)",
"example": null,
"openapi": {
"description": "Remaining API credits after training (null before /clone is called)",
"example": 450
}
},
"completedAt": {
"type": [
"string",
"null"
],
"description": "Timestamp when voice training completed (null if status is not \"done\" or \"error\")",
"example": null,
"openapi": {
"description": "Timestamp when voice training completed (null if status is not \"done\" or \"error\")",
"example": "2024-01-15T10:30:00.000Z"
}
},
"createdAt": {
"type": "string",
"description": "Timestamp when voice was created",
"example": "2024-01-15T10:00:00.000Z"
},
"updatedAt": {
"type": "string",
"description": "Timestamp when voice was last updated",
"example": "2024-01-15T10:30:00.000Z"
},
"requiredCredits": {
"type": "number",
"description": "Number of credits required to process this voice",
"example": 100
}
},
"required": [
"id",
"name",
"status",
"separate",
"maxMinutes",
"errorCode",
"errorMessage",
"apiCreditsUsed",
"apiCreditsLeft",
"completedAt",
"createdAt",
"updatedAt",
"requiredCredits"
]
},
"uploadUrls": {
"type": "array",
"items": {
"type": "string",
"format": "uri"
},
"description": "Presigned URLs for uploading training audio files",
"example": [
"https://s3.amazonaws.com/bucket/models/123e4567-e89b-12d3-a456-426614174000/vocals/123e4567-e89b-12d3-a456-426614174000_0?X-Amz-Signature=...",
"https://s3.amazonaws.com/bucket/models/123e4567-e89b-12d3-a456-426614174000/vocals/123e4567-e89b-12d3-a456-426614174000_1?X-Amz-Signature=..."
]
}
},
"required": [
"voice",
"uploadUrls"
]
},
"CloneVoiceResponse": {
"type": "object",
"properties": {
"voice": {
"type": "object",
"properties": {
"id": {
"type": "string",
"format": "uuid",
"description": "Unique identifier for the voice",
"example": "123e4567-e89b-12d3-a456-426614174000"
},
"name": {
"type": "string",
"description": "Display name of the voice",
"example": "My Custom Voice"
},
"status": {
"type": "string",
"enum": [
"new",
"queued",
"starting",
"processing",
"finalizing",
"done",
"error"
],
"description": "Current training/processing status of the voice",
"example": "queued",
"openapi": {
"description": "Current training/processing status of the voice",
"example": "done"
}
},
"separate": {
"type": "boolean",
"description": "Whether vocals separation was used during training",
"example": true
},
"maxMinutes": {
"type": "integer",
"description": "Maximum duration of training audio in minutes",
"example": 10
},
"errorCode": {
"type": [
"string",
"null"
],
"description": "Error code if training failed (null for now)",
"example": null
},
"errorMessage": {
"type": [
"string",
"null"
],
"description": "Error message if training failed (null for now)",
"example": null
},
"apiCreditsUsed": {
"type": "integer",
"description": "API credits consumed for training this voice (0 before /clone is called)",
"example": 100,
"openapi": {
"description": "API credits consumed for training this voice (0 before /clone is called)",
"example": 100
}
},
"apiCreditsLeft": {
"type": [
"integer",
"null"
],
"description": "Remaining API credits after training (null before /clone is called)",
"example": 450,
"openapi": {
"description": "Remaining API credits after training (null before /clone is called)",
"example": 450
}
},
"completedAt": {
"type": [
"string",
"null"
],
"description": "Timestamp when voice training completed (null if status is not \"done\" or \"error\")",
"example": null,
"openapi": {
"description": "Timestamp when voice training completed (null if status is not \"done\" or \"error\")",
"example": "2024-01-15T10:30:00.000Z"
}
},
"createdAt": {
"type": "string",
"description": "Timestamp when voice was created",
"example": "2024-01-15T10:00:00.000Z"
},
"updatedAt": {
"type": "string",
"description": "Timestamp when voice was last updated",
"example": "2024-01-15T10:30:00.000Z"
},
"requiredCredits": {
"type": "number",
"description": "Number of credits required to process this voice",
"example": 100
}
},
"required": [
"id",
"name",
"status",
"separate",
"maxMinutes",
"errorCode",
"errorMessage",
"apiCreditsUsed",
"apiCreditsLeft",
"completedAt",
"createdAt",
"updatedAt",
"requiredCredits"
]
}
},
"required": [
"voice"
]
},
"VoiceNotNewError": {
"type": "object",
"properties": {
"code": {
"type": "string",
"const": "voice_is_not_new",
"description": "Error code",
"example": "voice_is_not_new"
},
"message": {
"type": "string",
"description": "Human-readable error message",
"example": "Voice is not new"
}
},
"required": [
"code",
"message"
]
},
"GetMeResponse": {
"type": "object",
"properties": {
"user": {
"$ref": "#/components/schemas/UserPrivate"
}
},
"required": [
"user"
]
},
"UserPrivate": {
"type": "object",
"properties": {
"apiCredits": {
"type": "integer",
"description": "Number of API credits available",
"example": 1000
}
},
"required": [
"apiCredits"
]
}
},
"responses": {
"401": {
"description": "Unauthorized",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/UnauthorizedError"
}
}
}
},
"403": {
"description": "Insufficient credits",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/InsufficientCreditsError"
}
}
}
}
}
}
}API key in the format: "Api-Key
OpenAPI specification retrieved successfully. The example here (to the right on desktop, above on mobile) is the current, most up-to-date version of the OpenAPI spec.