Voice Generation API

Introduction

This API provides access to high-quality text-to-speech synthesis. Generate natural-sounding speech from text in multiple languages with various voice options and audio formats.

Try the Interactive Playground →
Important: Your balance is deducted based on the per character usage only when generating speech, not when listing voices or previewing them. Once your balance reaches zero, you will need to add more credits to continue using the API.

Authentication

All API requests require authentication using a Bearer token. Include your API key in the Authorization header of every request:

Authorization: Bearer YOUR_API_KEY

Available Models

The API provides two models optimized for different use cases:

English Model

Model ID: english

High-quality English-only voice synthesis with the best performance for English content.

🇺🇸 English

Multi Model

Model ID: multi

Support for multiple languages with natural pronunciation and accent handling.

🇺🇸 English 🇩🇪 German 🇪🇸 Spanish 🇫🇷 French 🇮🇹 Italian
Pricing: Both models use the same pricing: $0.000025 per character (approximately $0.025 per 1,000 characters or $25 per 1 million characters).

Available Voices

Browse our library of +5,000 stock voices available for text-to-speech generation. Use the filters below to find the perfect voice.

Note: Scroll down to load more voices. Use the preview button to hear a sample of each voice before using it in your application.

Speech Generation: POST /api/v1/speech

This endpoint generates speech audio from text input. The audio is streamed in real-time as it's being generated.

Request

Send a POST request with a JSON body containing your text and voice configuration.

Required Parameters

ParameterTypeDescription
transcriptstringThe text to convert to speech
voice.idstringThe ID of the voice to use (see Available Voices)

Optional Parameters

ParameterTypeDefaultDescription
model_idstring"english"Model to use: "english" or "multi"
output_format.containerstring"mp3"Audio format: "mp3" or "raw"
output_format.sample_rateinteger44100Sample rate in Hz (8000, 16000, 22050, 44100, 48000)
output_format.bit_rateinteger192000Bit rate for MP3 (32000-320000)
output_format.encodingstring"pcm_s16le"Encoding for RAW format

Example Request

{
  "model_id": "english",
  "transcript": "Hello! Welcome to our text-to-speech API. This is an example of high-quality voice synthesis.",
  "voice": {
    "id": "voice-id-here"
  },
  "output_format": {
    "container": "mp3",
    "sample_rate": 44100,
    "bit_rate": 192000
  }
}

Response

A successful request streams audio data directly. The Content-Type header will be set based on your chosen format:

  • audio/mpeg for MP3 format
  • application/octet-stream for RAW format

Example response headers:

HTTP/1.1 200 OK
Content-Type: audio/mpeg
X-Content-Type-Options: nosniff
Cache-Control: no-cache
X-Accel-Buffering: no

Streaming Audio

The API streams audio in real-time as it's being generated, allowing playback to start before the entire audio is complete. This provides a better user experience with lower latency.

Implementation Note: The streaming approach uses chunked transfer encoding. Clients should be prepared to receive data incrementally and can start playback as soon as the first chunks arrive.

List Voices: POST /api/v1/voices

This endpoint returns a list of available voices with optional filtering. Use it to discover voices before generating speech.

Request Body (All Optional)

ParameterTypeDescription
limitintegerMaximum number of voices to return (default: 50, max: 100)
languagestringFilter by language code (e.g., "en", "de", "es")
genderstringFilter by gender: "Male", "Female", "Neutral", "Unspecified"
model_idstringFilter by model: "english" or "multi"
my_voicebooleanIf true, returns only custom voices; if false, only stock voices
afterstringCursor for pagination

Example Request

{
  "limit": 50,
  "language": "en",
  "gender": "Female",
  "model_id": "english",
  "my_voice": false
}

Example Response

{
  "voices": [
    {
      "voice_id": "abc123",
      "name": "Sarah",
      "voice_type": "PREDEFINED",
      "language": "en",
      "gender": "Female",
      "accent": "American",
      "style": "Conversational",
      "description": "Warm and friendly voice perfect for narration"
    },
    {
      "voice_id": "def456",
      "name": "James",
      "voice_type": "PREDEFINED",
      "language": "en",
      "gender": "Male",
      "accent": "British",
      "style": "Professional"
    }
  ],
  "next_cursor": "eyJ..."
}
Pagination: Use the next_cursor value in the after parameter to retrieve the next page of results. The API returns a maximum of 100 voices per request.

