Skip to content
thefaqappthefaqapp
Browse docs

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 code
  • invalid_json (400): body wasn’t valid JSON
  • not_found (404): the question, category, or translation doesn’t exist in this org
  • conflict (409): the translation is already published
  • plan_required (403): machine translation needs Pro or Enterprise
  • ai_unavailable (503): every AI provider failed; safe to retry