Use this API to send content for translation, track its progress, and retrieve the translations in all target languages.
This API accepts JSON-structured content, preserving the original structure and keys. It translates only text values, leaving numbers, booleans, nulls, and other non-text values unchanged.
API Quick Links
Create Content Translations
Creates a new translation job from JSON-structured data.
The endpoint preserves your content’s original hierarchy of keys and arrays, translating only text values while leaving numbers, booleans, nulls, and other non-text values unchanged.
It is especially useful for:
- Content management – Localizing dynamic content structured in JSON
- Configuration files – Translating user-facing strings in config data
- API responses – Translating structured response payloads
- Documentation – Localizing hierarchical help content or guides
HTTP Request
POST https://app.ptc.wpml.org/api/v1/content_translation
Parameters
Parameter | Type | Required | Description |
---|---|---|---|
data | object | Yes | The JSON-structured data to translate. It can include nested objects, arrays, and string values. |
name | string | No | A human-readable name for the translation job. If omitted, one is generated automatically. |
callback_url | string | No | The URL that receives webhook notifications when the translation is complete. |
target_languages | array[string] | No | The array of ISO codes for target languages. If omitted, translations are created for all project-configured languages. See the Available Target Languages API for more information. |
Request Body Example
{
"data": {
"app": {
"title": "My Application",
"navigation": {
"home": "Home",
"about": "About Us",
"contact": "Contact"
},
"buttons": {
"save": "Save",
"cancel": "Cancel",
"submit": "Submit"
},
"messages": {
"welcome": "Welcome to our platform",
"error": "An error occurred"
}
},
"version": "1.0.0",
"settings": {
"theme": "dark",
"notifications": true
}
},
"name": "App UI Translations",
"callback_url": "https://your-app.com/webhooks/translation-complete",
"target_languages": ["es", "fr", "de"]
}
Responses
Success Response
- Code:
201 Created
- Content Type:
application/json
{
"id": 123,
"name": "App UI Translations",
"status": "queued",
"created_at": "2024-01-15T10:30:00.000Z",
"updated_at": "2024-01-15T10:30:00.000Z"
}
Response Schema
Field | Type | Description |
---|---|---|
id | number | The unique identifier of the content translation job. |
name | string | The job name (auto-generated if not provided). |
status | string | The current job status (queued , processing , completed ). |
created_at | string | The ISO 8601 timestamp indicating when the job was created. |
updated_at | string | The ISO 8601 timestamp indicating when the job was last updated. |
Error Responses
Invalid JSON Data
- Code:
422 Unprocessable Entity
{
"errors": {
"data": ["Data must be a valid JSON object"]
}
}
Invalid Target Languages
- Code:
422 Unprocessable Entity
{
"errors": {
"target_languages": ["Language codes [zh, xx] are not configured for this project"]
}
}
Unauthorized
- Code:
401 Unauthorized
{
"error": "Unauthorized access. Please provide a valid API token."
}
Forbidden
- Code:
403 Forbidden
{
"error": "Access denied. Insufficient permissions."
}
JSON Data Processing
When working with JSON-structured data, PTC processes the data as follows:
- Structure is preserved – The original hierarchy of keys and nesting remains unchanged
- Only strings are translated – Numbers, booleans, arrays, and null values are kept as they are
- Path-based translation – Each translatable string is identified by its JSON path
- Supports nesting – Works with deeply nested objects and arrays
- Handles mixed data types – Non-string values are preserved without modification
Example Data Transformation
Input:
{
"user": {
"name": "Welcome User",
"settings": {
"theme": "Choose Theme",
"count": 5,
"enabled": true
}
}
}
Processing outcome:
user.name
: “Welcome User” → Gets translateduser.settings.theme
: “Choose Theme” → Gets translateduser.settings.count:
5 → Remains unchangeduser.settings.enabled:
true → Remains unchanged
Translation Workflow
- Validation: JSON structure and target languages are checked
- Source file preparation: JSON is converted to an internal source format
- String reuse through translation memory: All translatable strings are extracted and stored in your project’s translation memory so previous translations can be reused
- Job queuing: A job is queued for each target language
- Processing: Automatic translation runs on the extracted strings
- Callback (optional): A webhook is sent when all translations are completed, if
callback_url
is provided
Webhook Callback
When a callback_url
is provided, a POST
request is sent when the job is completed.
Callback request body:
{
"id": 1,
"status": "completed",
"translations_url": "https://app.ptc.wpml.org/api/v1/content_translation/1"
}
Supported Data Types
JSON Type | Translation Behavior |
---|---|
string | Translated to target languages |
number | Preserved as-is |
boolean | Preserved as-is |
null | Preserved as-is |
array | Processed recursively |
object | Processed recursively |
Example Requests
Basic JSON translation:
curl -X POST "https://app.ptc.wpml.org/api/v1/content_translation" \
-H "Content-Type: application/json" \
-d '{
"data": {
"welcome": "Welcome",
"buttons": {
"save": "Save",
"cancel": "Cancel"
}
},
"name": "UI Labels"
}'
With specific target languages:
curl -X POST "https://app.ptc.wpml.org/api/v1/content_translation" \
-H "Content-Type: application/json" \
-d '{
"data": {
"title": "Product Catalog",
"categories": {
"electronics": "Electronics",
"clothing": "Clothing"
}
},
"target_languages": ["es", "fr"],
"callback_url": "https://myapp.com/webhook"
}'
Code Examples
const translationData = {
data: {
app: {
title: "My Application",
navigation: {
home: "Home",
about: "About Us"
}
}
},
name: "App Translations",
target_languages: ["es", "fr", "de"],
callback_url: "https://your-app.com/webhooks/complete"
};
const response = await fetch('https://app.ptc.wpml.org/api/v1/content_translation', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(translationData)
});
const result = await response.json();
console.log('Translation job created:', result);
// Store the ID for later retrieval
const translationId = result.id;
import requests
translation_data = {
"data": {
"app": {
"title": "My Application",
"navigation": {
"home": "Home",
"about": "About Us"
}
}
},
"name": "App Translations",
"target_languages": ["es", "fr", "de"],
"callback_url": "https://your-app.com/webhooks/complete"
}
headers = {
'Content-Type': 'application/json'
}
response = requests.post('https://app.ptc.wpml.org/api/v1/content_translation',
headers=headers, json=translation_data)
result = response.json()
print(f"Translation job created with ID: {result['id']}")
print(f"Status: {result['status']}")
<?php
$translationData = [
'data' => [
'app' => [
'title' => 'My Application',
'navigation' => [
'home' => 'Home',
'about' => 'About Us'
]
]
],
'name' => 'App Translations',
'target_languages' => ['es', 'fr', 'de'],
'callback_url' => 'https://your-app.com/webhooks/complete'
];
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => 'https://app.ptc.wpml.org/api/v1/content_translation',
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => json_encode($translationData),
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
'Content-Type: application/json'
],
]);
$response = curl_exec($curl);
curl_close($curl);
$result = json_decode($response, true);
echo "Translation job created with ID: " . $result['id'];
?>
const axios = require('axios');
const translationData = {
data: {
app: {
title: "My Application",
navigation: {
home: "Home",
about: "About Us"
}
}
},
name: "App Translations",
target_languages: ["es", "fr", "de"],
callback_url: "https://your-app.com/webhooks/complete"
};
const response = await axios.post('https://app.ptc.wpml.org/api/v1/content_translation', translationData, {
headers: {
'Content-Type': 'application/json'
}
});
console.log('Translation job created:', response.data);
// Monitor status
const checkStatus = async (id) => {
const statusResponse = await axios.get(`https://app.ptc.wpml.org/api/v1/content_translation/${id}/status`);
return statusResponse.data.status;
};
Get Content Translations
Retrieves the original content and all translated versions for a specific content translation job.
The response preserves your input structure: it returns a source object plus one object per target language (keyed by language code such as es
, fr
, de
).
HTTP Request
GET https://app.ptc.wpml.org/api/v1/content_translation/{id}
Path Parameters
Parameter | Type | Required | Description |
---|---|---|---|
id | integer | Yes | The unique identifier of the content translation job to retrieve. |
Responses
Success Response
- Code:
200 OK
- Content Type:
application/json
{
"source": {
"app": {
"title": "My Application",
"navigation": {
"home": "Home",
"about": "About",
"contact": "Contact"
},
"buttons": {
"save": "Save",
"cancel": "Cancel"
}
}
},
"es": {
"app": {
"title": "Mi Aplicación",
"navigation": {
"home": "Inicio",
"about": "Acerca de",
"contact": "Contacto"
},
"buttons": {
"save": "Guardar",
"cancel": "Cancelar"
}
}
},
"fr": {
"app": {
"title": "Mon Application",
"navigation": {
"home": "Accueil",
"about": "À propos",
"contact": "Contact"
},
"buttons": {
"save": "Enregistrer",
"cancel": "Annuler"
}
}
}
}
Response Schema
Field | Type | Description |
---|---|---|
source | object | The original source content in the same nested structure as submitted. |
{language_code} | object | The translated content for each target language, keyed by its ISO code (for example es , fr , de ), with the same structure as source.For more information, see the Available Target Languages API. |
Error Responses
Content Translation Not Found
- Code:
404 Not Found
{
"error": "Content translation not found"
}
Unauthorized
- Code:
401 Unauthorized
{
"error": "Unauthorized access. Please provide a valid API token."
}
Forbidden
- Code:
403 Forbidden
{
"error": "Access denied. Insufficient permissions."
}
Example Requests
Basic request:
curl -X GET "https://app.ptc.wpml.org/api/v1/content_translation/123" \
-H "Content-Type: application/json"
Code Examples
const contentTranslationId = 123;
const response = await fetch(`https://app.ptc.wpml.org/api/v1/content_translation/${contentTranslationId}`, {
method: 'GET',
headers: {
'Content-Type': 'application/json'
}
});
const data = await response.json();
// Access source content
console.log('Source title:', data.source.app.title);
// Access translated content
console.log('Spanish title:', data.es.app.title);
console.log('French title:', data.fr.app.title);
// Iterate through all languages
Object.keys(data).forEach(langCode => {
if (langCode !== 'source') {
console.log(`${langCode} translation:`, data[langCode]);
}
});
import requests
content_translation_id = 123
headers = {
'Content-Type': 'application/json'
}
response = requests.get(f'https://app.ptc.wpml.org/api/v1/content_translation/{content_translation_id}',
headers=headers)
data = response.json()
# Access source content
source_data = data['source']
print("Source content:", source_data)
# Access translations
for lang_code, translation in data.items():
if lang_code != 'source':
print(f"{lang_code.upper()} translation:", translation)
<?php
$content_translation_id = 123;
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://app.ptc.wpml.org/api/v1/content_translation/{$content_translation_id}",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
'Content-Type: application/json'
],
]);
$response = curl_exec($curl);
curl_close($curl);
$data = json_decode($response, true);
// Access source content
$sourceData = $data['source'];
echo "Source content: " . json_encode($sourceData, JSON_PRETTY_PRINT) . "\n";
// Access translations
foreach ($data as $langCode => $translation) {
if ($langCode !== 'source') {
echo strtoupper($langCode) . " translation: " . json_encode($translation, JSON_PRETTY_PRINT) . "\n";
}
}
?>
const axios = require('axios');
const contentTranslationId = 123;
const response = await axios.get(`https://app.ptc.wpml.org/api/v1/content_translation/${contentTranslationId}`, {
headers: {
'Content-Type': 'application/json'
}
});
const data = response.data;
// Function to traverse nested objects
function extractStrings(obj, path = '') {
const strings = [];
for (const [key, value] of Object.entries(obj)) {
const currentPath = path ? `${path}.${key}` : key;
if (typeof value === 'string') {
strings.push({ path: currentPath, value });
} else if (typeof value === 'object') {
strings.push(...extractStrings(value, currentPath));
}
}
return strings;
}
// Extract all translatable strings
const sourceStrings = extractStrings(data.source);
console.log('Source strings:', sourceStrings);
// Compare with translations
Object.keys(data).forEach(langCode => {
if (langCode !== 'source') {
const translatedStrings = extractStrings(data[langCode]);
console.log(`${langCode} strings:`, translatedStrings);
}
});
Get the Content Translation Status
Retrieves the current status of a specific content translation job.
The response reflects the overall progress and includes whether the translation is queued, in progress, completed, or has failed.
HTTP Request
GET https://app.ptc.wpml.org/api/v1/content_translation/{id}/status
Path Parameters
Parameter | Type | Required | Description |
---|---|---|---|
id | integer | Yes | The unique identifier of the content translation job to check. |
Responses
Success Response
- Code:
200 OK
- Content Type:
application/json
{
"status": "completed",
"completeness": 100
}
Response Schema
Field | Type | Description |
---|---|---|
status | string | The current translation status. Possible status values include: queued , in_progress , completed , failed , status_unknown . |
completeness | number | The percentage of translated strings (0–100). Calculated as (completed_translatable_strings / total_translatable_strings) × 100 . |
Status Values
Status | Description |
---|---|
queued | The translation has been queued and is waiting to be processed. |
in_progress | The translation is currently being processed. |
completed | The translation has been completed successfully. |
failed | The translation has failed due to an error. |
status_unknown | The translation status is unknown or cannot yet be determined. |
Error Responses
- Code:
404 Not Found
Possible causes:
- No content translation exists with the specified ID
- The translation job does not belong to the authenticated project
Example
curl -X GET "https://app.ptc.wpml.org/api/v1/content_translation/123/status" \
-H "Authorization: Bearer your-api-token"
Response:
{
"status": "completed",
"completeness": 100
}
GET https://app.ptc.wpml.org/api/v1/content_translation/{id}/status
{
"status": "in_progress",
"completeness": 70
}
curl -X GET "https://app.ptc.wpml.org/api/v1/content_translation/123/status" \
-H "Authorization: Bearer your-api-token"
{
"status": "completed",
"completeness": 100
}