Overview

The Translations API provides programmatic control over AI-powered documentation translations. Configure target languages, trigger translation jobs, manage glossary terms for domain-specific terminology, and track translation status across your documentation.

Base path: https://api.holydocs.com/api/v1/projects/:projectId

All translation endpoints require authentication. Language management and triggering translations both require the projects:write scope.

HolyDocs translations are AI-powered, not machine-translated. Each page is translated by an LLM that understands context, preserves MDX component structure, and respects your glossary for consistent terminology. Code blocks, component props, and URLs are preserved untranslated.

Supported Languages

HolyDocs supports 24 languages for AI-powered translation:

European

English (en), French (fr), German (de), Spanish (es), Portuguese (pt), Italian (it), Dutch (nl), Polish (pl), Swedish (sv), Norwegian (no), Danish (da), Finnish (fi)

Asian

Chinese Simplified (zh-CN), Chinese Traditional (zh-TW), Japanese (ja), Korean (ko), Thai (th), Vietnamese (vi), Indonesian (id), Malay (ms)

Other

Arabic (ar), Hebrew (he), Turkish (tr), Ukrainian (uk)

The source language for your documentation is auto-detected from your content. You do not need to specify it explicitly. English is the default source language.

List Languages

Retrieve the configured target languages for a project.

bash
GET /api/v1/projects/:projectId/languages

bash
curl "https://api.holydocs.com/api/v1/projects/$PROJECT_ID/languages" \ -H "Authorization: Bearer $HOLYDOCS_API_KEY"

Response

json
{ "data": { "sourceLanguage": "en", "targetLanguages": [ { "code": "ja", "name": "Japanese", "translatedPages": 38, "totalPages": 42, "completionRate": 0.90, "lastTranslatedAt": "2026-04-10T08:30:00Z" }, { "code": "de", "name": "German", "translatedPages": 42, "totalPages": 42, "completionRate": 1.0, "lastTranslatedAt": "2026-04-11T02:15:00Z" }, { "code": "zh-CN", "name": "Chinese Simplified", "translatedPages": 20, "totalPages": 42, "completionRate": 0.48, "lastTranslatedAt": "2026-04-08T14:00:00Z" } ] }}
bash
curl "https://api.holydocs.com/api/v1/projects/proj_abc123/languages" \ -H "Authorization: Bearer hd_a1b2c3d4e5f67890a1b2c3d4e5f67890"

Add Language

Add a new target language to the project. This does not trigger translation -- it configures the language as a translation target.

bash
POST /api/v1/projects/:projectId/languages

Request Body

json
{ "code": "fr", "autoTranslate": true}
FieldTypeRequiredDescription
codestringYesISO 639-1 language code from the supported languages list
autoTranslatebooleanNoAutomatically translate new and updated pages (default: false)

Response

json
{ "data": { "code": "fr", "name": "French", "autoTranslate": true, "translatedPages": 0, "totalPages": 42, "completionRate": 0.0, "createdAt": "2026-04-11T10:00:00Z" }}

Enable autoTranslate to keep translations up-to-date automatically. When a source page is updated and redeployed, the translation for that page is automatically re-queued. This is the recommended setting for actively maintained documentation.

Remove Language

Remove a language and all its translations from the project.

bash
DELETE /api/v1/projects/:projectId/languages/:code

Path Parameters

ParameterTypeDescription
projectIdstringProject ID
codestringLanguage code to remove (e.g., fr)

Response

json
{ "data": { "deleted": true, "code": "fr", "pagesDeleted": 42 }}

This permanently deletes all translations for the removed language. The source content is not affected. This action cannot be undone.

Trigger Translation

Start a translation job for a specific page or all pages in a language.

bash
POST /api/v1/projects/:projectId/translate

Request Body

json
{ "language": "ja", "scope": "all"}
FieldTypeRequiredDescription
languagestringYesTarget language code
scopeall | page | staleNoWhat to translate (default: all)
pagePathstringConditionalRequired when scope is page
forcebooleanNoRetranslate even if a current translation exists (default: false)

Response

json
{ "data": { "jobId": "tr_abc123", "language": "ja", "scope": "all", "pagesQueued": 42, "estimatedDuration": 180, "status": "queued", "createdAt": "2026-04-11T10:00:00Z" }}
bash
curl -X POST "https://api.holydocs.com/api/v1/projects/proj_abc123/translate" \ -H "Authorization: Bearer hd_a1b2c3d4e5f67890a1b2c3d4e5f67890" \ -H "Content-Type: application/json" \ -d '{ "language": "ja", "scope": "all" }'

Translation Scopes

ScopeBehavior
allTranslate every page, skipping pages with up-to-date translations (unless force: true)
pageTranslate a single page specified by pagePath
staleOnly translate pages where the source content has changed since the last translation

List Translations

Retrieve translation status for all pages in a specific language.

bash
GET /api/v1/projects/:projectId/translations

