Skip to main content
GET
/
v1
/
openapi.json
Get OpenAPI specification
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"
            }
          }
        }
      }
    }
  }
}

Authorizations

Authorization
string
header
required

API key in the format: "Api-Key "

Response

200 - application/json

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.