Portuguese (Portugal) Text-to-Speech API in PHP
You need to turn Portuguese (Portugal) text into speech from a PHP backend. By the end of this guide you will be able to POST text to Woord’s Text-to-Speech endpoint, authenticate with a Bearer token, and programmatically retrieve an MP3 URL for playback or storage—using curl, PHP, and JavaScript.
What you will build
This tutorial shows how to call the Woord Text-to-Speech convert endpoint for Portuguese (Portugal) using PHP. You will send form-encoded fields (not JSON), authorize with a Bearer token, and parse the JSON envelope to extract the audio URL. Examples include:
- A copy-pasteable curl request
- A PHP example (curl_init)
- A JavaScript example (fetch with URL-encoded form data)
- The official JSON response envelope and how to use it safely in production
Prerequisites
Before you start:
- A Woord account and API key. If you do not have one, create it here: Register.
- Familiarity with PHP basics (cURL extension enabled) and JSON decoding.
- Network access from your server to call Woord’s API domain.
Important: Free plans cannot call the convert endpoint. You will need a paid tier before convert succeeds.
Endpoint and parameters
Woord’s Text-to-Speech convert endpoint for creating audio is:
POST https://www.getwoord.com/api/convert
Authentication is via the Authorization header using a Bearer token. The request body must be sent as form fields (not JSON). For Portuguese (Portugal), use the following fields:
- text: The content you want to synthesize. Example: Hello World
- gender_voice: The voice gender. Default per docs: male
- language: The locale string. Use pt_PT for Portuguese (Portugal)
The official curl example (below) includes an additional field speakingRate=1.00 to demonstrate adjusting pace. Body semantics are form-encoded; do not send a JSON payload to this endpoint.
Authentication
Include your API key in the Authorization header:
Authorization: Bearer YOUR_API_KEY
Replace YOUR_API_KEY with your Woord key. Do not embed keys in client-side code for production web apps—proxy through your server and store the key securely.
Portuguese (Portugal) constants you will use
- Language: Portuguese (Portugal)
- language=pt_PT
- gender_voice=male
- Sample text from docs for this locale: Hello World
Send your first request
The convert endpoint returns a JSON envelope with an audio URL when successful. The following examples all target the same Woord endpoint using the required Portuguese (Portugal) fields.
Code: curl (form fields with Bearer)
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=pt_PT&speakingRate=1.00"
Code: PHP (curl_init)
<?php
$ch = curl_init("https://www.getwoord.com/api/convert");
$postFields = http_build_query([
"text" => "Hello World",
"gender_voice" => "male",
"language" => "pt_PT",
"speakingRate" => "1.00"
]);
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
"Accept: application/json",
"Authorization: Bearer YOUR_API_KEY",
"Content-Type: application/x-www-form-urlencoded"
],
CURLOPT_POSTFIELDS => $postFields,
CURLOPT_TIMEOUT => 30
]);
$response = curl_exec($ch);
if ($response === false) {
http_response_code(500);
echo "HTTP request failed: " . curl_error($ch);
curl_close($ch);
exit;
}
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
// Parse the JSON envelope
$data = json_decode($response, true);
if ($httpCode !== 200 || !is_array($data)) {
http_response_code(500);
echo "Unexpected response: " . $response;
exit;
}
// Validate the official fields you will use
if (isset($data["error"]) && $data["error"] === false && !empty($data["audio_src"])) {
// Save or stream the MP3 URL
$audioUrl = $data["audio_src"];
echo "Audio ready: " . htmlspecialchars($audioUrl, ENT_QUOTES);
} else {
echo "Conversion not successful. Full payload: " . htmlspecialchars($response, ENT_QUOTES);
}
Code: JavaScript (fetch with URL-encoded form data)
async function convertPtPt() {
const body = new URLSearchParams({
text: "Hello World",
gender_voice: "male",
language: "pt_PT",
speakingRate: "1.00"
});
const res = await fetch("https://www.getwoord.com/api/convert", {
method: "POST",
headers: {
"Accept": "application/json",
"Authorization": "Bearer YOUR_API_KEY",
"Content-Type": "application/x-www-form-urlencoded"
},
body
});
if (!res.ok) {
const text = await res.text();
throw new Error("HTTP " + res.status + ": " + text);
}
const data = await res.json();
if (data && data.error === false && data.audio_src) {
// Use data.audio_src (MP3)
console.log("Audio URL:", data.audio_src);
return data.audio_src;
} else {
throw new Error("Conversion failed: " + JSON.stringify(data));
}
}
convertPtPt().catch(console.error);
The official JSON response envelope
On success, Woord returns a compact JSON envelope. Here is the official example from the documentation. Values are illustrative; your audio_src will be a different, unique key.
Official convert envelope
{"message":"Your audio has been created!","audio_src":"https://getwoord.s3.amazonaws.com/4273352455515882618255eaaf3c1cbdbe0.55443890.mp3","error":false}
Field usage:
- message: Human-readable status.
- audio_src: HTTPS URL to the generated MP3 file. Do not hotlink this sample URL; your request will return a different URL.
- error: Boolean flag. false indicates success.
Portuguese (Portugal) settings you should keep consistent
To synthesize in Portuguese (Portugal), always pass language=pt_PT. The default documented gender is gender_voice=male. The sample text used in this guide and in the docs fixture is “Hello World”. If you need to adjust pacing, you can add speakingRate=1.00 as shown in the curl example.
Parsing and storing the MP3 URL
Once you receive audio_src, you can:
- Stream it directly to a media player on the client.
- Download it server-side and cache it. For example, use file_get_contents in PHP to retrieve the binary and save as .mp3.
- Store the URL in your database for later playback.
Because audio_src points to a generated asset, treat it as the canonical location for your TTS output. If you plan to serve many requests for the same text and settings, consider caching to reduce repeated conversions.
Error handling, retries, and timeouts
Handle transport errors (non-200 HTTP codes, timeouts) and application errors (error=true in the JSON payload). Use server-side timeouts (e.g., 30 seconds in PHP cURL) to avoid hanging processes. If a conversion fails with a transient network issue, implement a short retry with exponential backoff. For persistent errors, log the body for inspection.
Validation checklist for production
- Ensure you are sending form-encoded fields (Content-Type: application/x-www-form-urlencoded). Do not send JSON in the request body.
- Pass the correct locale: language=pt_PT for Portuguese (Portugal).
- Provide gender_voice=male if you expect the documented default voice profile.
- Escape or validate the text field on your server to avoid injection issues in logs or UIs.
- Log the message, error, and audio_src. Only audio_src is required to play audio.
Testing without billing
The convert endpoint cannot be called on the free plan. If you are still prototyping without billing enabled, you can build and unit-test your HTTP client with mocked responses matching the official envelope above, then switch to a paid plan to verify live conversions.
Operational tips
- Idempotency: If your application may retry the same text with the same settings, you can de-duplicate work by caching audio_src keyed by a hash of text + language + gender_voice (+ speakingRate if used).
- Security: Keep YOUR_API_KEY on the server side only. Never expose it in client-side JavaScript in production.
- Latency: Convert once, then serve the MP3 from your own CDN if your traffic pattern is heavy.
- Monitoring: Track non-200 responses and any cases where error !== false to catch integration drift early.
Full PHP example with download (optional)
This extension demonstrates downloading the MP3 to local storage after a successful convert call.
Code: PHP (convert, then download MP3)
<?php
function woord_convert_ptpt($apiKey, $text) {
$ch = curl_init("https://www.getwoord.com/api/convert");
$postFields = http_build_query([
"text" => $text,
"gender_voice" => "male",
"language" => "pt_PT",
"speakingRate" => "1.00"
]);
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
]);
$resp = curl_exec($ch);
if ($resp === false) {
throw new RuntimeException("HTTP: " . curl_error($ch));
}
$code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
if ($code !== 200) {
throw new RuntimeException("HTTP $code: $resp");
}
$data = json_decode($resp, true);
if (!is_array($data) || !isset($data["error"]) || $data["error"] !== false || empty($data["audio_src"])) {
throw new RuntimeException("Unexpected payload: " . $resp);
}
return $data["audio_src"];
}
function download_mp3($url, $path) {
$ctx = stream_context_create(["http" => ["timeout" => 30]]);
$binary = @file_get_contents($url, false, $ctx);
if ($binary === false) {
throw new RuntimeException("Failed to download audio");
}
if (file_put_contents($path, $binary) === false) {
throw new RuntimeException("Failed to write file");
}
return $path;
}
try {
$audioUrl = woord_convert_ptpt("YOUR_API_KEY", "Hello World");
$saved = download_mp3($audioUrl, __DIR__ . "/hello-pt_PT.mp3");
echo "Saved: " . $saved . PHP_EOL;
} catch (Throwable $e) {
echo "Error: " . $e->getMessage() . PHP_EOL;
}
Troubleshooting
- 401 or 403 errors: Verify the Authorization header uses Bearer and that the key is valid and active. Confirm your plan can call convert.
- Non-JSON responses: Check Content-Type in the request is application/x-www-form-urlencoded and Accept is application/json.
- Empty audio_src: Re-check the required fields text, gender_voice, and language=pt_PT.
- Playback issues: Confirm your client supports MP3. If streaming on the web, set correct MIME type (audio/mpeg).
Reference
See the API reference for additional details and any evolving parameters here: Documentation.
FAQ
Can I call the convert endpoint on a free plan?
No. Free cannot call convert. Upgrade your plan to run live conversions.
Do I send a JSON body to /api/convert?
No. The body must be form fields (application/x-www-form-urlencoded). Send text, gender_voice, and language=pt_PT.
What format is the returned audio?
The audio_src points to an MP3 file (as shown by the .mp3 extension in the example envelope).
Will my audio_src match the docs sample?
No. The S3 filename in the docs is a fixture. Your request will return a new, unique audio_src URL. Do not hotlink the docs URL.
How do I change voice speed?
The curl example includes speakingRate=1.00. If you use it, include it as a form field along with text, gender_voice, and language.
Get your key and build
Create your account and retrieve your API key, then copy the curl or PHP example above and synthesize Portuguese (Portugal) audio in minutes. Start here: Register.
