REST API · v1

API Reference

Integrate Sooddy text-to-speech into your own apps and scripts. A Pro subscription is required.

Base URL https://sooddy.com/api
INFO

Authentication

All protected endpoints use Bearer token authentication via Laravel Sanctum. Generate a personal access token from Profile → API access (Pro plan required).

Request header http
Authorization: Bearer YOUR_API_TOKEN

✓ Pro subscribers

Full API access

✗ Free users

Requests return 403

✓ Public endpoints

No auth needed

INFO

Error codes

All errors return JSON with a message field and an optional code field.

HTTP Code Meaning
401 unauthenticated Missing or invalid token
403 pro_required Token owner is not a Pro subscriber
402 insufficient_balance Wallet balance too low
422 Validation error — check request body
429 quota_exceeded Daily character quota exhausted
429 Rate limit hit (40 req / min on /tts)
500 Server error — contact support
GET /api/voices
PUBLIC

List voices

Returns all active voices. No authentication required.

Request bash
curl https://sooddy.com/api/voices
Response 200 json
{
    "data": [
        {
            "id": 42,
            "name": "Amy",
            "slug": "en_amy",
            "language": "en",
            "engine": "piper",
            "gender": "female",
            "preview_url": "https:\/\/sooddy.com\/audio\/example\/stream"
        },
        {
            "...": "more voices"
        }
    ]
}
GET /api/languages
PUBLIC

List languages

Returns all language codes with their display names.

Request bash
curl https://sooddy.com/api/languages
Response 200 json
{
    "data": [
        {
            "code": "en",
            "name": "English",
            "voice_count": 48
        },
        {
            "code": "de",
            "name": "German",
            "voice_count": 12
        },
        {
            "...": "more languages"
        }
    ]
}
GET /api/quota
PRO

Get quota

Returns your current daily character quota and usage.

Request bash
curl https://sooddy.com/api/quota \
  -H "Authorization: Bearer YOUR_API_TOKEN"
Response 200 json
{
    "data": {
        "limit": 100000,
        "used": 12450,
        "remaining": 87550,
        "resets_at": "2026-07-16T00:00:00Z"
    }
}
GET /api/history
PRO

List history

Returns a paginated list of your recent TTS generations.

Query param Type Default Description
page integer 1 Page number
per_page integer 15 Items per page (max 100)
Request bash
curl "https://sooddy.com/api/history?page=1&per_page=15" \
  -H "Authorization: Bearer YOUR_API_TOKEN"
Response 200 json
{
    "data": [
        {
            "uuid": "a1b2c3d4-...",
            "status": "completed",
            "text": "Hello world",
            "voice": "en_amy",
            "duration_s": 1.24,
            "chars": 11,
            "audio_url": "https:\/\/sooddy.com\/audio\/a1b2c3d4-...\/stream",
            "created_at": "2026-07-15T10:30:00Z"
        }
    ],
    "meta": {
        "page": 1,
        "per_page": 15,
        "total": 87
    }
}
POST /api/tts
PRO

Create speech

Submits a TTS job and returns 202 Accepted immediately with a poll_url. Use Poll status to track completion.

Field Type Required Description
text* string Yes Text to synthesise. Max 15,000 chars (Pro).
voice* string Yes Voice slug — e.g. en_amy. See /api/voices.
speed float No Playback speed 0.5–2.0. Default: 1.0.
format string No Output format: mp3 or wav. Default: mp3.
Request bash
curl -X POST https://sooddy.com/api/tts \
  -H "Authorization: Bearer YOUR_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "text":   "Hello from the API!",
    "voice":  "en_amy",
    "speed":  1.0,
    "format": "mp3"
  }'
Response 202 Accepted json
{
    "data": {
        "uuid": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
        "status": "queued",
        "created_at": "2026-07-15T10:30:00Z"
    },
    "poll_url": "https:\/\/sooddy.com\/api\/tts\/a1b2c3d4-e5f6-7890-abcd-ef1234567890"
}
GET /api/tts/{uuid}
PRO

Poll status

Poll after submitting a job. Status transitions: queuedprocessingcompleted (or failed). When completed, the audio_url is ready.

Request bash
curl https://sooddy.com/api/tts/{uuid} \
  -H "Authorization: Bearer YOUR_API_TOKEN"
Pending json
{
    "data": {
        "uuid": "a1b2c3d4-...",
        "status": "processing"
    }
}
Completed json
{
    "data": {
        "uuid": "a1b2c3d4-...",
        "status": "completed",
        "duration_s": 1.24,
        "chars": 20,
        "audio_url": "https:\/\/sooddy.com\/audio\/a1b2c3d4-...\/stream",
        "download_url": "https:\/\/sooddy.com\/audio\/a1b2c3d4-...\/download"
    }
}
Polling example javascript
async function generateSpeech(text, voice, token) {
  const BASE = 'https://sooddy.com/api';

  // 1. Submit the job
  const res = await fetch(`${BASE}/tts`, {
    method: 'POST',
    headers: {
      'Authorization': `Bearer ${token}`,
      'Content-Type':  'application/json',
    },
    body: JSON.stringify({ text, voice }),
  });
  const { poll_url } = await res.json();

  // 2. Poll until done (max 60 s)
  for (let i = 0; i < 30; i++) {
    await new Promise(r => setTimeout(r, 2000));
    const poll = await fetch(poll_url, {
      headers: { 'Authorization': `Bearer ${token}` },
    });
    const { data } = await poll.json();
    if (data.status === 'completed') return data.audio_url;
    if (data.status === 'failed')    throw new Error('TTS job failed');
  }
  throw new Error('Timed out waiting for TTS job');
}