Tài liệu API · v1

Tích hợp giọng nói vào sản phẩm của bạn

REST API để máy chủ của bạn tạo giọng nói từ văn bản (kèm phụ đề SRT nếu cần), theo dõi tiến độ và tải file kết quả — dùng chung số dư credit với giao diện web.

Base URL
https://voice1.pro/api
Xác thực
Authorization: Bearer <API_KEY>
Định dạng
JSON · UTF-8
Đặc tả API:voice1.pro/openapi.json

Khóa API của bạn

Đăng nhập để tạo khóa API và gọi API từ máy chủ của bạn. Mọi lệnh gọi dùng chung số dư credit với tài khoản.

Đăng nhập để tạo khóa
Hướng dẫnBắt đầu nhanh

Hướng dẫn

Bắt đầu nhanh

Từ khóa API tới file MP3 đầu tiên trong 5 phút.

API của Voice1 là REST + JSON. Mọi tác vụ tạo giọng chạy bất đồng bộ: bạn gửi yêu cầu, nhận về id ngay, rồi hỏi trạng thái tới khi xong và tải file về. Base URL: https://voice1.pro/api.

Chi phí thử nghiệm

Khóa thử vs_test_… (sandbox) chạy được toàn bộ ví dụ dưới đây miễn phí: tác vụ giả lập, không trừ credit — xem mục Sandbox. Khóa thật vs_live_…: 1 credit = 1 ký tự, tối thiểu 500 credit mỗi tác vụ — mỗi lần chạy ví dụ 500 credit.

0. Thử ngay, không cần code

  • Tạo Khóa thử ở thẻ "Khóa API của bạn" đầu trang (miễn phí).
  • Mở mục Tạo giọng từ văn bản → khung Gửi thử ở cuối trang.
  • Dán khóa, bấm Gửi POST → nhận id tác vụ.
  • Mở Chi tiết tác vụ / Tải file kết quả: id đã điền sẵn, bấm Gửi để xem kết quả và nghe file.

1. Tạo khóa API

Đăng nhập, bấm Tạo khóa ở thẻ "Khóa API của bạn" đầu trang, chọn Khóa thử (miễn phí) hoặc Khóa thật, rồi sao chép khóa. Khóa chỉ hiện một lần — hãy cất vào biến môi trường hoặc trình quản lý bí mật.

2. Chọn giọng

voiceId là bắt buộc và không có giá trị mặc định. Lấy từ thư viện giọng (endpoint công khai) và dùng nguyên văn id của giọng.

3. Tạo tác vụ, chờ xong và tải file

// Node.js 18+ — chạy: VOICE1_API_KEY=vs_test_... node quickstart.mjs  (Windows: xem mục "Chạy trên Windows")
import { writeFile } from 'node:fs/promises'

const BASE = 'https://voice1.pro'
const headers = {
  Authorization: `Bearer ${process.env.VOICE1_API_KEY}`,
  'Content-Type': 'application/json',
}

async function api(path, init = {}) {
  const res = await fetch(BASE + path, { ...init, headers: { ...headers, ...init.headers } })
  if (!res.ok) {
    const err = await res.json().catch(() => ({}))
    throw new Error(`${res.status} ${err.code}: ${err.message}`)
  }
  return res
}

// 1. Chọn giọng tiếng Việt
const voices = await (await api('/api/v1/voices?provider=elevenlabs&language=vi&pageSize=5')).json()
const voiceId = voices.items[0]?.id ?? 'jdlxsPOZOHdGEfcItXVu'

// 2. Tạo tác vụ (Idempotency-Key: gửi lại khi mạng lỗi không bị trừ tiền hai lần)
const task = await (await api('/api/v1/text-to-speech/elevenlabs', {
  method: 'POST',
  headers: { 'Idempotency-Key': `demo-${Date.now()}` },
  body: JSON.stringify({
    text: 'Xin chào! Đây là giọng nói tạo bằng API Voice1.',
    voiceId,
    modelId: 'eleven_v4',
  }),
})).json()
console.log('Đã tạo', task.id, '— chi phí', task.creditsCost, 'credit (khóa thử: không trừ)')

// 3. Chờ xong — giãn nhịp hỏi theo thời gian ước tính server trả về
let st
for (;;) {
  const { items } = await (await api('/api/v1/history/status', {
    method: 'POST',
    body: JSON.stringify({ ids: [task.id] }),
  })).json()
  st = items[0]
  // Không còn trong danh sách = tác vụ đã bị xóa (bị hủy, credit đã hoàn)
  if (!st) throw new Error(`Tác vụ ${task.id} không còn — có thể đã bị xóa`)
  if (st.status === 'completed' || st.status === 'failed') break
  const waitSec = Math.min(15, Math.max(2, st.etaDoneMinSec ?? 3))
  await new Promise((r) => setTimeout(r, waitSec * 1000))
}
if (st.status !== 'completed') throw new Error(`Tác vụ thất bại — xem lý do ở GET /api/v1/history/${task.id}`)

// 4. Tải file (audioUrl là đường dẫn, ghép với BASE; api() đã báo lỗi nếu không phải 2xx)
// Đuôi file lấy theo audioUrl: thường là .mp3, cũng có thể là .wav
const audio = await api(st.audioUrl)
const file = `voice1.${st.audioUrl.split('.').pop()}`
await writeFile(file, Buffer.from(await audio.arrayBuffer()))
console.log('Đã lưu', file)

Ghép đường dẫn file

Base URL https://voice1.pro/api + đường dẫn trong tài liệu (/v1/…). Riêng audioUrl (/api/v1/audio/<id>/audio.mp3 hoặc audio.wav) đã có sẵn /api — ghép với https://voice1.pro (không phải với https://voice1.pro/api, nếu không sẽ thành /api/api/…). Tải file qua audioUrl cần header Authorization; downloadUrl là link đầy đủ, không cần khóa. Luôn kiểm tra mã HTTP trước khi ghi file: khi lỗi, body là JSON chứ không phải audio.

Chạy trên Windows

  • PowerShell: $env:VOICE1_API_KEY="vs_test_..." rồi python quickstart.py hoặc node quickstart.mjs.
  • cmd: set VOICE1_API_KEY=vs_test_... rồi chạy như trên.
  • cURL trong PowerShell: gõ curl.exe (chữ curl trong PowerShell là lệnh khác). Hoặc dùng Git Bash / WSL.
  • Tiếng Việt qua cURL: lưu body vào file UTF-8 rồi gửi --data-binary @body.json. Gửi thẳng -d '…' có thể hỏng dấu — API trả 400 kèm hướng dẫn.
  • Thử nhanh: có thể dán khóa thẳng vào code, nhưng đừng commit hay chia sẻ file đó.

Tiếp theo

  • Đọc Luồng bất đồng bộ để theo dõi nhiều tác vụ hiệu quả.
  • Đọc Lỗi & xử lý trước khi đưa lên production.
  • Không muốn hỏi trạng thái liên tục? Đặt Webhook để được báo khi tác vụ xong.
  • Không viết code, dùng Make / n8n / Zapier? Xem Dùng với Make, n8n, Zapier.
  • Dùng Postman / Insomnia hay sinh SDK? Tải file OpenAPI hoặc Postman ở đầu trang.
  • Cần đọc nhiều file một lúc? Dùng endpoint tạo hàng loạt (tối đa 25 file mỗi lần).