Document Translation API Guide: Bulk Word and PDF Translation with Python
Translate Word, PDF, Excel and other files in bulk with the OmniDoc document translation API: upload, create jobs, receive webhooks and download results. Python example, job parameters, idempotent retries and pricing rules.
Document Translation API Guide: Translate Word and PDF Files in Bulk with Python and Webhooks
If your system handles contracts, manuals, papers or reports every day, uploading, waiting and downloading by hand quickly becomes the bottleneck. The OmniDoc document translation API hands the whole loop to your code:
upload a file, create a job, get notified when it finishes, download the result
. Translations keep the original layout, tables, images and formulas, and can be bilingual (source and translation side by side) or translation only.
The basics
Table 1
API conventions
Item
Details
Base URL
https://omnidoc.top/api/v1
Authentication
API key in the X-API-Key header, or sent as a Bearer token; create keys in the API console
Requests
JSON with Content-Type: application/json
Tracing
Keep the X-Request-Id of every response and quote it when contacting support
Rate limits
On 429, retry after the Retry-After interval
Supported files
Word (.docx), Excel (.xlsx), PowerPoint (.pptx), PDF, HTML, EPUB, Markdown and plain text, SRT/ASS subtitles, CSV, PNG/JPG images and UniDoc documents (.udoc). Every format except PPTX supports bilingual output: Word pairs paragraphs, Excel pairs columns, PDF pairs pages and subtitles pair lines. A bilingual request for PPTX returns the translation only.
Four steps to a translated file
Request an upload
: POST /upload/presign with the file name and size to get a direct upload URL, upload headers and a finalize_token.
Upload and confirm
: PUT the file with the returned headers (do not send your API key there), then POST /upload/finalize to get document.id.
Create the job
: POST /jobs with document_id and target_lang; an Idempotency-Key header is recommended.
Collect the result
: poll GET /jobs/{id}, subscribe to SSE progress or use a webhook; when the job completes, list the outputs with GET /artifacts?job_id=... and download them.
Job parameters
Table 2
POST /jobs request fields
Field
Default
Meaning
document_id
—
Confirmed document ID (required)
target_lang
—
Target language code (required)
source_lang
auto-detect
Source language code
engine
xr-397b
Translation profile: xr-397b, deepseek, qwen, chatgpt, gemini or claude
output_mode
bilingual
bilingual or single (translation only)
glossary_id
—
Glossary that fixes brand names and terminology
include_images
false
Also translate text inside images
context_translation
false
Context-aware translation for consistent terms
style_preset
—
Writing style preset
Python: create a job and wait for it
This snippet only needs requests. The full upload-to-download example is on the Python page of the developer docs.
import time, uuid, requests
BASE = "https://omnidoc.top/api/v1"
HEADERS = {"X-API-Key": "sk_your_key"}
def create_job(document_id, target_lang="en", engine="xr-397b"):
r = requests.post(f"{BASE}/jobs",
headers={**HEADERS, "Idempotency-Key": str(uuid.uuid4())},
json={"document_id": document_id, "target_lang": target_lang, "engine": engine},
timeout=30)
r.raise_for_status()
return r.json()
def wait_for_job(job_id):
while True:
job = requests.get(f"{BASE}/jobs/{job_id}", headers=HEADERS, timeout=20).json()
if job["status"] in ("completed", "failed"):
return job
time.sleep(5)
Batches and retries: concurrency, queueing and idempotency
Automatic queueing
: each account processes up to 5 files at a time; further jobs are still created and wait in the queue, and stage_message tells you how many are ahead.
Idempotency keys
: the same Idempotency-Key with the same body returns the original job, so nothing is created or charged twice. After a network timeout, query the job first instead of retrying with a new key.
Error codes
: 403 means the key may not use the chosen profile, 404 that the document or glossary does not exist, 415 an unsupported format, 422 an empty file or invalid parameters.
Webhooks: let the job call you
Each user can register up to 3 webhooks (POST /webhooks to create, PATCH to update or disable). When a file translation job ends, successfully or not, OmniDoc sends a job.completed event; data.status is completed or failed and data.char_count is the number of translated characters. If you set a secret, every callback carries X-Webhook-Signature: verify it with HMAC-SHA256 over the raw request body. The URL must be publicly reachable, and HTTPS is recommended.
What it costs
Balance check before start
: a PDF needs a balance above page count × 2 credits; other formats are estimated from the source text, at least 2 credits. If the balance is short, the job ends with quota_exceeded and nothing is charged.
Charged on delivery
: the actual usage is charged when the job completes; failed or cancelled jobs cost nothing.
Queries are free
: balance, job status, usage, receipts and download links never use credits.
Credit packs
start at 3,000 credits for ¥9.9, and purchased credits do not expire; GET /billing/credits/plans lists the packs on sale.
Next steps
Developer quickstart with complete cURL, Python and Node.js examples: https://docs.omnidoc.top/guide/quickstart/ . Prefer not to write code? An AI assistant connected to OmniDoc can translate local files directly; see https://omnidoc.top/blog/en/ai-word-excel-ppt-omnidoc/ .
- 1 -
Updated 2026-10-18