{"openapi":"3.1.0","info":{"title":"Voice API Platform","version":"1.0.0","description":"Text to speech, speech to text, speech recognition and voice cloning through one API.\n\n## Authentication\n\nEvery request needs a bearer token created from the API keys page:\n\n```\nAuthorization: Bearer vp_live_xxxxxxxxxxxx\n```\n\nA key's secret is shown once, at creation, and is stored only as a hash. If you lose it,\nrevoke the key and create another.\n\n## Request IDs\n\nEvery response carries an `X-Request-ID` header, and every error repeats it in the body.\nIt identifies one row in your request log — quote it when contacting support.\n\n## Errors\n\nErrors always use the same envelope:\n\n```json\n{ \"error\": { \"code\": \"INVALID_REQUEST\", \"message\": \"text must not be empty.\", \"request_id\": \"req_abc\" } }\n```\n\n## Rate limits\n\n100 requests per minute per API key by default. Separate keys have separate budgets.\nExceeding the limit returns `429` with code `RATE_LIMITED`.\n\n## Usage\n\nText to speech bills one unit per character; speech to text and recognition bill one unit\nper second of audio; cloning bills one unit per voice. Failed requests are never billed."},"servers":[{"url":"https://api.nexacalling.com/api/v1","description":"Production"}],"security":[{"bearerAuth":[]}],"tags":[{"name":"Speech synthesis","description":"Turn text into audio."},{"name":"Speech recognition","description":"Turn audio into text."},{"name":"Voices","description":"List, clone and delete voices."}],"paths":{"/text-to-speech":{"post":{"tags":["Speech synthesis"],"summary":"Synthesize speech","description":"Generates audio from text using one of your organization's voices. Returns raw `audio/mpeg` bytes.","operationId":"textToSpeech","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["text","voice_id"],"properties":{"text":{"type":"string","minLength":1,"maxLength":5000,"description":"The text to speak. Billed at one unit per character.","example":"Hello, and welcome to the Voice API Platform."},"voice_id":{"type":"string","description":"A voice ID from `GET /voices`.","example":"voice_c1x2n8fk4p"}}}}}},"responses":{"200":{"description":"The generated audio.","headers":{"X-Request-ID":{"schema":{"type":"string"}}},"content":{"audio/mpeg":{"schema":{"type":"string","format":"binary"}}}},"400":{"description":"Missing or invalid text, or text over the length limit.","headers":{"X-Request-ID":{"description":"Identifier for this request. Quote it in support requests.","schema":{"type":"string","example":"req_k3f9x2mQ7Lp0"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, malformed, unknown or revoked API key.","headers":{"X-Request-ID":{"description":"Identifier for this request. Quote it in support requests.","schema":{"type":"string","example":"req_k3f9x2mQ7Lp0"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Account suspended, or the service is disabled.","headers":{"X-Request-ID":{"description":"Identifier for this request. Quote it in support requests.","schema":{"type":"string","example":"req_k3f9x2mQ7Lp0"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such voice in your organization.","headers":{"X-Request-ID":{"description":"Identifier for this request. Quote it in support requests.","schema":{"type":"string","example":"req_k3f9x2mQ7Lp0"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded.","headers":{"X-Request-ID":{"description":"Identifier for this request. Quote it in support requests.","schema":{"type":"string","example":"req_k3f9x2mQ7Lp0"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"502":{"description":"The voice service failed.","headers":{"X-Request-ID":{"description":"Identifier for this request. Quote it in support requests.","schema":{"type":"string","example":"req_k3f9x2mQ7Lp0"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/speech-to-text":{"post":{"tags":["Speech recognition"],"summary":"Transcribe audio","description":"Transcribes an uploaded audio file. Accepts mp3, wav, m4a, webm and ogg up to 25 MB. Synchronous.","operationId":"speechToText","requestBody":{"required":true,"content":{"multipart/form-data":{"schema":{"$ref":"#/components/schemas/TranscriptionRequest"}}}},"responses":{"200":{"description":"The transcript.","headers":{"X-Request-ID":{"schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Transcript"}}}},"400":{"description":"Missing file, or an invalid language code.","headers":{"X-Request-ID":{"description":"Identifier for this request. Quote it in support requests.","schema":{"type":"string","example":"req_k3f9x2mQ7Lp0"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, malformed, unknown or revoked API key.","headers":{"X-Request-ID":{"description":"Identifier for this request. Quote it in support requests.","schema":{"type":"string","example":"req_k3f9x2mQ7Lp0"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"413":{"description":"The file exceeds 25 MB.","headers":{"X-Request-ID":{"description":"Identifier for this request. Quote it in support requests.","schema":{"type":"string","example":"req_k3f9x2mQ7Lp0"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"415":{"description":"The file is not an accepted audio format.","headers":{"X-Request-ID":{"description":"Identifier for this request. Quote it in support requests.","schema":{"type":"string","example":"req_k3f9x2mQ7Lp0"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded.","headers":{"X-Request-ID":{"description":"Identifier for this request. Quote it in support requests.","schema":{"type":"string","example":"req_k3f9x2mQ7Lp0"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"502":{"description":"The voice service failed.","headers":{"X-Request-ID":{"description":"Identifier for this request. Quote it in support requests.","schema":{"type":"string","example":"req_k3f9x2mQ7Lp0"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/asr":{"post":{"tags":["Speech recognition"],"summary":"Recognize speech","description":"The speech-recognition surface. Accepts the same inputs and returns the same shape as `/speech-to-text`; usage is recorded under ASR.","operationId":"asr","requestBody":{"required":true,"content":{"multipart/form-data":{"schema":{"$ref":"#/components/schemas/TranscriptionRequest"}}}},"responses":{"200":{"description":"The transcript.","headers":{"X-Request-ID":{"schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Transcript"}}}},"400":{"description":"Missing file, or an invalid language code.","headers":{"X-Request-ID":{"description":"Identifier for this request. Quote it in support requests.","schema":{"type":"string","example":"req_k3f9x2mQ7Lp0"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, malformed, unknown or revoked API key.","headers":{"X-Request-ID":{"description":"Identifier for this request. Quote it in support requests.","schema":{"type":"string","example":"req_k3f9x2mQ7Lp0"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"413":{"description":"The file exceeds 25 MB.","headers":{"X-Request-ID":{"description":"Identifier for this request. Quote it in support requests.","schema":{"type":"string","example":"req_k3f9x2mQ7Lp0"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"415":{"description":"The file is not an accepted audio format.","headers":{"X-Request-ID":{"description":"Identifier for this request. Quote it in support requests.","schema":{"type":"string","example":"req_k3f9x2mQ7Lp0"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded.","headers":{"X-Request-ID":{"description":"Identifier for this request. Quote it in support requests.","schema":{"type":"string","example":"req_k3f9x2mQ7Lp0"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"502":{"description":"The voice service failed.","headers":{"X-Request-ID":{"description":"Identifier for this request. Quote it in support requests.","schema":{"type":"string","example":"req_k3f9x2mQ7Lp0"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/voices":{"get":{"tags":["Voices"],"summary":"List voices","description":"Lists the catalogue voices plus any voices your organization has cloned. Another organization's voices are never included.","operationId":"listVoices","responses":{"200":{"description":"The available voices.","headers":{"X-Request-ID":{"schema":{"type":"string"}}},"content":{"application/json":{"schema":{"type":"object","properties":{"voices":{"type":"array","items":{"$ref":"#/components/schemas/Voice"}}}}}}},"401":{"description":"Missing, malformed, unknown or revoked API key.","headers":{"X-Request-ID":{"description":"Identifier for this request. Quote it in support requests.","schema":{"type":"string","example":"req_k3f9x2mQ7Lp0"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded.","headers":{"X-Request-ID":{"description":"Identifier for this request. Quote it in support requests.","schema":{"type":"string","example":"req_k3f9x2mQ7Lp0"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/voices/clone":{"post":{"tags":["Voices"],"summary":"Clone a voice","description":"Creates an instant voice clone from an audio sample.\n\n`consent` is required and must be `true`. By sending it you confirm you have permission\nand authorization to use the recording for voice cloning. The confirmation is stored with\na timestamp against the voice.","operationId":"cloneVoice","requestBody":{"required":true,"content":{"multipart/form-data":{"schema":{"type":"object","required":["name","consent","file"],"properties":{"name":{"type":"string","maxLength":64,"example":"Narrator"},"description":{"type":"string","maxLength":500},"consent":{"type":"string","enum":["true"],"description":"Must be `true`. Confirms you are authorized to clone this voice."},"file":{"type":"string","format":"binary","description":"An audio sample of one speaker."}}}}}},"responses":{"201":{"description":"The created voice.","headers":{"X-Request-ID":{"schema":{"type":"string"}}},"content":{"application/json":{"schema":{"type":"object","properties":{"voice":{"$ref":"#/components/schemas/Voice"}}}}}},"400":{"description":"Missing name, missing consent, or the clone limit is reached.","headers":{"X-Request-ID":{"description":"Identifier for this request. Quote it in support requests.","schema":{"type":"string","example":"req_k3f9x2mQ7Lp0"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, malformed, unknown or revoked API key.","headers":{"X-Request-ID":{"description":"Identifier for this request. Quote it in support requests.","schema":{"type":"string","example":"req_k3f9x2mQ7Lp0"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Voice cloning is disabled for this account.","headers":{"X-Request-ID":{"description":"Identifier for this request. Quote it in support requests.","schema":{"type":"string","example":"req_k3f9x2mQ7Lp0"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"413":{"description":"The sample exceeds 25 MB.","headers":{"X-Request-ID":{"description":"Identifier for this request. Quote it in support requests.","schema":{"type":"string","example":"req_k3f9x2mQ7Lp0"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"415":{"description":"The sample is not an accepted audio format.","headers":{"X-Request-ID":{"description":"Identifier for this request. Quote it in support requests.","schema":{"type":"string","example":"req_k3f9x2mQ7Lp0"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded.","headers":{"X-Request-ID":{"description":"Identifier for this request. Quote it in support requests.","schema":{"type":"string","example":"req_k3f9x2mQ7Lp0"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"502":{"description":"The voice service failed.","headers":{"X-Request-ID":{"description":"Identifier for this request. Quote it in support requests.","schema":{"type":"string","example":"req_k3f9x2mQ7Lp0"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/voices/{id}":{"delete":{"tags":["Voices"],"summary":"Delete a cloned voice","description":"Deletes one of your organization's cloned voices. Catalogue voices cannot be deleted.","operationId":"deleteVoice","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"example":"voice_c1x2n8fk4p"}],"responses":{"200":{"description":"The voice was deleted.","headers":{"X-Request-ID":{"schema":{"type":"string"}}},"content":{"application/json":{"schema":{"type":"object","properties":{"deleted":{"type":"boolean"},"id":{"type":"string"}}}}}},"401":{"description":"Missing, malformed, unknown or revoked API key.","headers":{"X-Request-ID":{"description":"Identifier for this request. Quote it in support requests.","schema":{"type":"string","example":"req_k3f9x2mQ7Lp0"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such cloned voice in your organization.","headers":{"X-Request-ID":{"description":"Identifier for this request. Quote it in support requests.","schema":{"type":"string","example":"req_k3f9x2mQ7Lp0"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded.","headers":{"X-Request-ID":{"description":"Identifier for this request. Quote it in support requests.","schema":{"type":"string","example":"req_k3f9x2mQ7Lp0"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}}},"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","description":"An API key from the API keys page, e.g. `vp_live_xxxxxxxx`."}},"schemas":{"Error":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message","request_id"],"properties":{"code":{"type":"string","enum":["INVALID_REQUEST","INVALID_API_KEY","ACCOUNT_SUSPENDED","SERVICE_DISABLED","NOT_FOUND","PAYLOAD_TOO_LARGE","UNSUPPORTED_MEDIA_TYPE","RATE_LIMITED","INTERNAL_ERROR","PROVIDER_ERROR"]},"message":{"type":"string","example":"text must not be empty."},"request_id":{"type":"string","example":"req_k3f9x2mQ7Lp0"}}}}},"Transcript":{"type":"object","required":["text","language","request_id"],"properties":{"text":{"type":"string","example":"Hello, and welcome to the Voice API Platform."},"language":{"type":["string","null"],"description":"Detected or supplied language code.","example":"en"},"request_id":{"type":"string","example":"req_k3f9x2mQ7Lp0"}}},"TranscriptionRequest":{"type":"object","required":["file"],"properties":{"file":{"type":"string","format":"binary","description":"mp3, wav, m4a, webm or ogg, up to 25 MB."},"language":{"type":"string","description":"Optional ISO language hint. Omit to detect automatically.","example":"en"}}},"Voice":{"type":"object","required":["id","name","type","created_at"],"properties":{"id":{"type":"string","example":"voice_c1x2n8fk4p"},"name":{"type":"string","example":"Narrator"},"language":{"type":["string","null"],"example":"en"},"type":{"type":"string","enum":["PROVIDER","CLONED"],"description":"`PROVIDER` is a shared catalogue voice; `CLONED` belongs to your organization."},"created_at":{"type":"string","format":"date-time"}}}}}}