Any document to JSON
Name what you need, such as the invoice number and the total due, and any document comes back in exactly that structure, whatever its layout. Details the document does not contain stay empty instead of being invented.
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.
Every document extraction project eventually hits the same wall: generic OCR gives you a wall of text, but your database wants fields.
Why plain text recognition is not enough
Plain text recognition tells you which characters are on a page. It does not know that the third number in the top-right corner is the invoice total, or that the paragraph under Effective Date is the date your contract system needs. Teams have long closed that gap with rules tuned to one document layout, and those rules break the moment a vendor changes its template. This tool flips the logic: instead of teaching it one layout, you describe what a good answer looks like, by name and type, and it looks for exactly those details wherever they sit on the page.
When to use it and what to watch for
It suits document flows with dozens of vendor layouts, contract templates that keep evolving or handwritten variations, such as a clinic moving patient details and insurance information from handwritten intake forms into the exact places its records system expects. Your structure can be a short list, like an invoice number and the total due, or nested, with line items that carry their own details. A common mistake is to treat a blank as a failure: when the document does not contain something, it is left empty or flagged rather than filled with a guess. If you add a plain-language instruction as well as a structure, the structure wins.
The gap between OCR and usable data
Plain OCR tells you what characters are on a page; it does not know that the third number in the top-right corner is an invoice total, or that the paragraph under 'Effective Date' is the field your contract system needs. Teams have historically closed that gap with regular expressions tuned to one document layout, which then break the moment a vendor changes their template.
What you can do with it
Medical intake form processing
A clinic extracts patient demographics and insurance information from handwritten intake forms into the exact fields their records system expects.
FAQ
Does it work on scanned paper as well as native PDFs?
Yes, it processes both scanned and native digital documents, and pricing is per page regardless of source format.
Can I choose exactly which details come back?
Yes. Describe the items you want by name and type, such as an invoice number and the total due, and the result follows that structure exactly, whatever the layout of the source document.
What happens if the document doesn't contain one of my items?
It is left empty or flagged as missing. The tool does not force a value that was not actually there, so a blank in the result means the document did not contain it.
Can it handle line items inside a document?
Yes. Your structure can be nested, for example a list of line items where each item carries its own details, and the result fills every level that the document actually provides.
Do I have to describe a structure, or can I just say what I need?
Either works. You can describe the exact structure, or give a plain-language instruction to steer the reading. If you provide both, the structure wins and the instruction is ignored.
Related tools
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, by email and from Telegram — and soon from our app too.
Call it from your stack
curl -X POST https://api.kit.forhosting.com/ocr/to-json \
-H "Authorization: Bearer $KIT_KEY" \
-H "Content-Type: application/json" \
-d '{"image":"https://ejemplo.com/imagen.jpg"}'const res = await fetch("https://api.kit.forhosting.com/ocr/to-json", {
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.KIT_KEY}`,
"Content-Type": "application/json"
},
body: JSON.stringify({
"image": "https://ejemplo.com/imagen.jpg"
})
});
const { task_id } = await res.json();import os, requests
res = requests.post(
"https://api.kit.forhosting.com/ocr/to-json",
headers={"Authorization": f"Bearer {os.environ['KIT_KEY']}"},
json={
"image": "https://ejemplo.com/imagen.jpg"
},
)
task_id = res.json()["task_id"]<?php
$res = file_get_contents("https://api.kit.forhosting.com/ocr/to-json", false, stream_context_create([
"http" => [
"method" => "POST",
"header" => "Authorization: Bearer " . getenv("KIT_KEY") . "\r\nContent-Type: application/json",
"content" => '{"image":"https://ejemplo.com/imagen.jpg"}',
],
]));
$task = json_decode($res, true);body := bytes.NewBufferString(`{"image":"https://ejemplo.com/imagen.jpg"}`)
req, _ := http.NewRequest("POST", "https://api.kit.forhosting.com/ocr/to-json", body)
req.Header.Set("Authorization", "Bearer "+os.Getenv("KIT_KEY"))
req.Header.Set("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)Example request
{
"image": "https://ejemplo.com/imagen.jpg"
}Example response
{
"task_id": "tsk_a1b2c3d4e5f6a1b2c3d4e5f6",
"type": "ocr.to_json",
"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_mb | 25 |
max_pages | 10 |
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. |
Technical notes
This endpoint takes a document and the schema you define, then returns JSON shaped exactly to that schema, so extraction stops being a text-parsing project and starts being a straightforward API call.
The gap between OCR and usable data
This endpoint closes the gap differently: you describe the fields you want, by name and type, and the extraction targets exactly those fields regardless of how the source document is laid out.
How you define what comes back
You send the document plus a schema describing the fields you need, whether that is a flat list like invoice_number and total_due or a nested structure with line items and their own sub-fields, to POST /ocr/to-json. You get a task_id right away, since matching document content to an arbitrary schema takes real processing time. When it finishes, the result is JSON that mirrors your schema, with fields populated where the document contains them and left empty or flagged where it does not, rather than forcing a value that was not actually there.
Why schema-driven extraction generalizes better
Fixed-template extractors have a long history in document automation and they still work well for a single unchanging form, but most real document flows involve dozens of vendor layouts, evolving contract templates, or handwritten variations that a rigid template cannot anticipate. Schema-driven extraction flips the logic: instead of teaching the system one layout, you tell it what a good answer looks like, and it reads any layout looking for that answer. That is what makes the same schema work across an invoice from one supplier and a completely different-looking invoice from another.
How it plugs into the rest of a pipeline
This endpoint is commonly the second step after document classification, since the right schema depends on knowing whether you are looking at an invoice, a lease, or a medical form. Once you have structured JSON, it drops directly into a database insert, a validation rule set, or a downstream key-points summary without any further text wrangling. Because each call carries its own schema, you can run different extractions against different document types in the same pipeline without maintaining separate integrations for each.
Pricing that matches the work involved
A task that fails is never charged, we retry automatically up to three times and then return a specific error if extraction genuinely cannot complete. The cost is $0.010 per request plus $0.0575 per page, reflecting that extraction time scales with document length, not with how many fields your schema asks for. There is no free tier or trial, access requires prepaid balance and calls without one return HTTP 402, which keeps throughput reliable for paying workloads instead of degraded by unmetered traffic.
Integration use cases
Invoice ingestion into an accounting system
An accounts payable team defines a schema with vendor, invoice number, line items, and total, then extracts every incoming invoice into that exact shape regardless of vendor layout.
Lease abstraction for property management
A property manager extracts rent amount, term dates, and renewal clauses from leases with wildly different formatting into one consistent JSON structure.
Insurance claim form digitization
An insurer extracts policyholder details, claim amounts, and incident dates from scanned claim forms directly into their claims database schema.
Technical questions
How do I define what fields the document to JSON API extracts?
You send a schema describing the fields you want, by name and type, alongside the document, and the response mirrors that schema exactly, including nested structures like line items.
What happens if a field in my schema is not in the document?
The field is left empty or flagged rather than filled with a guessed value, so you can distinguish genuinely missing data from a parsing failure.
Can the same schema work across documents from different vendors?
That is the core advantage over template-based extraction: a well-defined schema targets the same fields across differently laid-out documents without a per-vendor template.
Is there a free tier to test the document to JSON API?
There's no free tier — free tiers get abused and slow everyone down. Access runs on a prepaid ForHosting KIT balance: top up from $10.00 (it never expires) and each request is charged at its published price, so a call with no balance returns HTTP 402. No subscription, no tokens, no invented credits, and a failed task is never charged.
How much does document extraction cost?
It is $0.010 per request plus $0.0575 per page, and you are only charged for pages that are successfully processed.
How do I get the extracted JSON back?
You receive a task_id immediately, then the JSON result arrives via a signed webhook when ready or a signed link valid for 24 hours.
Can I run schema-based extraction on a large batch of documents?
Yes, each request is independent and billed per document, so you can send a single file or fan the same schema out across thousands of documents.