Voice Preview: GET /api/v1/preview/<voice_id>

This endpoint returns a preview URL for a specific voice, allowing you to hear a sample before using it for speech generation.

Query Parameters

ParameterTypeDescription
idstringThe voice ID to preview (required)

Example Request

curl -X GET "https://voice.demo.efficientstack.com/api/v1/preview/abc123" \
  -H "Authorization: Bearer YOUR_API_KEY"

Example Response

{
  "signed_url": "https://storage.example.com/previews/abc123.mp3?signature=...",
  "expires_at": 1699200000
}

The signed_url can be used directly in an audio player or downloaded. The URL typically expires after a certain period indicated by expires_at.

Audio Formats

The API supports multiple audio formats and encoding options to suit different use cases.

MP3 Format

Compressed audio format ideal for streaming and storage efficiency.

ParameterOptionsDescription
sample_rate8000, 16000, 22050, 44100, 48000Higher rates provide better quality
bit_rate32000 - 320000Higher rates provide better quality (192000 recommended)

RAW Format

Uncompressed audio format for professional audio processing or custom encoding pipelines.

EncodingDescription
pcm_s16le16-bit signed PCM, little-endian (most common)
pcm_f32le32-bit float PCM, little-endian (high precision)
pcm_mulawμ-law encoding (telephony applications)

Example: MP3 with High Quality

{
  "output_format": {
    "container": "mp3",
    "sample_rate": 48000,
    "bit_rate": 320000
  }
}

Example: RAW PCM

{
  "output_format": {
    "container": "raw",
    "sample_rate": 44100,
    "encoding": "pcm_s16le"
  }
}

Error Handling

When an error occurs, the API returns an appropriate HTTP status code and a JSON error object:

{
  "error": {
    "message": "Invalid API key provided",
    "type": "invalid_request_error",
    "code": null
  }
}

Common Error Codes

Status CodeError TypeDescription
400Bad RequestInvalid request format or parameters
401UnauthorizedMissing or invalid API key
402Payment RequiredInsufficient account balance
404Not FoundVoice ID not found
500Server ErrorInternal server error, try again later

Balance Errors

If your account balance is insufficient for the requested operation, you'll receive a 402 error:

{
  "error": {
    "message": "Insufficient balance. Required: $0.0025, Available: $0.0010",
    "type": "insufficient_balance",
    "code": null
  }
}

Code Examples

Here are examples of how to use the API in different programming languages.

import requests

API_KEY = "YOUR_API_KEY"
BASE_URL = "https://voice.demo.efficientstack.com/api/v1"

headers = {
    "Authorization": f"Bearer {API_KEY}",
    "Content-Type": "application/json"
}

def list_voices():
    response = requests.post(
        f"{BASE_URL}/voices",
        headers=headers,
        json={
            "limit": 50,
            "language": "en",
            "gender": "Female",
            "my_voice": False
        }
    )
    return response.json()

def generate_speech(text, voice_id):
    response = requests.post(
        f"{BASE_URL}/speech",
        headers=headers,
        json={
            "model_id": "english",
            "transcript": text,
            "voice": {"id": voice_id},
            "output_format": {
                "container": "mp3",
                "sample_rate": 44100,
                "bit_rate": 192000
            }
        },
        stream=True
    )
    
    with open("output.mp3", "wb") as f:
        for chunk in response.iter_content(chunk_size=8192):
            f.write(chunk)
    
    return "output.mp3"

def preview_voice(voice_id):
    response = requests.get(
        f"{BASE_URL}/preview",
        headers={"Authorization": f"Bearer {API_KEY}"},
        params={"id": voice_id}
    )
    return response.json()

voices = list_voices()
print(f"Found {len(voices['voices'])} voices")

if voices['voices']:
    voice_id = voices['voices'][0]['voice_id']
    audio_file = generate_speech("Hello, this is a test!", voice_id)
    print(f"Audio saved to {audio_file}")
const API_KEY = "YOUR_API_KEY";
const BASE_URL = "https://voice.demo.efficientstack.com/api/v1";

const headers = {
  "Authorization": `Bearer ${API_KEY}`,
  "Content-Type": "application/json"
};

async function listVoices() {
  const response = await fetch(`${BASE_URL}/voices`, {
    method: "POST",
    headers: headers,
    body: JSON.stringify({
      limit: 50,
      language: "en",
      gender: "Female",
      my_voice: false
    })
  });
  return await response.json();
}

