Skip to main content

Quickstart

Three steps, and the third one returns audio. Nothing here needs an SDK.

1. Get an API key​

Keys live on the Developer page in the VieNeu web app. Create one, copy it once — the plaintext is shown at creation and never again — and put it in your environment:

export VIENEU_API_KEY="vn_sk_..."

A key can only be issued against an active token grant, so a brand-new account has to start one first; the Developer page offers a free 7-day trial that does exactly that, once per account. Without a grant, key creation answers 403 with No active API token grant found.

Keys beginning vn_sk_ are live. vn_test_ keys behave identically — same billing, same limits, same endpoints — except that each request is capped at 100 words, which makes them safe to paste into a sample repository.

2. Pick a voice​

The catalogue is public — this call needs no key:

curl -s "https://api.vieneu.io/api/v1/voices?engine=v4" | head -c 400
{"voices":[{"id":"Ngọc Lan","description":"Giọng nữ, giọng trầm dịu dàng",
"name":"Ngọc Lan","gender":"female","region":"south","engine":"v4",
"kind":"catalog"}, …]}

The id field is what you send. Always filter by engine. A voice belongs to one engine, the two catalogues are only partly interchangeable, and sending an id from the wrong one is a 400 rather than a substitution — see voice ids differ by engine.

3. Synthesize​

POST /v1/audio/speech returns the audio bytes in the response — no job, no polling. It is OpenAI's endpoint shape, so an OpenAI client works against it unchanged; see OpenAI-compatible endpoint.

curl​

curl https://api.vieneu.io/api/v1/audio/speech \
-H "Authorization: Bearer $VIENEU_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "input": "Xin chào, đây là VieNeu.", "voice": "Ngọc Lan" }' \
--output speech.mp3

Python​

# pip install requests
import os
import requests

resp = requests.post(
"https://api.vieneu.io/api/v1/audio/speech",
headers={"Authorization": f"Bearer {os.environ['VIENEU_API_KEY']}"},
json={"input": "Xin chào, đây là VieNeu.", "voice": "Ngọc Lan"},
timeout=120,
)
resp.raise_for_status()
with open("speech.mp3", "wb") as f:
f.write(resp.content)
print("wrote speech.mp3", len(resp.content), "bytes")

JavaScript​

// Node 18+ — no dependencies.
import { writeFile } from 'node:fs/promises';

const resp = await fetch('https://api.vieneu.io/api/v1/audio/speech', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.VIENEU_API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({ input: 'Xin chào, đây là VieNeu.', voice: 'Ngọc Lan' }),
});
if (!resp.ok) throw new Error(`HTTP ${resp.status}: ${await resp.text()}`);

await writeFile('speech.mp3', Buffer.from(await resp.arrayBuffer()));
console.log('wrote speech.mp3');

You now have an mp3. response_format changes that — wav, opus, pcm and 8 kHz ulaw are all available, with the field-level detail in the API reference under createSpeech.

Where to go next​

  • Long text — /v1/audio/speech holds the connection open for the whole synthesis. Past a few paragraphs, submit a job instead: see the two ways to synthesize.
  • Playback before the text finishes — Streaming.
  • When a call fails — Errors lists every machine-readable code and what to do about it.
  • Everything else — the API reference is generated from the server's own route definitions and covers every field of every endpoint.