Translations
Manage per-organization language config, translate questions and categories, and read translated content.
Updated 2026-05-20
Every organization has one default language and zero or more extra languages. Each translation is its own record, read and written through the endpoints below.
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": {
"defaultLanguage": "en",
"languages": ["en", "es", "de", "fr"]
}
}
languages always includes defaultLanguage.
Configure target languages
Pick languages in the dashboard under Settings, then Languages, or call PATCH /languages with a key that has the admin scope:
curl -X PATCH https://api.thefaq.app/api/v1/acme/languages \
-H "Authorization: Bearer $FAQAPP_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "defaultLanguage": "en", "languages": ["es", "de", "fr"] }'
Removing a language does not delete its translations.
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": [
{
"id": "qtr_8f2c",
"language": "es",
"question": "¿Cómo cancelo mi suscripción?",
"answer": "Abre Ajustes, luego Facturación, luego Cancelar suscripción.",
"slug": "como-cancelo-mi-suscripcion",
"seoTitle": null,
"seoDescription": null,
"aiTranslated": false,
"publishedAt": "2026-05-19T10:00:00Z",
"createdAt": "2026-05-18T09:00:00Z",
"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/es \
-H "Authorization: Bearer $FAQAPP_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"question": "¿Cómo cancelo mi suscripción?",
"answer": "Abre Ajustes, luego Facturación, luego Cancelar suscripción."
}'
POST is idempotent per question and 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-translate \
-H "Authorization: Bearer $FAQAPP_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "language": "es" }'
Translates into one language per call. sourceLanguage is optional and defaults to en. The result is saved as an unpublished draft (publishedAt: null) so you can review it before publishing with POST /translations/:id/publish. List pending drafts with GET /translations/drafts.
Required scope: write. Plan: Pro or Enterprise; lower plans get 403 plan_required.
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 or update one language, or machine-translate:
curl -X POST https://api.thefaq.app/api/v1/acme/categories/billing/translations/es \
-H "Authorization: Bearer $FAQAPP_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "name": "Facturación", "description": "Pagos, facturas y reembolsos" }'
curl -X POST https://api.thefaq.app/api/v1/acme/categories/billing/translations/ai-translate \
-H "Authorization: Bearer $FAQAPP_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "language": "de" }'
Reading translated content
Read translations from the translations endpoints above. Question and category reads always return the default language.
Error codes
validation_error(400): missing or invalid field, or an invalid language codeinvalid_json(400): body wasn’t valid JSONnot_found(404): the question, category, or translation doesn’t exist in this orgconflict(409): the translation is already publishedplan_required(403): machine translation needs Pro or Enterpriseai_unavailable(503): every AI provider failed; safe to retry