Translations
Manage per-organization language config, translate questions and categories, and read translated content.
Updated 2026-05-20
Every organization has one source language (set once on creation) and zero or more target languages. Translations live alongside the source content, fetched explicitly with an Accept-Language header or appended as part of the resource itself.
Machine translation runs on demand via the AI fallback chain (OpenAI → Anthropic → Google). All translations are editable before publish — the machine pass is a starting point, not a final answer.
Language config
Read configured languages
curl https://api.thefaq.app/api/v1/acme/languages \
-H "Authorization: Bearer $FAQAPP_API_KEY"
Response:
{
"data": {
"source": "en",
"targets": ["es", "de", "fr"],
"available": ["af", "ar", "az", "…and ~95 more"]
}
}
Configure target languages
Target languages are configured in the dashboard at Settings → Languages. Pick from the ~95 supported BCP-47 codes; add or remove anytime. Removing a language does not delete its translations; they’re soft-archived and restored if you re-add the language later.
Question translations
Read all translations for a question
curl https://api.thefaq.app/api/v1/acme/questions/how-do-i-cancel/translations \
-H "Authorization: Bearer $FAQAPP_API_KEY"
Response:
{
"data": [
{
"language": "es",
"title": "¿Cómo cancelo mi suscripción?",
"answer": "Abre Ajustes → Facturación → Cancelar suscripción...",
"status": "published",
"updatedAt": "2026-05-19T10:00:00Z"
}
]
}
Create or update a translation
curl -X POST https://api.thefaq.app/api/v1/acme/questions/how-do-i-cancel/translations \
-H "Authorization: Bearer $FAQAPP_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"language": "es",
"title": "¿Cómo cancelo mi suscripción?",
"answer": "Abre Ajustes → Facturación → Cancelar suscripción..."
}'
POST is idempotent per (question, language) — calling it twice with different content updates the existing translation in place.
Patch (partial update)
curl -X PATCH https://api.thefaq.app/api/v1/acme/questions/how-do-i-cancel/translations/es \
-H "Authorization: Bearer $FAQAPP_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "answer": "Updated Spanish answer." }'
Delete
curl -X DELETE https://api.thefaq.app/api/v1/acme/questions/how-do-i-cancel/translations/es \
-H "Authorization: Bearer $FAQAPP_API_KEY"
Returns 204 No Content.
Required scope (create/update/delete): write.
Machine-translate
curl -X POST https://api.thefaq.app/api/v1/acme/questions/how-do-i-cancel/translations/ai \
-H "Authorization: Bearer $FAQAPP_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "languages": ["es", "de", "fr"] }'
Runs all requested target languages in parallel. Returns the generated translations as status: draft so you can review before publishing. Re-running overwrites existing drafts; published translations are never touched.
Required scope: write.
Category translations
Same surface, scoped per category:
curl https://api.thefaq.app/api/v1/acme/categories/billing/translations \
-H "Authorization: Bearer $FAQAPP_API_KEY"
Create + AI-translate via:
curl -X POST https://api.thefaq.app/api/v1/acme/categories/billing/translations \
-H "Authorization: Bearer $FAQAPP_API_KEY" \
-d '{ "language": "es", "name": "Facturación", "description": "..." }'
curl -X POST https://api.thefaq.app/api/v1/acme/categories/billing/translations/ai \
-H "Authorization: Bearer $FAQAPP_API_KEY" \
-d '{ "languages": ["es", "de"] }'
Reading translated content inline
To get a question or category in a specific language without a separate fetch, include Accept-Language:
curl https://api.thefaq.app/api/v1/acme/questions/how-do-i-cancel \
-H "Authorization: Bearer $FAQAPP_API_KEY" \
-H "Accept-Language: es"
The response replaces title + answer with the Spanish translation if one exists and is published, otherwise falls back to source. The x-faq-language-served response header tells you which language was actually returned.
Error codes
language_not_configured(400): target language not in your org’stargetslisttranslation_not_found(404): no translation exists for(question, language)validation_failed(400): missing required fieldai_translation_failed(502): all AI providers erroredplan_limit_reached(402): translation features not available on Free plan