async function generateSpeech(text, voiceId) {
  const response = await fetch(`${BASE_URL}/speech`, {
    method: "POST",
    headers: headers,
    body: JSON.stringify({
      model_id: "english",
      transcript: text,
      voice: { id: voiceId },
      output_format: {
        container: "mp3",
        sample_rate: 44100,
        bit_rate: 192000
      }
    })
  });
  
  const blob = await response.blob();
  
  const url = URL.createObjectURL(blob);
  const a = document.createElement('a');
  a.href = url;
  a.download = 'speech.mp3';
  a.click();
  
  return url;
}

async function previewVoice(voiceId) {
  const response = await fetch(
    `${BASE_URL}/preview/${voiceId}`,
    {
      headers: { "Authorization": `Bearer ${API_KEY}` }
    }
  );
  return await response.json();
}

async function main() {
  const voices = await listVoices();
  console.log(`Found ${voices.voices.length} voices`);
  
  if (voices.voices.length > 0) {
    const voiceId = voices.voices[0].voice_id;
    await generateSpeech("Hello, this is a test!", voiceId);
    console.log("Audio generated and downloaded");
  }
}

main();
curl -X POST "https://voice.demo.efficientstack.com/api/v1/voices" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "limit": 50,
    "language": "en",
    "gender": "Female",
    "my_voice": false
  }'

curl -X POST "https://voice.demo.efficientstack.com/api/v1/speech" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model_id": "english",
    "transcript": "Hello, this is a test of the text-to-speech API!",
    "voice": {
      "id": "voice-id-here"
    },
    "output_format": {
      "container": "mp3",
      "sample_rate": 44100,
      "bit_rate": 192000
    }
  }' \
  --output speech.mp3

curl -X GET "https://voice.demo.efficientstack.com/api/v1/preview/voice-id-here" \
  -H "Authorization: Bearer YOUR_API_KEY"

curl -X POST "https://voice.demo.efficientstack.com/api/v1/speech" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model_id": "multi",
    "transcript": "Bonjour! Comment allez-vous?",
    "voice": {
      "id": "french-voice-id"
    }
  }' \
  --output french_speech.mp3
<?php

$apiKey = "YOUR_API_KEY";
$baseUrl = "https://voice.demo.efficientstack.com/api/v1";

function listVoices($apiKey, $baseUrl) {
    $ch = curl_init("$baseUrl/voices");
    curl_setopt($ch, CURLOPT_POST, 1);
    curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode([
        'limit' => 50,
        'language' => 'en',
        'gender' => 'Female',
        'my_voice' => false
    ]));
    curl_setopt($ch, CURLOPT_HTTPHEADER, [
        "Authorization: Bearer $apiKey",
        "Content-Type: application/json"
    ]);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    
    $response = curl_exec($ch);
    curl_close($ch);
    
    return json_decode($response, true);
}

function generateSpeech($apiKey, $baseUrl, $text, $voiceId) {
    $ch = curl_init("$baseUrl/speech");
    curl_setopt($ch, CURLOPT_POST, 1);
    curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode([
        'model_id' => 'english',
        'transcript' => $text,
        'voice' => ['id' => $voiceId],
        'output_format' => [
            'container' => 'mp3',
            'sample_rate' => 44100,
            'bit_rate' => 192000
        ]
    ]));
    curl_setopt($ch, CURLOPT_HTTPHEADER, [
        "Authorization: Bearer $apiKey",
        "Content-Type: application/json"
    ]);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    
    $audioData = curl_exec($ch);
    curl_close($ch);
    
    file_put_contents('output.mp3', $audioData);
    return 'output.mp3';
}

function previewVoice($apiKey, $baseUrl, $voiceId) {
    $ch = curl_init("$baseUrl/preview/" . urlencode($voiceId));
    curl_setopt($ch, CURLOPT_HTTPHEADER, [
        "Authorization: Bearer $apiKey"
    ]);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    
    $response = curl_exec($ch);
    curl_close($ch);
    
    return json_decode($response, true);
}

$voices = listVoices($apiKey, $baseUrl);
echo "Found " . count($voices['voices']) . " voices\n";

if (!empty($voices['voices'])) {
    $voiceId = $voices['voices'][0]['voice_id'];
    $audioFile = generateSpeech($apiKey, $baseUrl, "Hello, this is a test!", $voiceId);
    echo "Audio saved to $audioFile\n";
}

?>