Index PDFs and scans
A filing cabinet of PDFs is only searchable if someone remembers which file has what in it. This endpoint reads contracts, reports and scanned forms page by page and turns them into an index you can query by meaning, not by filename.
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.
Why a folder of PDFs isn't actually searchable
Operating system search looks at filenames and, sometimes, embedded text layers — it has no idea what's inside a scanned invoice or a report saved as flattened images. Anyone who has hunted through a contracts folder for 'the clause about early termination' without knowing which file it's in has felt this gap directly. search.index_document exists to close it by reading the actual content, not just the file's metadata.
What happens to a document after you submit it
POST /search/index-document with your file, get back a task_id, and receive confirmation by webhook or a signed 24-hour link once the document has been read, split into fragments per page or section, embedded, and added to your searchable index. Scanned pages go through recognition first, so a photographed contract page and a digitally generated one both end up equally searchable.
The two document types this handles differently
A born-digital PDF already carries a text layer that can be extracted directly, but a scan — a faxed form, a photographed receipt, an old report digitized years after the fact — has no text at all, only pixels arranged to look like letters. That distinction has mattered since document imaging became common in the 1990s, and it still determines how much work has to happen before a document's content becomes something a computer can actually read, let alone search.
Where accuracy naturally varies
A clean, well-scanned page reads reliably; a blurry fax, tiny handwriting, or a table with unusual formatting is harder for any recognition process, human or automated, and results should be treated accordingly for anything where getting it exactly right matters, like legal or financial detail. This is a search index, not a certified transcription, and it's built for finding the right document fast, not for replacing a careful manual read of a critical page.
How it fits into a document-heavy workflow
Legal teams index case files so an associate can search across a matter's paper trail instead of opening each PDF in turn. Finance teams index scanned invoices to search old records by vendor or amount without an OCR pipeline of their own. Priced per request plus per page, a two-page memo and a two-hundred-page annual report both cost exactly what they take to process, with nothing charged for a document that fails to index correctly.
What you can do with it
Legal case file search
A law firm indexes the PDFs in a case folder so an associate can search across depositions, contracts and correspondence by topic instead of opening each file.
Scanned invoice archive
An accounting team indexes years of scanned invoices to search old records by vendor name or line-item description without maintaining its own OCR pipeline.
Policy and compliance lookup
An HR department indexes its policy PDFs so employees can search for the specific clause that applies to their situation instead of skimming every document.
Research paper library
A research group indexes a library of PDF papers to search across findings by concept rather than relying on each paper's title or abstract alone.
FAQ
How do I index a PDF for search with the API?
Send the file to POST /search/index-document, store the returned task_id, and get confirmation the document is indexed by webhook or a signed link valid for 24 hours.
Is the document indexing API free?
No, there's no free tier or trial; it costs $0.010 per request plus $0.059 per page, and a failed task is never charged.
Can it index scanned PDFs, not just digital ones?
Yes, scanned pages go through recognition before indexing, so both born-digital PDFs and scanned images become searchable.
How accurate is text extraction from a low-quality scan?
It depends on scan quality — clean pages read reliably, while blurry or handwritten pages are harder to process accurately, so treat critical details as needing a manual check.
What file formats does it accept besides PDF?
Check the endpoint reference for the current list of accepted document formats beyond PDF.
How is this different from search.index_text?
search.index_text indexes text you already have; search.index_document reads a file directly, including recognition for scanned pages, before indexing its content.
Can I index a large batch of documents at once?
Yes, submit multiple documents as separate async tasks and collect each confirmation by webhook, which scales cleanly for large archives.
Is the uploaded document kept after indexing?
No, uploaded files and results are deleted after the retention window and are never used for training.
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/search/index-document \
-H "Authorization: Bearer $KIT_KEY" \
-H "Content-Type: application/json" \
-d '{"input":"…"}'const res = await fetch("https://api.kit.forhosting.com/search/index-document", {
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/search/index-document",
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/search/index-document", 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/search/index-document", 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": "search.index_document",
"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_chunks | 10000 |
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. |