English (US) Text-to-Speech API in PHP
You have a PHP app and need to generate natural-sounding English (US) speech from text. By the end of this guide, you will send text to the Woord Text-to-Speech API, receive a playable MP3 URL, and integrate it in PHP—plus a Python helper for testing. You will use a Bearer token, form-encoded fields, and production-safe handling of the JSON response.
What you will build and what you need
You will build a minimal PHP integration that posts text to the Woord Text-to-Speech convert endpoint and saves the generated English (US) audio. You will also see how to test the same endpoint with cURL and Python.
- Account and API key: create one here: Register.
- Important: free plans cannot call the convert endpoint. Upgrade after registration to run the requests shown below.
- Language/locale for this guide: English (US).
- PHP 7.4+ or 8.x, with either curl extension or allow_url_fopen enabled (for file_get_contents alternatives).
Endpoint and parameters for English (US) Text-to-Speech
The Woord convert endpoint accepts standard form fields (application/x-www-form-urlencoded) via POST. Authentication uses a Bearer token. The body is not JSON.
- Method: POST
- URL: https://www.getwoord.com/api/convert
- Headers:
- Accept: application/json
- Authorization: Bearer YOUR_API_KEY
- Form fields:
- text: the input text to synthesize
- gender_voice: e.g., male (docs default)
- language: en_US (English, United States)
- speakingRate: 1.00 (shown in the official sample below)
Response returns JSON containing an audio_src field with a public S3 URL for your generated MP3, a message, and an error flag.
Origin catalog facts for this integration
- Language: English (US)
- language=en_US
- gender_voice=male (docs default)
- Sample text from editorial/docs for this locale: Hello World
- curl: curl "https://www.getwoord.com/api/convert" -X POST -H "Accept: application/json" -H "Authorization: Bearer YOUR_KEY" --data "text=Hello+World&gender_voice=male&language=en_US&speakingRate=1.00"
- Official convert envelope:
{"message":"Your audio has been created!","audio_src":"https://getwoord.s3.amazonaws.com/4273352455515882618255eaaf3c1cbdbe0.55443890.mp3","error":false} - The S3 filename is the docs fixture. The reader’s audio_src will be a new key. Do not hotlink this URL.
cURL quickstart: English (US) TTS
This is the official sample request. Copy it, replace YOUR_KEY with your Bearer token, and run it from a terminal. It uses form data, not JSON.
cURL example
curl "https://www.getwoord.com/api/convert" -X POST -H "Accept: application/json" -H "Authorization: Bearer YOUR_KEY" --data "text=Hello+World&gender_voice=male&language=en_US&speakingRate=1.00"
If your token is valid and your plan allows convert, you will receive JSON with message, audio_src, and error fields. Your audio_src will be different from the docs fixture shown below.
Official convert envelope
{
"message": "Your audio has been created!",
"audio_src": "https://getwoord.s3.amazonaws.com/4273352455515882618255eaaf3c1cbdbe0.55443890.mp3",
"error": false
}
Fields you’ll actually use:
- message: confirmation string for logs or UI toasts.
- audio_src: the HTTPS URL of your generated MP3 file.
- error: boolean that signals success (false) or failure (true).
Do not hotlink the fixture audio_src above; when you run your request you will get a new URL. Use your returned URL for downloads and playback.
PHP implementation with curl_init
Below is a minimal PHP function that posts the required form fields and saves the returned MP3 locally. It uses curl_init and expects a valid Bearer token.
PHP (curl_init) example
<?php
function woord_tts_en_us_to_file($apiKey, $text, $outputPath) {
$url = 'https://www.getwoord.com/api/convert';
$postFields = http_build_query([
'text' => $text,
'gender_voice' => 'male',
'language' => 'en_US',
// Optional per sample: speakingRate
'speakingRate' => '1.00',
]);
$ch = curl_init($url);
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
'Accept: application/json',
'Authorization: Bearer ' . $apiKey,
'Content-Type: application/x-www-form-urlencoded',
],
CURLOPT_POSTFIELDS => $postFields,
]);
$response = curl_exec($ch);
if ($response === false) {
$err = curl_error($ch);
curl_close($ch);
throw new RuntimeException('cURL error: ' . $err);
}
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
if ($status < 200 || $status >= 300) {
throw new RuntimeException('Non-2xx status: ' . $status . ' body=' . $response);
}
$json = json_decode($response, true);
if (!is_array($json) || !array_key_exists('error', $json)) {
throw new RuntimeException('Malformed JSON response: ' . $response);
}
if ($json['error'] === true) {
throw new RuntimeException('API returned error=true: ' . $response);
}
if (empty($json['audio_src'])) {
throw new RuntimeException('audio_src missing in response: ' . $response);
}
// Download the generated audio using the returned audio_src
$audioUrl = $json['audio_src'];
$audioData = file_get_contents($audioUrl);
if ($audioData === false) {
throw new RuntimeException('Failed to download audio from ' . $audioUrl);
}
if (file_put_contents($outputPath, $audioData) === false) {
throw new RuntimeException('Failed to write audio to ' . $outputPath);
}
return [
'message' => isset($json['message']) ? $json['message'] : null,
'audio_src' => $audioUrl,
'output_path' => $outputPath,
];
}
// Example usage:
// $result = woord_tts_en_us_to_file('YOUR_API_KEY', 'Hello World', __DIR__ . '/hello_world_en_us.mp3');
// var_dump($result);
Notes:
- Form-encoding is required; do not send JSON in the POST body.
- Use en_US for language and male for gender_voice per the docs default for this locale.
- The code downloads your own audio_src URL returned by your request (not the fixture shown in the docs).
Optional: Python verification script
If you prefer to validate your token and response in a terminal, this Python snippet mirrors the same form-based POST, reads audio_src, and writes the MP3 to disk. It uses requests and sends application/x-www-form-urlencoded form data.
Python example
import os
import sys
import requests
API_KEY = os.environ.get('WOORD_API_KEY', 'YOUR_API_KEY')
URL = 'https://www.getwoord.com/api/convert'
def synth_en_us(text, out_path):
headers = {
'Accept': 'application/json',
'Authorization': f'Bearer {API_KEY}',
}
data = {
'text': text,
'gender_voice': 'male',
'language': 'en_US',
'speakingRate': '1.00',
}
r = requests.post(URL, headers=headers, data=data, timeout=30)
r.raise_for_status()
payload = r.json()
if payload.get('error') is True:
raise RuntimeError(f"API error: {payload}")
audio_src = payload.get('audio_src')
if not audio_src:
raise RuntimeError(f"Missing audio_src: {payload}")
# Download your generated audio (do not use the fixture URL from docs)
audio = requests.get(audio_src, timeout=60)
audio.raise_for_status()
with open(out_path, 'wb') as f:
f.write(audio.content)
return payload
if __name__ == '__main__':
text = 'Hello World'
out = 'hello_world_en_us.mp3'
resp = synth_en_us(text, out)
print('message:', resp.get('message'))
print('audio_src:', resp.get('audio_src'))
print('error:', resp.get('error'))
print('saved to:', out)
This Python script reads the same three form fields plus the speakingRate shown in the sample, then downloads the returned MP3 to a file.
Response schema and how to use it safely
The convert endpoint returns a small JSON envelope. Here is the official example again (do not use this audio_src directly in your app; it is a docs fixture):
{
"message": "Your audio has been created!",
"audio_src": "https://getwoord.s3.amazonaws.com/4273352455515882618255eaaf3c1cbdbe0.55443890.mp3",
"error": false
}
You will typically:
- Check error == false.
- Read audio_src and either store it as metadata or immediately download.
- Log message to help with debugging or UI display.
For reference during development, here are additional example envelopes with the exact same structure (do not hotlink the fixture URL):
{
"message": "Your audio has been created!",
"audio_src": "https://getwoord.s3.amazonaws.com/4273352455515882618255eaaf3c1cbdbe0.55443890.mp3",
"error": false
}
{
"message": "Your audio has been created!",
"audio_src": "https://getwoord.s3.amazonaws.com/4273352455515882618255eaaf3c1cbdbe0.55443890.mp3",
"error": false
}
{
"message": "Your audio has been created!",
"audio_src": "https://getwoord.s3.amazonaws.com/4273352455515882618255eaaf3c1cbdbe0.55443890.mp3",
"error": false
}
Even though the values match the docs fixture here, in your application logic always use the audio_src returned by your real request.
End-to-end flow in PHP
1) Prepare your inputs
- Text: choose the English (US) content you want read aloud. Start with the sample "Hello World" to validate your pipeline.
- language: en_US.
- gender_voice: male.
- Optional tuning parameter as per sample: speakingRate=1.00.
2) Authenticate
- Add Authorization: Bearer YOUR_API_KEY to headers.
- Keep the token outside source control (e.g., server env var).
3) Send form-encoded POST
- Set Content-Type: application/x-www-form-urlencoded if your HTTP client does not do this automatically.
- Do not send JSON in the POST body; the API consumes form fields.
4) Validate the response
- Ensure a 2xx HTTP status.
- Parse JSON and check error == false.
- Read message for observability and audio_src for the asset URL.
5) Persist or stream audio
- Download audio_src immediately and write to disk for caching, or store the URL if that fits your architecture.
- Do not embed the docs fixture in production; always use your request’s audio_src.
Practical details that save time
- Transport and body:
- POST with application/x-www-form-urlencoded fields. Avoid JSON bodies.
- Include Accept: application/json to receive the envelope.
- Language and voice:
- Use language=en_US for English (US).
- gender_voice=male per docs default for this guide’s locale.
- Content length and encoding:
- URL-encode text properly, especially with spaces and punctuation.
- If your app handles Unicode, ensure PHP uses UTF-8 consistently to avoid mis-encoded characters in text.
- Production handling:
- Cache generated MP3s by a stable key (e.g., SHA-256 of normalized text + voice config) to avoid duplicate synth requests.
- Store audio_src and your local file path together for quick reuse.
- Set conservative timeouts and expose meaningful errors in logs; keep the UI messages generic.
- Environment and secrets:
- Store YOUR_API_KEY in an environment variable or secret manager.
- Never ship the key to front-end clients.
- Free vs. paid:
- Free cannot call convert. Run your integration after upgrading the plan tied to your API key.
Error handling, retries, and observability
The convert API returns a JSON envelope with an error flag. Treat both HTTP errors and API-level error=true as failures. Because the service returns a simple response, your handler can be concise and robust.
- HTTP errors: non-2xx should raise and be logged with response body for diagnosis.
- API-level errors: if error is true, capture the full body string in logs for support tickets.
- Retries: apply cautious retries only for transient network/HTTP failures; do not retry blindly on API-level error=true.
- Timeouts: set both connect and read timeouts; avoid unbounded waits in web handlers.
- Telemetry: log the language, gender_voice, and a content hash of text (not the raw text if it contains PII) to correlate synth requests with audio files.
Testing scenarios specific to English (US)
To validate the integration thoroughly for en_US with gender_voice=male, consider these focused tests:
- Simple phrase: "Hello World" (matches the docs sample; helps confirm parity).
- Numbers and currency: "Your total is 1,249 dollars and 35 cents." Check pronunciation and commas.
- Abbreviations: "The U.S. release is scheduled at 3 PM EST." Ensure periods and capitalization are handled.
- Punctuation pacing: "Wait... are you sure?" Validate pauses and speaking cadence.
- Long-form paragraphs: verify your timeout and download logic with multi-sentence input.
Linking out when you need more depth
If you need extended references or updates on fields and behavior, consult the official Documentation. This guide focuses on the English (US) path with form-encoded POST to the convert endpoint and does not cover other locales.
FAQ
Q1: Can I call the convert endpoint on a free plan?
Free cannot call convert. Register and upgrade before running the examples.
Q2: Should I send JSON or form fields?
Send form fields using application/x-www-form-urlencoded. The body is not JSON.
Q3: What are the required fields for English (US)?
text, gender_voice=male, language=en_US. The sample also shows speakingRate=1.00.
Q4: How do I get the audio file?
Read audio_src from the JSON response and download it with your HTTP client. Do not use the docs fixture URL; use your returned URL.
Q5: Can I change the voice or speed?
Use gender_voice and the speakingRate shown in the sample. For additional options, check the Documentation.
Ready to synthesize English (US) speech from your PHP app? Create your account and get an API key here: Register. Then copy the cURL sample above to verify your token and drop the PHP function into your codebase to start generating MP3s.
