SomSpeech API reference
Integrate natural speech into your application. List voices, send text, and receive MP3 audio with two REST endpoints.
https://somspeech.comNo daily or monthly quota · 1,950 characters per request. Availability remains subject to speech service and hosting capacity.
Quickstart
Choose a voice
Fetch the voice list and save its index.
Send your text
POST JSON with text and voiceIndex.
Play your audio
Save the returned MP3 bytes or create a Blob URL.
curl -X POST "https://somspeech.com/api/tts" \
-H "Content-Type: application/json" \
-d '{"voiceIndex":1,"text":"Ku soo dhawoow SomSpeech.","pitch":0,"rate":0}' \
--output somspeech.mp3/api/voices
application/jsonReturns available voices with public 1-based indices, grouped by language. Somali voices appear first. Use the returned index for speech requests. Refresh the list when integrating; indices can change when the catalog changes.
curl "https://somspeech.com/api/voices"{
"success": true,
"total": 1,
"voices": [
{ "index": 1, "id": "somali-somalia-male-muuse",
"name": "Muuse", "gender": "Male",
"language": "Somali", "country": "Somalia" }
],
"grouped": {
"Somali": [
{ "index": 1, "id": "somali-somalia-male-muuse",
"name": "Muuse", "gender": "Male",
"language": "Somali", "country": "Somalia" }
]
}
}The live response contains the complete available catalog. IDs are public SomSpeech identifiers.
/api/tts
audio/mpegGenerate one chunk of speech. Send Content-Type: application/json. A successful response contains raw MP3 bytes, ready to save or play.
| Parameter | Type | Description |
|---|---|---|
voiceIndex | number · required | Positive integer from /api/voices. |
text | string · required | Non-empty text, up to 1,950 UTF-16 code units (JavaScript text.length). |
pitch | number · optional | Somali voices only: −100 deeper to +100 higher. Default: 0. Other languages must use 0 or omit. |
rate | number · optional | Somali voices only: −100 slower to +100 faster. Default: 0. Other languages must use 0 or omit. |
Response headers
X-Pitch, X-Rate, X-Voice-Name, and X-Char-Count describe the generated audio. Decode the voice name with decodeURIComponent().
Long text. One audio file.
Split at sentence boundaries, request chunks in parallel, and concatenate MP3 Blobs in their original order. The example checks every response before merging. For large workloads, send batches to keep memory and network usage manageable.
const baseURL = "https://somspeech.com";
// Split at sentence or word boundaries; keep each chunk <=1950.
function splitText(input, max = 1950) {
const chunks = [];
let rest = input.trim();
while (rest.length > max) {
const window = rest.slice(0, max);
const sentence = Math.max(window.lastIndexOf(". "),
window.lastIndexOf("! "), window.lastIndexOf("? "));
let end = sentence > max / 2 ? sentence + 1
: window.lastIndexOf(" ");
if (end <= 0) end = max;
// Avoid splitting a UTF-16 surrogate pair.
if (/[\uD800-\uDBFF]/.test(rest[end - 1])) end--;
chunks.push(rest.slice(0, end).trim());
rest = rest.slice(end).trim();
}
if (rest) chunks.push(rest);
return chunks;
}
async function generateSpeech(text, voiceIndex, pitch = 0, rate = 0) {
const chunks = splitText(text);
if (!chunks.length) throw new Error("Text is required.");
const blobs = await Promise.all(chunks.map(async chunk => {
const response = await fetch(baseURL + "/api/tts", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ voiceIndex, text: chunk, pitch, rate })
});
if (!response.ok) {
const error = await response.json();
throw new Error(error.error || "Speech generation failed.");
}
return response.blob();
}));
return new Blob(blobs, { type: "audio/mpeg" });
}
const blob = await generateSpeech("Ku soo dhawoow SomSpeech.", 1);
const url = URL.createObjectURL(blob);
const player = new Audio(url);
await player.play();
// Call URL.revokeObjectURL(url) when finished with the audio.Errors & troubleshooting
Errors return JSON with success: false and a readable error message. Browser requests are supported from any origin; credentials and cookies are unnecessary.
| Status | Meaning | Next step |
|---|---|---|
400 | Invalid request | Check the voice index, JSON, text length, and pitch/rate. Non-zero pitch/rate require a Somali voice. |
405 | Wrong method | Use GET for voices and POST for speech. |
502 | Speech service unavailable | Retry after a short delay, with a bounded retry count. |
{ "success": false, "error": "Invalid voiceIndex. Select an index from GET /api/voices." }Hear your first request.
This playground calls the same public API documented above. All languages are available; pitch and rate adjustments are supported only for Somali voices.