Structured JSON output for document layout
Async Mdkit jobs also produce a structured JSON document — fetch it with format=json when you need layout and structure, not just text.
Last updated
| Availability | Async lane only — GET /v1/convert/jobs/{id}/result?format=json |
|---|---|
| Extra cost | None — one job produces both Markdown and JSON |
Markdown is the right output for LLM prompts, but some pipelines need structure: what was a table, what was a heading, which page a paragraph came from. Async conversion jobs produce both outputs from one conversion — Markdown for text, JSON for structure — and you choose per fetch.
The JSON is the high-fidelity engine's own document model: a schema_name and
version at the top, then arrays of texts, tables, pictures and pages
beneath, with each item carrying its label (section header, paragraph, list
item, caption …) and its provenance — the page number and bounding box it was
found at.
Fetch both formats
curl -H "X-API-Key: $MDKIT_API_KEY" \
"https://api.mdkit.online/v1/convert/jobs/$JOB_ID/result?format=markdown" -o doc.md
curl -H "X-API-Key: $MDKIT_API_KEY" \
"https://api.mdkit.online/v1/convert/jobs/$JOB_ID/result?format=json" -o doc.json
Python — walk the structure
import httpx
BASE = "https://api.mdkit.online"
HEADERS = {"X-API-Key": "YOUR_KEY"}
job_id = "YOUR_JOB_ID"
doc = httpx.get(
f"{BASE}/v1/convert/jobs/{job_id}/result",
params={"format": "json"},
headers=HEADERS,
timeout=60,
).json()
print(doc["schema_name"], doc["version"])
for item in doc.get("texts", []):
if item.get("label") == "section_header":
print("heading:", item["text"])
for table in doc.get("tables", []):
data = table.get("data", {})
pages = [prov["page_no"] for prov in table.get("prov", [])]
print(f"table {data.get('num_rows')}x{data.get('num_cols')} on page(s) {pages}")
When JSON earns its weight
- Structure-aware chunking — cut on element boundaries so a table is never sliced in half, then embed the Markdown of each chunk.
- Page-accurate citations — every item's provenance carries a page number, so an answer can say page 14 instead of somewhere in this document.
- Selective extraction — pull only the tables, or only the captions, without writing a Markdown parser.
Stay on Markdown when the destination is a prompt: the JSON is faithful, not compact, and paying tokens for bounding boxes helps nobody.
Rules of the road
- JSON is an async-lane feature.
POST /v1/convertreturns Markdown only; submit throughPOST /v1/convert/jobsto get both. - One job, both outputs, no extra credits — the job's 10 credits cover the conversion and you may fetch either format as often as you like.
- The result endpoint answers
409until the job has succeeded, and a job id that is not yours is a plain404— job ids stay unenumerable.
Try it
Sign in with a magic link for an API key, submit one document through the async lane, and diff the two outputs.
FAQ
- How do I get structured JSON instead of Markdown?
- Fetch an async job's result with format=json. JSON output is an async-lane feature — the synchronous /v1/convert endpoint returns Markdown only.
- What is in the JSON document?
- The high-fidelity engine's full structured representation of the input: a schema name and version, then arrays of texts, tables, pictures and pages, each item labelled and carrying the page it came from. Use it when you need structure rather than prompt-ready text.
- Can I get both Markdown and JSON from one job?
- Yes. A single async job produces both; you choose per fetch by changing the format parameter, at no extra credit cost.
- Does the JSON say which page something came from?
- Yes. Items carry a provenance entry with the page number and the bounding box on that page, which is what makes page-accurate citations possible in a RAG answer.