Repair broken JSON
The JSON that actually shows up in production is rarely the clean, spec-perfect kind — it's got a trailing comma from a hand-edited config, single quotes copied from JavaScript, or a stream cut off mid-object because a language model hit its token limit. This endpoint takes that broken text and repairs it into JSON a strict parser will accept.
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 'almost JSON' is everywhere now
Since large language models started generating structured output as plain text rather than through a guaranteed schema, a huge share of the JSON flowing through automation pipelines now comes from a model that got cut off mid-response, added a stray comment, or wrapped the object in markdown fences out of habit. Add in JSON hand-edited by a person who's used to JavaScript's forgiving object literals, or config files copied between projects with a leftover trailing comma, and a strict parser rejects documents that are one small, mechanical fix away from being perfectly valid. data.json_repair exists for exactly that gap between 'obviously meant to be JSON' and 'passes JSON.parse.'
What gets fixed and how you get it back
POST the broken text to /data/json-repair, and a task_id comes back right away while the repair runs in the background. It handles the common failure patterns directly: trailing commas before a closing bracket, unquoted or single-quoted keys, missing closing brackets on a truncated stream, and stray text like markdown code fences wrapped around the object. The repaired, strictly valid JSON — along with a summary of what was changed — arrives by signed webhook or waits behind a signed link valid for 24 hours.
Repair versus guessing
There's an important line between fixing structural syntax and inventing data, and this endpoint stays firmly on the syntax side of it: closing an unterminated string, adding a missing bracket, removing a comma that shouldn't be there are mechanical, unambiguous fixes. It does not fabricate missing field values or guess at what a truncated value was supposed to say — if a value itself was cut off with no way to recover it, that's reported rather than invented, because a repair tool that quietly makes up data is worse than one that fails loudly.
Where it belongs in an automated pipeline
The natural place for this endpoint is right after any step that produces JSON without a strict guarantee it's well-formed — parsing an LLM completion, ingesting a hand-maintained config, or reading output from a script that doesn't validate its own writes — and right before that JSON is handed to code that will otherwise throw on the first syntax error. Because pricing is per request plus a per-document rate and a failure is never billed, it's cheap enough to run as a standing safety net on every JSON payload a pipeline receives rather than something reached for only after an outage traces back to a malformed document.
What you can do with it
Recovering truncated LLM completions
An agent pipeline repairs JSON output from a language model that was cut off mid-object due to hitting its token limit, recovering everything that streamed before the cutoff.
Cleaning hand-edited config files
A DevOps tool repairs JSON configuration files edited by hand that picked up trailing commas or single-quoted keys from JavaScript habits.
Stripping markdown fences from model output
An automation script repairs JSON that a chat model wrapped in triple-backtick markdown fences, extracting and validating the object inside.
Pre-ingestion validation gate
A data pipeline runs every incoming JSON payload through repair before storage, so a minor syntax issue never blocks an otherwise-usable record.
FAQ
How do I fix broken JSON with the API?
POST the malformed text to /data/json-repair, save the returned task_id, and receive the repaired JSON by webhook or a signed link valid for 24 hours.
Is the JSON repair API free?
No, there is no free tier or trial; it costs $0.003 per request plus $0.0135 per document, and a failed repair is never charged.
Can it fix JSON truncated by an LLM hitting its token limit?
Yes, closing unterminated strings, objects and arrays from a cut-off stream is one of the most common repairs it performs.
Does it fix trailing commas and single-quoted keys?
Yes, trailing commas before closing brackets and unquoted or single-quoted keys, both common in hand-edited or JavaScript-style JSON, are corrected.
Will it invent missing data to make the JSON valid?
No, it fixes structural syntax only; if an actual value was truncated with no way to recover it, that's reported rather than fabricated.
Does it remove markdown code fences around JSON?
Yes, JSON wrapped in triple-backtick markdown fences, common in chat model output, is unwrapped and validated as part of the repair.
Can I repair a large batch of documents at once?
Yes, submit one async task per document and collect each result by webhook, which fits pipelines that repair many LLM outputs or configs at once.
Is my broken JSON data stored after repair?
No, submitted text and repaired 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/data/json-repair \
-H "Authorization: Bearer $KIT_KEY" \
-H "Content-Type: application/json" \
-d '{"input":"…"}'const res = await fetch("https://api.kit.forhosting.com/data/json-repair", {
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/data/json-repair",
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/data/json-repair", 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/data/json-repair", 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": "data.json_repair",
"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 |
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. |