Online Text Reader API: MP3 Over REST
You need to turn plain text into an MP3 file over HTTP, reliably and fast, without wiring up SDKs or message buses. By the end of this guide, you’ll be able to POST text to Woord’s Online Text Reader API and download an MP3 URL directly from the response, integrate it in a background job or a web form, and handle errors, quotas, and deployment details with confidence.
What you’ll build and the constraints to respect
Woord’s Online Text Reader API is a REST endpoint that converts text into an MP3. You submit a short request with your text and voice parameters, and the service responds with a URL you can download. The request body is form-encoded (not JSON) and requires Bearer authentication.
Plan and quota details relevant to your implementation:
- Per-file character cap: 10,000 characters.
- Starter plan: $9.99/mo.
- Trial: 8 days / 20,000 characters.
There is no MCP in this flow. For complete parameter details and supported languages/voices, see the Documentation. To begin your trial, Register.
Endpoint and authentication
Woord’s TTS conversion happens through a single POST endpoint:
- Method and URL: POST https://www.getwoord.com/api/convert
- Auth: Bearer token in the Authorization header
- Body: form fields (not JSON)
Required form fields in this integration:
- text: the text to convert to speech (respect the 10k characters per file cap)
- gender_voice: the desired voice gender
- language: the language code/name supported by Woord
If you need enumerations (e.g., valid language and voice options), consult the Documentation. Keep your API key secure, do not embed it in client-side code.
Quickstart: curl request
This is a complete, copy-pasteable curl example. Replace YOUR_API_KEY with your token and adjust the form fields to the language and voice you need.
curl -X POST https://www.getwoord.com/api/convert \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/x-www-form-urlencoded" \
--data-urlencode "text=Hello from Woord. This will be converted to an MP3." \
--data-urlencode "gender_voice=female" \
--data-urlencode "language=en-US"
Below is the official request sample for the same endpoint:
curl "https://www.getwoord.com/api/convert" -X POST \
-H "Accept: application/json" \
-H "Authorization: Bearer ACCESS_KEY" \
--data "text=Hello+from+Woord&gender_voice=female&language=en_US&speakingRate=1.00"
Understanding the response
The API returns JSON with the information you need to retrieve the generated MP3. Here is the official sample response:
{
"message": "Your audio has been created!",
"audio_src": "https://getwoord.s3.amazonaws.com/4273352455515882618255eaaf3c1cbdbe0.55443890.mp3",
"error": false
}
From this JSON, you will use the following fields in your application:
- audio_src: a URL you can download to obtain the MP3 generated for your specific request. Always download the URL from your own request; do not reuse sample values.
- success and/or error/message fields (if present in the sample): use these to determine whether the conversion succeeded. If success is false or an error/message indicates a problem, handle it as described below.
- Any additional identifiers present in the sample (e.g., request or conversion IDs): these can help you correlate logs and retries.
Important: if your code does not find audio_src in the response, treat it as a failed conversion and retry or surface the error to the caller. Do not assume that a 200 HTTP status always implies a valid audio URL—check the response fields.
Official flow: request and download
The integration pattern is straightforward:
- Send a POST to https://www.getwoord.com/api/convert with the form fields text, gender_voice, and language, and a Bearer token in the Authorization header.
- Parse the JSON response and retrieve audio_src from your own request.
- Download the URL to obtain your MP3.
Below is a concise Python example that completes the round trip:
import os
import sys
import requests
API_URL = "https://www.getwoord.com/api/convert"
API_KEY = os.getenv("WOORD_API_KEY", "YOUR_API_KEY")
def text_to_mp3(text, gender_voice, language, out_path):
# 1) Send the form-encoded POST
headers = {"Authorization": f"Bearer {API_KEY}"}
data = {
"text": text,
"gender_voice": gender_voice,
"language": language,
}
resp = requests.post(API_URL, headers=headers, data=data, timeout=60)
# 2) Validate HTTP status
try:
resp.raise_for_status()
except Exception as e:
raise SystemExit(f"HTTP error: {e}")
# 3) Parse JSON and validate the fields you need
try:
payload = resp.json()
except ValueError:
raise SystemExit("Response is not valid JSON")
# Check for a success flag if present, and ensure we have audio_src
if isinstance(payload, dict):
success = payload.get("success", True) # default to True if not provided
audio_src = payload.get("audio_src")
else:
raise SystemExit("Unexpected JSON structure")
if not success:
# If the API includes an error or message field, show it.
err = payload.get("error") or payload.get("message") or "Unknown error"
raise SystemExit(f"TTS conversion failed: {err}")
if not audio_src:
raise SystemExit("Missing audio_src in response")
# 4) Download the MP3
with requests.get(audio_src, stream=True, timeout=120) as r:
r.raise_for_status()
with open(out_path, "wb") as f:
for chunk in r.iter_content(chunk_size=8192):
if chunk:
f.write(chunk)
return out_path
if __name__ == "__main__":
text = "Hello from Woord. This will be converted to an MP3."
gender = "female"
lang = "en-US"
out = "woord_output.mp3"
try:
path = text_to_mp3(text, gender, lang, out)
print(f"Saved MP3 to {path}")
except SystemExit as e:
print(e)
sys.exit(1)
Handling failures and missing values
Build your client to validate both transport and semantic success:
- HTTP layer: non-2xx should fail fast with a clear message. Consider retrying idempotently if the failure is transient (connection resets, timeouts).
- JSON layer: if the payload cannot be parsed, treat it as a failure and log the response body for support.
- API semantics: check a success flag if present. If success is false or audio_src is missing, surface the error and consider a retry policy appropriate for your workflow.
- Field presence: do not assume optional fields exist. Use safe accessors (e.g., dict.get in Python) and branch accordingly.
If you encounter persistent issues with certain parameters (e.g., unsupported language/voice combinations), verify the exact values against the Documentation and test a minimal payload first.
Character caps, batching, and splitting text
The per-file cap is 10,000 characters. If your input is longer, split it before sending to the API.
- Split on natural boundaries (sentences, paragraphs) to avoid audible jumps.
- Keep each chunk under 10,000 characters. Account for any templated preface you add (e.g., SSML-like tags if supported—confirm format requirements in the docs).
- Decide whether you want a single audio file or multiple. If you need a single output, concatenate the returned MP3s on your side after downloading (outside the API).
Character usage is your main “unit” to monitor for costs and quotas, so add server-side validation and guardrails before calling the API.
Caching and re-use
If you generate the same text, voice, and language repeatedly, avoid recomputing it:
- Deduplicate requests by hashing the triplet (text, gender_voice, language) and caching the resulting MP3 in your storage.
- Store the MP3 with metadata (input hash, language, gender voice) to make cache lookups easy.
- Download audio_src once per unique input and serve the MP3 directly from your CDN or media storage for playback at scale.
Do not hardcode or share audio_src from sample or other users; always use the URL returned from your own request.
Time, localization, and content
The API converts text to audio without explicit time scheduling constraints. You may experience queueing in peak hours; implement reasonable HTTP timeouts and background job retries. For locale-sensitive content, ensure your language parameter matches the content’s language and any desired accent. If you are assembling dynamic prompts from multiple sources, normalize whitespace and punctuation to keep speech natural.
JavaScript example (Node.js)
Here’s the same workflow in Node.js using node-fetch (or any Fetch-compatible client). It posts form fields, reads JSON, and downloads the MP3.
import fs from "fs";
import fetch from "node-fetch";
import { URLSearchParams } from "url";
const API_URL = "https://www.getwoord.com/api/convert";
const API_KEY = process.env.WOORD_API_KEY || "YOUR_API_KEY";
async function textToMp3(text, genderVoice, language, outPath) {
// 1) POST form fields
const params = new URLSearchParams();
params.append("text", text);
params.append("gender_voice", genderVoice);
params.append("language", language);
const resp = await fetch(API_URL, {
method: "POST",
headers: {
"Authorization": `Bearer ${API_KEY}`,
"Content-Type": "application/x-www-form-urlencoded",
},
body: params.toString(),
});
if (!resp.ok) {
const body = await resp.text();
throw new Error(`HTTP ${resp.status}: ${body}`);
}
// 2) Parse JSON
let payload;
try {
payload = await resp.json();
} catch {
throw new Error("Response is not valid JSON");
}
// 3) Validate success and audio_src
const success = payload.success !== false; // default to true if field absent
const audioSrc = payload.audio_src;
if (!success) {
const err = payload.error || payload.message || "Unknown error";
throw new Error(`TTS conversion failed: ${err}`);
}
if (!audioSrc) {
throw new Error("Missing audio_src in response");
}
// 4) Download the MP3
const audioResp = await fetch(audioSrc);
if (!audioResp.ok) {
const body = await audioResp.text();
throw new Error(`Audio download failed: ${audioResp.status} ${body}`);
}
const fileStream = fs.createWriteStream(outPath);
await new Promise((resolve, reject) => {
audioResp.body.pipe(fileStream);
audioResp.body.on("error", reject);
fileStream.on("finish", resolve);
});
return outPath;
}
(async () => {
try {
const path = await textToMp3(
"Hello from Woord. This will be converted to an MP3.",
"female",
"en-US",
"woord_output.mp3"
);
console.log(`Saved MP3 to ${path}`);
} catch (e) {
console.error(e);
process.exit(1);
}
})();
Production and security considerations
- Secrets: store your API key in server-side secrets management. Never expose it in browsers or mobile apps.
- Timeouts: set both connect and read timeouts for the convert request and the subsequent MP3 download.
- Idempotency: if you might retry the same input, de-duplicate requests at the application layer (e.g., by hashing inputs).
- Observability: log request IDs (if present in the response), HTTP statuses, and audio_src for debugging. Avoid logging sensitive text in production if it includes PII.
- No MCP: there is no MCP step to configure in this integration.
Go live in two steps
- Register (https://www.getwoord.com/register?utm_source=blog&utm_medium=article&utm_campaign=online-text-reader-api-mp3&utm_content=register) — 8-day trial / 20k characters.
- POST form fields. Fetch audio_src.
Troubleshooting and edge cases
- 400 or 422 errors: re-check required form fields (text, gender_voice, language). Validate character length stays below 10,000 per file.
- Missing audio_src: consider the conversion failed; inspect any message/error fields and correct inputs accordingly.
- Language/voice mismatch: verify supported combinations in the Documentation.
- Large batch jobs: split text, parallelize responsibly, and cache MP3 outputs so you don’t re-convert identical inputs.
FAQ
How do I authenticate?
Use a Bearer token in the Authorization header when calling POST https://www.getwoord.com/api/convert.
What are the body parameters?
Send form fields text, gender_voice, and language. The request body is not JSON.
How do I get the MP3?
Read audio_src from your own successful response and download that URL to obtain the MP3.
What are the usage limits?
The cap is 10,000 characters per file. The trial provides 8 days / 20,000 characters. The Starter plan is $9.99/mo.
Where can I find full parameter lists and options?
See the Documentation for the latest details.
Create an MP3 with Woord today. Start your 8-day trial and ship your first integration in minutes: Register.
