Translate a PDF
A contract, a manual or a government form rarely arrives as plain text — it arrives as a PDF, with columns, tables and a signature block that has to stay exactly where it is. This endpoint reads the document, translates the words, and rebuilds the page instead of handing you a wall of unformatted text.
Run it online
Run this on our servers with your account. Free tools run in your browser; this one bills your KIT balance per the price above.
The problem with 'just paste it into a translator'
Copy the text out of a two-column PDF and paste it anywhere else, and the columns collapse, the footnotes jump to the wrong place, and the table that lined up prices against dates turns into a run-on sentence. That's fine for a quick read, but useless for a document someone needs to file, print or sign. Legal teams, HR departments handling foreign hires, and import/export operations dealing with customs paperwork all hit this same wall: the translation is only half the job if the layout doesn't survive.
What actually happens to the file
POST /translate/pdf with the source file and target language and you get a task_id back immediately; the document is queued, its text extracted page by page, translated, and placed back into the original structure — same page breaks, same tables, same approximate positioning of headers and figures. Because this runs asynchronously, a ten-page lease and a two-page invoice queue the same way and you're never left holding an open connection waiting on a slow render.
Why PDF translation is harder than it looks
PDF was designed in the early 1990s as a fixed, print-accurate format — it describes where ink lands on a page, not what the words mean structurally the way an HTML document does. That's exactly why it's been the default for anything that must look identical everywhere: contracts, certificates, academic papers. But it also means a translator working from a PDF has to first reconstruct the logical reading order — which text belongs to which paragraph, which cell belongs to which table — before translating a single word, otherwise a sentence split across a page break comes out scrambled.
Getting the result back and where it fits
Once translation finishes, the new PDF arrives through a signed webhook call, or sits behind a signed link valid for 24 hours if your system prefers to poll instead. Because pricing is a flat request fee plus a per-page rate, a five-page NDA and a fifty-page technical manual both cost exactly what their page counts predict — no surprises, no rounding up to a plan tier. Bolt this into an onboarding flow, a document-management system, or a nightly batch job that clears a translation backlog, and it becomes one dependable step instead of a manual task someone dreads.
What you can do with it
Cross-border employment contracts
An HR platform translates signed employment contracts into a new hire's language while keeping clause numbering and signature blocks in their original positions.
Customs and shipping paperwork
A logistics company translates supplier invoices and certificates of origin so customs brokers in the destination country can read them without reformatting.
Academic paper distribution
A research office translates published PDF papers for internal circulation without breaking citation layout or figure placement.
Regulatory filing review
A compliance team translates foreign regulator PDFs into their working language so legal counsel can review clauses side by side with the original structure.
FAQ
How do I translate a PDF with the API?
POST the PDF file and target language to /translate/pdf, save the returned task_id, and retrieve the translated PDF by webhook or a signed link valid for 24 hours.
Is the PDF translation API free?
No, there is no free tier or trial; it costs $0.011 per request plus $0.0705 per page, and a failed translation is never charged.
Does the translated PDF keep the original layout?
Yes, the endpoint rebuilds the page structure — tables, columns and page breaks — around the translated text instead of returning plain text.
Can it handle scanned PDFs or only text-based ones?
It's built for text-based PDFs where the words are extractable; heavily scanned image-only pages should be processed through OCR first for reliable results.
How is the price calculated for a long document?
Price is a flat per-request fee plus a per-page rate, so a 100-page manual costs predictably more than a 2-page letter, with no plan tiers involved.
Can I translate many PDFs in bulk?
Yes, submit one asynchronous task per file and collect each finished PDF by webhook as it completes, which is the normal pattern for batch document runs.
Is this endpoint live?
Yes, /translate/pdf is live and accepting production requests today.
Is my document stored after translation?
No, source and translated files are removed after the retention window and are never used to train any model.
For developers — API access
Everything on this page is available programmatically. This section is for teams who want to wire it into their own systems; everyone else can just use the tool above.
API endpoint
Prefer to automate it? One authenticated POST creates the task; the result comes back by webhook or a signed link. The same capability also runs here on the web, and soon from our app, email and Telegram.
Call it from your stack
curl -X POST https://api.kit.forhosting.com/translate/pdf \
-H "Authorization: Bearer $KIT_KEY" \
-H "Content-Type: application/json" \
-d '{"input":"…"}'const res = await fetch("https://api.kit.forhosting.com/translate/pdf", {
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.KIT_KEY}`,
"Content-Type": "application/json"
},
body: JSON.stringify({
"input": "…"
})
});
const { task_id } = await res.json();import os, requests
res = requests.post(
"https://api.kit.forhosting.com/translate/pdf",
headers={"Authorization": f"Bearer {os.environ['KIT_KEY']}"},
json={
"input": "…"
},
)
task_id = res.json()["task_id"]<?php
$res = file_get_contents("https://api.kit.forhosting.com/translate/pdf", false, stream_context_create([
"http" => [
"method" => "POST",
"header" => "Authorization: Bearer " . getenv("KIT_KEY") . "\r\nContent-Type: application/json",
"content" => '{"input":"…"}',
],
]));
$task = json_decode($res, true);body := bytes.NewBufferString(`{"input":"…"}`)
req, _ := http.NewRequest("POST", "https://api.kit.forhosting.com/translate/pdf", body)
req.Header.Set("Authorization", "Bearer "+os.Getenv("KIT_KEY"))
req.Header.Set("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)Example request
{
"input": "…"
}Example response
{
"task_id": "tsk_a1b2c3d4e5f6a1b2c3d4e5f6",
"type": "translate.pdf",
"status": "queued",
"_links": {
"result": "/tasks/tsk_…/result"
}
}The API is asynchronous: the call returns a task_id immediately and the result arrives by webhook. Polling is capped at 1 req/s per task.
Pricing
Published price — no tokens, no invented credits. A failed task is never charged.
Limits
max_tokens | 20000 |
Errors
| HTTP | Code | Meaning |
|---|---|---|
401 | unauthorized | Missing or invalid API key. |
402 | insufficient_balance | Your balance doesn't cover the task price. |
404 | unknown_type | That task type doesn't exist. |
429 | rate_limited | Too many requests. Use the webhook instead of polling. |
413 | input_too_large | The file exceeds the size limit. |
422 | task_failed | The task failed after 3 retries. You are never charged for it. |