Document Translation API Overview

View as Markdown

The Document Translation API takes a source document and returns it translated into one or more Indian languages, in its original file format. The layout, formatting, and structure of the source file are preserved.

Authentication: send your API key in the api-subscription-key header. Generate a key from Key Management in the dashboard.

What you get from one job

A single job translates into up to 12 target languages (out of 23 total supported) from one uploaded document. You upload once, and each target language is translated independently and exported separately.

How it works

Document translation is asynchronous by design: you create a job, upload the file, start the pipeline, poll it, and then export each language’s result, rather than getting a translated file back from a single request. Every integration follows the same five steps:

1

Create the job

POST /translate/document/jobs with your source/target languages and the original filename. Returns a job_id and a short-lived signed upload_url, with status 201 Created.

2

Upload the document

PUT the file bytes to upload_url. This step is required; the create call only accepts metadata, not the file itself.

3

Start the pipeline

POST /translate/document/jobs/{job_id}/start, no request body. Runs file validation, then parsing (OCR for PDFs, structural extraction for Office and web formats), then translation, one independent branch per target language. Idempotent: calling start again on the same job returns the current job state instead of erroring.

4

Poll progress

GET /translate/document/jobs/{job_id}/live-status for an overall progress percentage and per-language translation state. Poll every 10-15 seconds.

5

Export each language

POST /translate/document/jobs/{job_id}/export?lang={code}&format={fmt} to enqueue an async export for one target language, then poll GET /translate/document/jobs/{job_id}/export/status until export_state is Completed and download from download_url.

Export is per language, not one call for the whole job. Loop over your target_language_codes and call export once for each, only after that language’s own state in live-status is Completed. Calling export before that returns 409 Conflict.

Quickstart

Install the SDK (pip install sarvamai or npm install sarvamai), set SARVAM_API_KEY, and point document at a local PDF or Office file. The client uses https://api.sarvam.ai by default, so your API key is the only configuration it needs.

Document translation does not include an SDK upload helper yet. After create, PUT the file bytes to upload_url with Content-Type and x-ms-blob-type: BlockBlob, then call start. See Poll and Export for the polling and download loop.

1import os
2from pathlib import Path
3
4import httpx
5from sarvamai import SarvamAI
6
7client = SarvamAI(api_subscription_key=os.environ["SARVAM_API_KEY"])
8document = Path("chapter1.pdf")
9
10# 1. Create job (auto_process=True is the default)
11job = client.document_translation.create(
12 job_name="chapter1",
13 source_language_code="en-IN",
14 target_language_codes=["hi-IN", "ta-IN"],
15 original_filename=document.name,
16 auto_process=True,
17 model_type="plus",
18)
19
20# 2. Upload to the signed URL (required — not handled by the SDK)
21with document.open("rb") as f:
22 httpx.put(
23 job.upload_url,
24 content=f.read(),
25 headers={
26 "Content-Type": "application/pdf",
27 "x-ms-blob-type": "BlockBlob",
28 },
29 timeout=120.0,
30 )
31
32# 3. Start the pipeline (required even when auto_process=True)
33client.document_translation.start(job_id=job.job_id)
34
35# 4–5. Poll translation, then export — see Poll and Export guide
36print(job.job_id)

That job is now running. See Poll and Export for the polling loop and per-language download flow.

Page-granular vs document-granular responses

The response format depends on the uploaded file type:

  • PDFs are tracked per page.
  • Word, spreadsheets, and presentations are tracked per text segment (roughly a paragraph).

Both response formats share the same base fields. Only the progress-related fields differ.

Response shapes at a glance

PDF uploads (per page)Word / Spreadsheet / Presentation uploads (per segment)
Tracking unitPageSegment (paragraph-sized chunk of text)
Start responsenum_pages-
Live statuspage_metricstranslation_metrics
Per-language progresspages_completed, pages_failedprogress, segments_completed, segments_total
Other metricstotal_pages, pages_processed, pages_succeeded, pages_failedlanguages_total, languages_completed, languages_failed

Shared fields (both response types)

job_id job_state job_name source_language_code progress translations[] created_at updated_at

OptionalOn failure
warningserror_message

Job states

StateDescription
AcceptedJob created, queued for processing
RunningJob is being processed
CompletedAll languages translated successfully
PartiallyCompletedSome languages succeeded, some failed
FailedAll languages failed or a job-level error occurred

Terminal states are Completed, PartiallyCompleted, and Failed.

Each language in translations[] has its own state (Pending, Running, Completed, Failed), independent of the others. A language is exportable as soon as its own entry reads Completed, even while other languages in the same job are still Running. Treat PartiallyCompleted as a terminal state alongside Completed, and check each language’s own state before deciding what to export.

Request parameters

Required:

FieldDescription
job_nameHuman-readable job name, 1-255 characters
source_language_codeBCP-47 code identifying the original document’s language
target_language_codesArray of destination languages, 1 to 12 entries per job (out of 23 total supported); one translated document is produced per language
original_filenameFile name with extension; validated against the supported format list

Optional:

