Docs
Text-to-Speech
Generate TTS audio and receive a permanent hosted audio URL.
Generate high-quality TTS audio programmatically. Submit a script, choose a voice, and receive a permanent hosted audio URL. Uses character-based credits (see Credits & Billing).
GET/api/voices
Browse and search available ElevenLabs voices. Returns voice IDs you can use with provider=elevenlabs. For Stealth voices, use /api/voices/stealth instead.
Headers
| Name | Type | Required | Description |
|---|---|---|---|
| Authorization | string | Required | Bearer token: Bearer YOUR_API_KEY |
Query Parameters
| Name | Type | Required | Default | Description |
|---|---|---|---|---|
| search | string | Optional | — | Search by voice name or labels |
| gender | string | Optional | — | Filter by gender: male, female, or neutral |
| age | string | Optional | — | Filter by age: young, middle_aged, or old |
| language | string | Optional | — | Language code (e.g. en, es, fr) |
| accent | string | Optional | — | Filter by accent (e.g. american, british) |
| sort | string | Optional | trending | Sort by: trending, created_date, usage_character_count_1y |
| page_size | integer | Optional | 30 | Results per page (max 100) |
| page | integer | Optional | 0 | Page number (0-indexed) |
# Browse trending voices curl "https://api.algrow.online/api/voices?sort=trending&page_size=10" \ -H "Authorization: Bearer YOUR_API_KEY" # Search for female English voices curl "https://api.algrow.online/api/voices?search=narrator&gender=female&language=en" \ -H "Authorization: Bearer YOUR_API_KEY"
{
"success": true,
"voices": [
{
"voice_id": "EkK5I93UQWFDigLMpZcX",
"name": "James - Husky, Engaging and Bold",
"gender": "male",
"age": "middle_aged",
"accent": "american",
"language": "en",
"description": "A slightly husky and bassy voice...",
"preview_url": "https://...",
"category": "high_quality",
"use_case": "narrative_story"
}
],
"has_more": true
}POST/api/generate-simple
Create a text-to-speech generation job. Returns a job_id immediately. The audio is generated asynchronously — poll /api/job-status/:job_id to check progress and retrieve the audio URL when complete.
Headers
| Name | Type | Required | Description |
|---|---|---|---|
| Authorization | string | Required | Bearer token: Bearer YOUR_API_KEY |
| Content-Type | string | Auto | Set automatically by curl -F. If manual: multipart/form-data |
Request Parameters (form-data)
| Name | Type | Required | Default | Description |
|---|---|---|---|---|
| script | string | Required | — | Text to convert to speech. Limit depends on plan & provider (see table below). |
| voice_id | string | Required | — | Voice ID. For ElevenLabs: e.g. 21m00Tcm4TlvDq8ikWAM. For Stealth: use the voice_id from /api/voices/stealth. For MiniMax: use the voice_id from /api/voices/minimax (clone first). |
| provider | string | Optional | elevenlabs | TTS engine. Values: elevenlabs, stealth, minimax |
| model_id | string | Optional | eleven_multilingual_v2 | Model to use. Also available: eleven_v3, eleven_v4 (newest, most expressive; bills 3× characters), eleven_turbo_v2_5, eleven_flash_v2_5, eleven_turbo_v2, eleven_flash_v2 |
| stability | float | Optional | 0.5 | Voice consistency. Higher = more stable, lower = more expressive. Range: 0.0 – 1.0 |
| similarity_boost | float | Optional | 0.5 | How closely to match the original voice. Range: 0.0 – 1.0 |
| style | float | Optional | 0.0 | Speaking style exaggeration. Higher values amplify the voice's style. Range: 0.0 – 1.0 |
| speed | float | Optional | 1.0 | Playback speed. Range: 0.7 – 1.2 (ElevenLabs) or 0.5 – 2.0 (MiniMax) |
| pitch | int | Optional | 0 | Pitch shift in semitones. Range: -12 – +12. (MiniMax only) |
| volume | float | Optional | 1.0 | Output volume multiplier. Range: 0.0 – 10.0. (MiniMax only) |
| voice_name | string | Optional | voice_id | Human-readable label for this voice (for your reference only) |
| custom_title | string | Optional | — | Custom filename for the output MP3 (without extension) |
| generate_srt | string | Optional | false | ElevenLabs only: set to true to generate an SRT subtitle file. Bills 1.2× characters. Ignored for Stealth, which always returns a free word-level SRT. |
| temperature | float | Optional | 1.1 | Voice expressiveness (Stealth only). Higher = more expressive. |
| speaking_rate | float | Optional | 1.0 | Speaking speed multiplier (Stealth only). |
| stealth_model | string | Optional | 1.5 | Stealth model tier (Stealth only). 1.5 = standard model (1× characters, default); 2.0 = Stealth 2.0, our newest, most capable model (2× characters). |
Provider-specific parameters: When provider=stealth: only temperature, speaking_rate and stealth_model are used. Parameters stability, similarity_boost, style, speed, and model_id are ignored. When provider=elevenlabs (default): only stability, similarity_boost, style, speed, and model_id are used. Parameters temperature and speaking_rate are ignored. When provider=minimax: only speed, pitch, and volume are used. The voice must be cloned via /api/voices/minimax/clone first. Minimum 200 characters.
Stealth models: Two tiers, selected with stealth_model. 1.5 (default) is the standard model and bills 1× characters. 2.0 is Stealth 2.0 — our newest, most capable model with richer expression and stronger multilingual quality — and bills 2× characters against your Stealth balance. Both auto-chunk at ~1,900 char boundaries. Output: MP3, uploaded to CDN.
SRT subtitles: Setting generate_srt=true (ElevenLabs only) runs an extra forced-alignment pass to produce a word-timed subtitle file alongside the audio, and bills 1.2× the character count of your script. Without it, generation bills 1×. model_id=eleven_v4 bills 3× characters, and the two stack (v4 with SRT bills 3.6×). Stealth jobs always include a word-level SRT as transcript_url at no extra cost, so generate_srt is ignored there and billing stays at 1× the script characters (2× on Stealth 2.0).
Per-generation character limits:
| Provider | Professional | Ultimate |
|---|---|---|
| ElevenLabs | 100,000 | 200,000 |
| Stealth | 45,000 | 100,000 |
| MiniMax | 100,000 | 200,000 |
Response Fields
| Field | Type | Description |
|---|---|---|
| success | boolean | Whether the request was accepted |
| job_id | string | Unique job identifier. Use this to poll for status. |
| status | string | Current job status: pending |
| status_detail_message | string | Human-readable status message |
| message | string | Informational message |
| payload | object | Echo of the submitted parameters (text, voice_id, settings, etc.) |
200 Queued 400 Validation error 401 Auth failed 402 No credits 403 Plan required 429 Too busy 500 Server error
curl -X POST "https://api.algrow.online/api/generate-simple" \ -H "Authorization: Bearer YOUR_API_KEY" \ -F "script=Hello, welcome to our channel." \ -F "voice_id=21m00Tcm4TlvDq8ikWAM" \ -F "provider=elevenlabs" \ -F "stability=0.7" \ -F "similarity_boost=0.8"
curl -X POST "https://api.algrow.online/api/generate-simple" \ -H "Authorization: Bearer YOUR_API_KEY" \ -F "script=Hello, welcome to our channel." \ -F "voice_id=Evan" \ -F "provider=stealth" \ -F "temperature=1.1" \ -F "speaking_rate=1.0"
curl -X POST "https://api.algrow.online/api/generate-simple" \ -H "Authorization: Bearer YOUR_API_KEY" \ -F "script=Hello, welcome to our channel." \ -F "voice_id=Evan" \ -F "provider=stealth" \ -F "stealth_model=2.0" \ -F "temperature=1.1" \ -F "speaking_rate=1.0"
{
"success": true,
"job_id": "d477b67a-bb9d-403e-a6cf-bc8a82c93a61",
"status": "pending",
"status_detail": "pending",
"status_detail_message": "Processing",
"message": "Generation queued. Worker will process it.",
"payload": {
"text": "Hello, welcome to our channel.",
"voice_id": "21m00Tcm4TlvDq8ikWAM",
"voice_name": "21m00Tcm4TlvDq8ikWAM",
"settings": { ... }
}
}GET/api/job-status/:job_id
Retrieve the current status and result of a generation job. Poll this endpoint every 2–3 seconds until status is completed or failed. Typical generation time is 3–15 seconds depending on script length.
Path Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| job_id | string | Required | The job_id returned from POST /api/generate-simple |
Response Fields
| Field | Type | Description |
|---|---|---|
| success | boolean | Always true if the job was found |
| job_id | string | The job identifier |
| status | string | One of: pending, processing, completed, failed |
| status_detail_message | string | Human-readable status: "Processing", "Completed", or "Failed" |
| created_at | float | Unix timestamp when the job was created |
| completed_at | float | Unix timestamp when the job finished (only present when done) |
| audio_url | string | Permanent URL to the MP3 file. After generation, audio is uploaded to Cloudflare R2 and served via our CDN at audio.algrow.online — this URL will not expire. (Only when status=completed) |
| transcript_url | string | Permanent URL to the SRT subtitle file, built from word-level timestamps. Always present for completed Stealth jobs (free). For ElevenLabs, only present when generate_srt=true was passed. |
| error | string | Error description (only when status=failed) |
| error_code | string | Machine-readable error code, e.g. TERMS_OF_SERVICE_VIOLATION (only when status=failed, if available) |
| error_message | string | Human-readable error message from the provider (only when status=failed, if available) |
Status lifecycle: pending → processing → completed or failed. Typical completion time is 3–15 seconds.
200 Success 401 Auth failed 404 Job not found
curl "https://api.algrow.online/api/job-status/300040" \ -H "Authorization: Bearer YOUR_API_KEY"
{
"success": true,
"job_id": "d477b67a-bb9d-403e-a6cf-bc8a82c93a61",
"status": "processing",
"status_detail": "processing",
"status_detail_message": "Processing",
"created_at": 1772482202.525
}{
"success": true,
"job_id": "d477b67a-bb9d-403e-a6cf-bc8a82c93a61",
"status": "completed",
"status_detail": "completed",
"status_detail_message": "Completed",
"created_at": 1772482202.525,
"completed_at": 1772482210.831,
"audio_url": "https://audio.algrow.online/elevenlabs/tts/user123/300040.mp3",
"transcript_url": "https://audio.algrow.online/elevenlabs/tts/user123/transcript_300040.srt"
}{
"success": true,
"job_id": "d477b67a-bb9d-403e-a6cf-bc8a82c93a61",
"status": "failed",
"status_detail": "failed",
"status_detail_message": "Failed",
"created_at": 1772482202.525,
"completed_at": 1772482215.100,
"error": "Async job failed: [TERMS_OF_SERVICE_VIOLATION] The text you are trying to use may violate our Terms of Service and has been blocked.",
"error_code": "TERMS_OF_SERVICE_VIOLATION",
"error_message": "The text you are trying to use may violate our Terms of Service and has been blocked."
}GET/api/jobs
List your generation jobs, sorted by creation time (newest first). Returns only jobs belonging to the authenticated user. Useful for debugging and monitoring your recent generations.
curl "https://api.algrow.online/api/jobs" \ -H "Authorization: Bearer YOUR_API_KEY"
{
"success": true,
"jobs": [
{
"id": "300040",
"provider": "elevenlabs",
"status": "completed",
"script_length": 340,
"created_at": 1772482202.525,
"completed_at": 1772482210.831
}
]
}GET/api/health
Check API health and view your current job counts. No authentication required. Use this to verify the API is online and check how many concurrent slots you have available.
curl "https://api.algrow.online/api/health" \ -H "Authorization: Bearer YOUR_API_KEY"
{
"status": "healthy",
"active_jobs": 2,
"total_jobs": 15
}POST/api/reports
Publish a self-contained HTML report to Algrow's public report host and get back a stable URL on audio.algrow.online — no storage credentials needed. Built for agent skills that render analysis reports (channel decodes, audits, idea backlogs) and want to hand the user a hosted link. Reports are namespaced per user: re-posting the same slug overwrites your own report (re-render = same URL); you can never touch another user's. Pages are served with noindex so they stay out of search engines.
Request Body (JSON)
| Name | Type | Required | Default | Description |
|---|---|---|---|---|
| slug | string | Required | — | URL slug for the report: 3–80 chars of a-z 0-9 -, starting alphanumeric. Same slug → overwrite your own previous version. |
| html | string | Required | — | The complete, self-contained HTML document (must start with <!DOCTYPE html> or <html>). Max 2 MB — inline your CSS; link external images/fonts by URL. |
Limits. 50 uploads per key per 24h, on top of the standard per-key rate limit. A <meta name="robots" content="noindex"> tag is injected automatically if missing.
200 Report published 400 Bad slug / not a complete HTML document 401 Auth failed 413 HTML too large (2 MB cap) 429 Daily upload cap reached
No example for this one.
GET/api/credits
Check what your key has left to spend. Returns your studio credit balance (what image, video, thumbnail and caption-remover calls draw from) plus both voice character pools. ElevenLabs and MiniMax share one pool (tts_characters); Stealth has its own (stealth_characters). Studio credits and plan characters reset every month on period_end; purchased characters roll over and are only spent once the plan allowance is gone.
Response Fields
| Field | Type | Description |
|---|---|---|
| plan | string | Your current plan tier (starter, professional or ultimate). |
| credits.remaining | number | Studio credits left this period. Spent by /api/generate-image, /api/generate-video, the /api/thumbnails endpoints and /api/caption-remover. |
| credits.limit | number | Studio credits included this period, purchased credits included. |
| credits.period_end | string | ISO timestamp of the next monthly reset. |
| tts_characters.remaining | number | Characters available to /api/generate-simple with provider=elevenlabs or provider=minimax (plan allowance plus purchased). |
| tts_characters.purchased_remaining | number | Characters bought as credit packs. These roll over between periods. |
| stealth_characters.remaining | number | Characters available to /api/generate-simple with provider=stealth. Separate pool from tts_characters; a Stealth generation on the 2.0 model bills double the script length. |
| stealth_characters.purchased_remaining | number | Stealth characters bought as top-ups. These roll over between periods. |
200 Success 401 Auth failed
curl "https://api.algrow.online/api/credits" \ -H "Authorization: Bearer YOUR_API_KEY"
{
"success": true,
"plan": "professional",
"credits": {
"remaining": 257.5,
"limit": 300,
"used": 42.5,
"period_start": "2026-08-01T09:14:22+00:00",
"period_end": "2026-08-31T09:14:22+00:00"
},
"tts_characters": {
"remaining": 120000,
"plan_remaining": 100000,
"plan_limit": 100000,
"purchased_remaining": 20000
},
"stealth_characters": {
"remaining": 1850000,
"plan_remaining": 1850000,
"plan_limit": 2000000,
"purchased_remaining": 0
}
}