Text to JSON
Free-form text refuses to fit into a database column until someone forces it to. This endpoint does the forcing: give it your schema and a block of text — a product description, a resume, a support ticket — and it returns JSON that matches your fields exactly, validated so malformed output never reaches your application.
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 'just parse it' is harder than it sounds
Text written for humans rarely lines up with the fields an application needs. A resume mentions a phone number in one sentence and a job title three paragraphs later; a product description buries the material and dimensions inside marketing copy. Writing a parser for every source format is a losing game, because the format changes every time the source changes. text.to_json replaces that brittle parsing logic with a schema you define once and text you can point at anything.
You define the shape, we fill it in
POST /text/to-json takes two things: your target schema, describing the fields, types, and which ones are required, and the source text to extract from. The response is JSON built to that exact shape — no extra fields invented, no renamed keys, no silent type coercion that turns a string into a number when it shouldn't. If a required field genuinely is not present in the source text, the response says so instead of inventing a plausible-looking placeholder.
Validation is not an afterthought here
The output is checked against your schema before it is returned, so what lands in your webhook is already structurally valid — correct types, correct required fields, no orphan keys. This matters more than it sounds: unstructured-to-structured pipelines usually fail quietly, with a malformed record slipping into a database and breaking a report three weeks later. Validating at generation time turns that into an immediate, visible error instead.
Where this replaces a small army of custom parsers
Teams that ingest text from many different sources — scraped listings, forwarded emails, PDFs converted to text, scanned forms — traditionally write and maintain a separate parser per source. A single schema-driven extraction call replaces that whole maintenance burden, because the model reads intent rather than matching brittle patterns, so it survives format drift that would break a regular expression.
How it plugs into automation
Because the task is asynchronous and delivers a signed webhook, it drops cleanly into an ingestion pipeline: a document lands, gets converted to text, sent for extraction, and the resulting JSON is inserted straight into your system with no manual review step required for the common case, though nothing stops you from spot-checking the ones your business considers high stakes.
What you can do with it
Resume ingestion for hiring tools
Extract name, contact info, work history, and skills from freeform resume text into a consistent schema your applicant tracker already understands.
Product feed normalization
Turn scraped or supplier-provided product descriptions into structured records with price, dimensions, and material fields ready for your catalog.
Support ticket triage
Convert a customer's freeform complaint email into a structured object with category, urgency, and account reference for automatic routing.
Document digitization follow-up
Feed OCR output from scanned forms through the endpoint to get clean, validated JSON instead of hand-writing regex against noisy text.
FAQ
How does the text to JSON API know what fields I want?
You send a schema describing your desired fields, types, and which are required, and the endpoint extracts and formats the source text to match that shape exactly.
What happens if the text doesn't contain a required field?
The response will indicate the field could not be found rather than inventing a plausible value, so you can distinguish missing data from a parsing failure.
Does it support nested objects and arrays in the schema?
Yes, schemas can describe nested structures and lists, and the extraction follows that shape rather than flattening everything into a single level.
Is the output validated before I receive it?
Yes, the JSON is checked against your schema for correct types and required fields before delivery, so what reaches your webhook is already structurally sound.
Is there a free tier to try text to JSON conversion?
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 is pricing calculated?
$0.003 per request plus $0.0135 per 1,000 words of source text. A failed extraction is never billed; the system retries automatically up to three times before returning a clear error.
Can I run this on a large batch of documents?
Yes, it's built for bulk use — queue as many asynchronous requests as you need against the same schema and collect results as each finishes.
How do I get the JSON back once it's processed?
Through a signed webhook, recommended for automated pipelines, or a signed link that stays valid for 24 hours for manual retrieval.
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/text/to-json \
-H "Authorization: Bearer $KIT_KEY" \
-H "Content-Type: application/json" \
-d '{"text":"…"}'const res = await fetch("https://api.kit.forhosting.com/text/to-json", {
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.KIT_KEY}`,
"Content-Type": "application/json"
},
body: JSON.stringify({
"text": "…"
})
});
const { task_id } = await res.json();import os, requests
res = requests.post(
"https://api.kit.forhosting.com/text/to-json",
headers={"Authorization": f"Bearer {os.environ['KIT_KEY']}"},
json={
"text": "…"
},
)
task_id = res.json()["task_id"]<?php
$res = file_get_contents("https://api.kit.forhosting.com/text/to-json", false, stream_context_create([
"http" => [
"method" => "POST",
"header" => "Authorization: Bearer " . getenv("KIT_KEY") . "\r\nContent-Type: application/json",
"content" => '{"text":"…"}',
],
]));
$task = json_decode($res, true);body := bytes.NewBufferString(`{"text":"…"}`)
req, _ := http.NewRequest("POST", "https://api.kit.forhosting.com/text/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
{
"text": "…"
}Example response
{
"task_id": "tsk_a1b2c3d4e5f6a1b2c3d4e5f6",
"type": "text.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_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. |
422 | task_failed | The task failed after 3 retries. You are never charged for it. |