Request and Retrieve Translations via the API

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.

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

ParameterTypeRequiredDescription
dataobjectYesThe JSON-structured data to translate. It can include nested objects, arrays, and string values.
namestringNoA human-readable name for the translation job. If omitted, one is generated automatically.
callback_urlstringNoThe URL that receives webhook notifications when the translation is complete.
target_languagesarray[string]NoThe 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

FieldTypeDescription
idnumberThe unique identifier of the content translation job.
namestringThe job name (auto-generated if not provided).
statusstringThe current job status (queued, processing, completed).
created_atstringThe ISO 8601 timestamp indicating when the job was created.
updated_atstringThe 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 translated
  • user.settings.theme: “Choose Theme” → Gets translated
  • user.settings.count: 5 → Remains unchanged
  • user.settings.enabled: true → Remains unchanged

Translation Workflow

  1. Validation: JSON structure and target languages are checked
  2. Source file preparation: JSON is converted to an internal source format
  3. String reuse through translation memory: All translatable strings are extracted and stored in your project’s translation memory so previous translations can be reused
  4. Job queuing: A job is queued for each target language
  5. Processing: Automatic translation runs on the extracted strings
  6. 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 TypeTranslation Behavior
stringTranslated to target languages
numberPreserved as-is
booleanPreserved as-is
nullPreserved as-is
arrayProcessed recursively
objectProcessed 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

ParameterTypeRequiredDescription
idintegerYesThe 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

FieldTypeDescription
sourceobjectThe original source content in the same nested structure as submitted.
{language_code}objectThe 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

ParameterTypeRequiredDescription
idintegerYesThe 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
FieldTypeDescription
statusstringThe current translation status. Possible status values include: queued, in_progress, completed, failed, status_unknown.
completenessnumberThe percentage of translated strings (0–100). Calculated as (completed_translatable_strings / total_translatable_strings) × 100.
Status Values
StatusDescription
queuedThe translation has been queued and is waiting to be processed.
in_progressThe translation is currently being processed.
completedThe translation has been completed successfully.
failedThe translation has failed due to an error.
status_unknownThe 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
}

Scroll to Top