Query Parameters

ParameterTypeRequiredDescription
languagestringYesTarget language code
statuscompleted | pending | failed | staleNoFilter by translation status
pagenumberNoPage number (default: 1)
perPagenumberNoResults per page (default: 50, max: 200)

Response

json
{ "data": [ { "pagePath": "/quickstart", "pageTitle": "Quickstart Guide", "language": "ja", "status": "completed", "translatedTitle": "\u30af\u30a4\u30c3\u30af\u30b9\u30bf\u30fc\u30c8\u30ac\u30a4\u30c9", "sourceHash": "a1b2c3d4", "translatedHash": "e5f6g7h8", "wordCount": 1240, "translatedAt": "2026-04-10T08:30:00Z", "sourceUpdatedAt": "2026-04-09T12:00:00Z" }, { "pagePath": "/api/authentication", "pageTitle": "API Authentication", "language": "ja", "status": "stale", "translatedTitle": "API\u8a8d\u8a3c", "sourceHash": "i9j0k1l2", "translatedHash": "m3n4o5p6", "wordCount": 890, "translatedAt": "2026-04-05T06:00:00Z", "sourceUpdatedAt": "2026-04-08T14:00:00Z" }, { "pagePath": "/webhooks", "pageTitle": "Webhooks", "language": "ja", "status": "pending", "translatedTitle": null, "sourceHash": "q7r8s9t0", "translatedHash": null, "wordCount": 1560, "translatedAt": null, "sourceUpdatedAt": "2026-04-10T09:00:00Z" } ], "meta": { "total": 42, "page": 1, "perPage": 50, "totalPages": 1 }}

Translation Statuses

StatusDescription
completedTranslation is current and matches the latest source content
staleTranslation exists but the source page has been updated since. The translation is still served but may be outdated.
pendingPage has not been translated yet for this language
in_progressTranslation is currently being processed
failedTranslation failed (typically due to content complexity or LLM error)

A stale translation is still served to readers. HolyDocs does not hide translated content when the source changes. Instead, it flags the translation as stale so you can prioritize retranslation. Use scope: "stale" in the translate endpoint to batch-update stale pages.

Add Glossary Term

Add a term to the project glossary. Glossary terms ensure consistent translation of domain-specific terminology, product names, and technical jargon across all languages.

bash
POST /api/v1/projects/:projectId/glossary

Request Body

json
{ "term": "HolyDocs", "description": "Product name, do not translate", "translations": { "ja": "HolyDocs", "de": "HolyDocs", "zh-CN": "HolyDocs", "fr": "HolyDocs" }}
FieldTypeRequiredDescription
termstringYesThe source term (1-100 characters)
descriptionstringNoContext for the translator (e.g., "Product name, do not translate")
translationsobjectNoMap of language codes to translated terms. If omitted for a language, the AI uses the description as guidance.
caseSensitivebooleanNoMatch the term case-sensitively (default: true)

Response

json
{ "data": { "id": "gl_abc123", "term": "HolyDocs", "description": "Product name, do not translate", "translations": { "ja": "HolyDocs", "de": "HolyDocs", "zh-CN": "HolyDocs", "fr": "HolyDocs" }, "caseSensitive": true, "createdAt": "2026-04-11T10:00:00Z" }}
bash
curl -X POST "https://api.holydocs.com/api/v1/projects/proj_abc123/glossary" \ -H "Authorization: Bearer hd_a1b2c3d4e5f67890a1b2c3d4e5f67890" \ -H "Content-Type: application/json" \ -d '{ "term": "deployment pipeline", "description": "The automated build and publish process", "translations": { "ja": "\u30c7\u30d7\u30ed\u30a4\u30e1\u30f3\u30c8\u30d1\u30a4\u30d7\u30e9\u30a4\u30f3", "de": "Deployment-Pipeline", "fr": "pipeline de d\u00e9ploiement" } }'

Glossary Best Practices

Add entries for your product name, feature names, and brand terminology. Set the translation to the original term if it should not be translated (e.g., "HolyDocs" stays "HolyDocs" in all languages).

Terms like "webhook," "API key," and "SSO" may have established translations in some languages and should remain in English in others. Use the translations field to specify the correct form per language.

Add glossary entries for acronyms (e.g., "RBAC" with description "Role-Based Access Control") so the AI translator expands or preserves them appropriately in context.

If your documentation references specific UI labels (e.g., "Settings > API Keys"), add glossary entries so these labels are translated consistently with your product's actual localized UI.

Update Glossary Term

Update an existing glossary term's translations, context, or doNotTranslate flag. All fields are optional — unspecified fields are left untouched.

bash
PUT /api/v1/projects/:projectId/glossary/:termId

Request Body

