Evom Labs API Reference

Developer platform

API examples

Copy-ready examples for the supported REST, Server-Sent Events and WebSocket workflows. Every credential is a placeholder and must be replaced server-side.

On this page

Security

Run these examples on a trusted server. Never place an API key in browser code, a mobile bundle, logs or source control.

Generate a finished audio file

Use the bytes endpoint for a short, non-realtime request. The response body is binary audio, so save it with the format selected in the JSON body.

curl
curl -X POST https://studio.evomlabs.com/api/v1/tts/bytes \
  -H "Authorization: Bearer vc_sk_live_YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{"text":"Xin chào","language":"vi","format":"wav"}' \
  --output hello.wav
POST /api/v1/tts/bytes

Stream Text-to-Speech

Use SSE when one POST should progressively return base64 PCM16 events. Use WebSocket for a long-lived, bidirectional voice-agent connection.

Server-Sent Events

curl
curl -N -X POST https://studio.evomlabs.com/api/v1/tts/sse \
  -H "Authorization: Bearer vc_sk_live_YOUR_KEY" \
  -H "Accept: text/event-stream" \
  -H "Content-Type: application/json" \
  -d '{"text":"Xin chào","language":"vi"}'
text/event-stream
event: start
data: {"sample_rate":24000,"channels":1,"format":"pcm_s16le","encoding":"base64"}

event: audio
data: {"sequence":1,"audio":"<base64 PCM16 little-endian>"}

event: done
data: {"chunks":12,"duration_ms":5230,"elapsed_ms":6100}

WebSocket

Python
import json, requests, websocket

BASE_URL = "https://studio.evomlabs.com"
API_KEY = "vc_sk_live_YOUR_KEY"
text = "Xin chào, đây là bài test giọng nói."

# 1. Ask for a short-lived token. It expires in 60 seconds, so open the
#    socket immediately afterwards.
token = requests.post(
    f"{BASE_URL}/api/v1/tts/stream-token",
    headers={"Authorization": f"Bearer {API_KEY}"},
    json={"text_length": len(text)},
).json()["data"]

# 2. Always connect to the ws_url the response returned.
ws = websocket.create_connection(f"{token['ws_url']}?token={token['stream_token']}")
ws.send(json.dumps({"type": "start", "text": text, "language": "vi"}))

pcm = bytearray()
while True:
    frame = ws.recv()
    if isinstance(frame, bytes):
        pcm.extend(frame)          # PCM16 mono at 24 kHz
        continue
    event = json.loads(frame)
    if event["type"] in ("done", "error", "cancelled"):
        break

ws.close()
print("received", len(pcm), "bytes of audio")
WSS /ws/tts/stream

Transcribe an audio file

Upload the entire recording as multipart/form-data and wait for the final transcript object.

curl
curl -X POST "https://studio.evomlabs.com/api/v1/stt/transcriptions" \
  -H "Authorization: Bearer stt_sk_live_YOUR_KEY" \
  -F "audio=@recording.wav" \
  -F "language=auto"
Python
import requests

with open("recording.wav", "rb") as audio:
    response = requests.post(
        "https://studio.evomlabs.com/api/v1/stt/transcriptions",
        headers={"Authorization": "Bearer stt_sk_live_YOUR_KEY"},
        files={"audio": audio},
        data={"language": "auto"},
        timeout=1800,
    )

response.raise_for_status()
print(response.json()["text"])
POST /api/v1/stt/transcriptions

Transcribe a live microphone

Auto mode uses server VAD. Manual mode waits for commit and suits Push-to-Talk or a client that already has VAD.

Automatic VAD

JavaScript
const ws = new WebSocket(
  "wss://studio.evomlabs.com/api/public/v1/stt/ws" +
  "?token=stt_sk_live_YOUR_KEY&language=auto"
);

ws.addEventListener("open", () => {
  ws.send(JSON.stringify({
    type: "start",
    mode: "auto",
    language: "auto",
    sample_rate: 48000,
    format: "pcm_s16le",
  }));
});

ws.addEventListener("message", (event) => {
  const message = JSON.parse(event.data);
  if (message.type === "partial" || message.type === "segment") {
    renderTranscript(message.combined_text);
  }
  if (message.type === "final") {
    renderTranscript(message.text);
  }
  if (message.type === "error") {
    console.error(message.code, message.message);
  }
});

// Send PCM16 frames with ws.send(arrayBuffer).
function stopTranscription() {
  if (ws.readyState === WebSocket.OPEN) {
    ws.send(JSON.stringify({ type: "stop" }));
  }
}

Manual commit

JavaScript
// Start with: { "type": "start", "mode": "manual", ... }
// Send PCM16 frames, then commit exactly that buffered speech:
ws.send(JSON.stringify({ type: "commit" }));

// The server returns one final segment. Send commit again for the next turn,
// or stop to commit a sufficiently long trailing buffer and close the session.
ws.send(JSON.stringify({ type: "stop" }));
WSS /api/public/v1/stt/ws

Clone a voice and inspect usage

These calls require an account key. Voice enrollment requires audioUpload; key inventory requires keyManagement. A disabled permission returns 403 PERMISSION_DENIED.

Voice Clone

curl
curl -X POST https://studio.evomlabs.com/api/v1/voices \
  -H "Authorization: Bearer vc_ak_live_YOUR_KEY" \
  -F "file=@sample.wav" \
  -F "name=Authorized sample voice" \
  -F "gender=female" \
  -F "consent=true"

API keys and remaining usage

curl
curl https://studio.evomlabs.com/api/v1/keys   -H "Authorization: Bearer vc_ak_live_YOUR_KEY"
JSON
{
  "ok": true,
  "data": {
    "account_usage": {
      "tts": {"limit":500000,"used":1234,"remaining":498766,"unlimited":false},
      "stt": {"limit":100000,"used":50,"remaining":99950,"unlimited":false},
      "reset_date": "2026-09-01T00:00:00.000Z",
      "reset_interval": "month",
      "reset_interval_count": 1
    },
    "keys": {"admin":[],"tts":[],"stt":[]}
  }
}
GET /api/v1/keys
Evom Labs API documentation