FieldDescription
genreContent category: NON_FICTION, ADULT_FICTION, CHILDREN_FICTION, RELIGIOUS, LEGAL, or ACADEMIC, used to tune the translation prompt
metadataAdditional metadata object
auto_processBoolean. When true (the default), all target languages are bulk-translated automatically once parsing/OCR completes
model_typelite (faster, suited to short-form content) or plus (higher quality, suited to long-form content). Defaults to plus when omitted
use_native_numeralsBoolean; when true, numerals render in the target script instead of Arabic numerals. null/false uses international numerals
style_guidelinesUp to ~4000 characters of global tone, terminology, and formatting instructions
language_specific_guidelinesPer-language overrides (~4000 characters each); keys must match entries in target_language_codes

Supported file formats

CategoryExtensions
PDF.pdf
Word.doc, .docx, .odt
Spreadsheets.xls, .xlsx, .ods
Presentations.ppt, .pptx, .odp
Web pages.html, .xhtml, .mhtml

Supported languages

23 languages: English plus 22 Indic languages.

LanguageCodeLanguageCode
Assameseas-INManipurimni-IN
Bengalibn-INMarathimr-IN
Bodobrx-INNepaline-IN
Dogridoi-INOdiaor-IN
Englishen-INPunjabipa-IN
Gujaratigu-INSanskritsa-IN
Hindihi-INSantalisat-IN
Kannadakn-INSindhisd-IN
Kashmiriks-INTamilta-IN
Konkanikok-INTelugute-IN
Maithilimai-INUrduur-IN
Malayalamml-IN

Response examples

POST /translate/document/jobs returns 201 Created:

1{
2 "job_id": "550e8400-e29b-41d4-a716-446655440000",
3 "upload_url": "https://api.sarvam.ai/translate/document/uploads/550e8400-e29b-41d4-a716-446655440000?sig=...",
4 "expires_in_hours": 24,
5 "source_language_code": "en-IN",
6 "target_language_codes": ["hi-IN", "ta-IN"]
7}

GET /translate/document/jobs/{job_id}/live-status returns:

1{
2 "job_id": "550e8400-e29b-41d4-a716-446655440000",
3 "job_name": "chapter1",
4 "job_state": "Running",
5 "source_language_code": "en-IN",
6 "progress": 55,
7 "page_metrics": {
8 "total_pages": 42,
9 "pages_processed": 23,
10 "pages_succeeded": 23,
11 "pages_failed": 0
12 },
13 "translations": [
14 {
15 "target_language_code": "hi-IN",
16 "state": "Running",
17 "pages_completed": 12,
18 "pages_failed": 0
19 },
20 {
21 "target_language_code": "ta-IN",
22 "state": "Pending",
23 "pages_completed": 0,
24 "pages_failed": 0
25 }
26 ],
27 "created_at": "2026-08-04T10:00:00Z",
28 "updated_at": "2026-08-04T10:05:00Z"
29}

GET /translate/document/jobs/{job_id}/export/status returns, once the export is Completed:

1{
2 "export_id": "exp_1a2b3c4d",
3 "job_id": "550e8400-e29b-41d4-a716-446655440000",
4 "target_language_code": "hi-IN",
5 "format": "pdf",
6 "export_state": "Completed",
7 "download_url": "https://api.sarvam.ai/translate/document/exports/550e8400-e29b-41d4-a716-446655440000/hi-IN?sig=...",
8 "filename": "chapter1_hi-IN.pdf",
9 "expires_in_hours": 24,
10 "file_size": 1048576,
11 "created_at": "2026-08-04T10:10:00Z",
12 "completed_at": "2026-08-04T10:12:30Z"
13}

Errors

HTTP StatusDescription
400Invalid request — invalid language code, genre, filename, or export format
401Unauthorized — send a valid api-subscription-key
402Payment required — insufficient credits to complete this operation
404Not found — no job exists for this job_id, or no export for the given export_id or lang
409Conflict — export already in progress for this language and format, or translation not yet Completed
500Internal server error
503Service unavailable — export enqueue failed. Please retry

Best Practices

Poll, Don't Block

Poll live-status every 10-15 seconds from a background worker, not an HTTP request handler. Cap total wait time and handle timeouts gracefully.

Export Per Language

Export is per language, not one call for the whole job. Loop over your target_language_codes and call export once for each, only after that language’s own state is Completed.

Check Per-Language State

Don’t gate the export loop on job_state alone. A job at PartiallyCompleted can still have individual languages ready to export. Check each language’s own state in translations[].

Pick the Right Genre

Use genre to tune the translation prompt for your content type. LEGAL for contracts, CHILDREN_FICTION for children’s books, ACADEMIC for research papers.

Limits

LimitValue
Target languages per job1 to 12 (out of 23 total supported languages)
job_name length1-255 characters
style_guidelines / language_specific_guidelines length~4000 characters each
Signed upload URL validityexpires_in_hours on the create response (24 hours)
Signed export URL validityexpires_in_hours on the export response (24 hours); call export/status again for a fresh link
Poll intervalEvery 10-15 seconds against live-status

Next Steps

Need help scoping a document translation integration? Reach out on Discord.