json
{ "sourceTerm": "deployment pipeline", "translations": { "es": "pipeline de despliegue", "ja": "デプロイパイプライン" }, "context": "technical", "doNotTranslate": false}
FieldTypeRequiredDescription
sourceTermstringNoNew source term
translationsobjectNoMap of language codes to translated terms (replaces the existing map)
contextstringNoContext for the translator
doNotTranslatebooleanNoIf true, preserve the source term verbatim in all translations

Response

json
{ "data": { "id": "gl_abc123", "sourceTerm": "deployment pipeline", "translations": { "es": "pipeline de despliegue", "ja": "デプロイパイプライン" }, "context": "technical", "doNotTranslate": false }}

Returns 404 NOT_FOUND if the glossary term does not exist or belongs to another project.

List Glossary Terms

Retrieve all glossary terms for a project.

bash
GET /api/v1/projects/:projectId/glossary

Query Parameters

ParameterTypeRequiredDescription
pagenumberNoPage number (default: 1)
perPagenumberNoResults per page (default: 50, max: 200)
qstringNoSearch glossary terms by name

Response

json
{ "data": [ { "id": "gl_abc123", "term": "HolyDocs", "description": "Product name, do not translate", "translations": { "ja": "HolyDocs", "de": "HolyDocs", "zh-CN": "HolyDocs", "fr": "HolyDocs" }, "caseSensitive": true, "createdAt": "2026-04-11T10:00:00Z" }, { "id": "gl_def456", "term": "deployment pipeline", "description": "The automated build and publish process", "translations": { "ja": "\u30c7\u30d7\u30ed\u30a4\u30e1\u30f3\u30c8\u30d1\u30a4\u30d7\u30e9\u30a4\u30f3", "de": "Deployment-Pipeline", "fr": "pipeline de d\u00e9ploiement" }, "caseSensitive": false, "createdAt": "2026-04-11T10:05:00Z" } ], "meta": { "total": 15, "page": 1, "perPage": 50, "totalPages": 1 }}

Export Translations to Repo

Commit all translations for a given language to a new branch in the project's connected repo. Lets you turn dashboard-only translations into repo-committed files that downstream tools or teammates can review in a pull request.

bash
POST /api/v1/projects/:projectId/translations/export-repo

Request Body

json
{ "language": "ja", "branch": "translations/ja"}
FieldTypeRequiredDescription
languagestringYesTarget language code
branchstringNoDestination branch name. Defaults to holydocs/translations-<lang>-<timestamp>

Response

json
{ "data": { "branch": "holydocs/translations-ja-1713384000000", "commitSha": "a1b2c3d4...", "filesWritten": 42 }}

Behavior

  • Files are written as <language>/<slug>.mdx under the project's repoPath (docs directory).
  • If the branch doesn't exist, it's created from the default branch. Existing branches are reused (idempotent).
  • The response includes the commit SHA — open a PR manually on GitHub to merge.
  • Requires a GitHub connection on the project. GitLab export is not yet supported.
  • Returns filesWritten: 0 when there are no translations for the language (no-op).

Use this endpoint to graduate AI-generated or dashboard-edited translations into your repository so they are preserved across re-deploys and visible in code review. Once exported, HolyDocs treats them as human-owned translations and will never overwrite them with AI output.

Translation Workflow

A typical translation workflow using the API:

1

Add target languages

Configure the languages you want to support. Enable autoTranslate for languages that should stay automatically up-to-date.

bash
POST /api/v1/projects/proj_abc123/languages{"code": "ja", "autoTranslate": true}
2

Build your glossary

Add domain-specific terms, product names, and technical terminology to ensure consistent translations.

bash
POST /api/v1/projects/proj_abc123/glossary{"term": "HolyDocs", "description": "Product name, do not translate"}
3

Trigger initial translation

Translate all existing pages for each configured language.

bash
POST /api/v1/projects/proj_abc123/translate{"language": "ja", "scope": "all"}
4

Monitor progress

Poll the translations endpoint to track completion status.

bash
GET /api/v1/projects/proj_abc123/translations?language=ja&status=pending
5

Maintain translations

With autoTranslate enabled, updated pages are retranslated on each deployment. For manual control, use scope: "stale" to batch-retranslate pages whose source has changed.

Translation Limits by Plan

PlanLanguagesPages per MonthGlossary Terms
Free15010
Starter350050
Pro105,000200
Business2450,0001,000
Enterprise24UnlimitedUnlimited

"Pages per month" counts individual page translation operations. Translating 42 pages into 3 languages counts as 126 page translations. Retranslating a stale page also counts as one operation.

Error Codes

CodeStatusDescription
NOT_FOUND404Project not found or language not configured
VALIDATION_ERROR400Invalid language code, missing required fields, or unsupported language
AUTH_ERROR401Missing or invalid authentication
FORBIDDEN403API key lacks projects:write scope
LIMIT_EXCEEDED429Language limit, monthly page limit, or glossary term limit exceeded
ALREADY_EXISTS409Language already configured or glossary term already exists
TRANSLATION_FAILED502LLM translation failed (retry the job)
Ask a question... ⌘I