Two Minute Toolkit TwoMinuteLab Fishbone
Clean Lab Fishbone Diagrams in 2 minutes or less

Lab Fishbone HTTP API

POST a small JSON description and get back a deck-ready PNG (or SVG). The endpoint is open and CORS-enabled, so it works from browsers, scripts, CI and anywhere else you can make an HTTP call. The same JSON opens in the builder.

POST https://www.twominutetoolkit.com/api/render/labfishbone
Fair use: rate-limited to 20 requests a minute per IP (bursts capped at 5 a second), shared across every Two Minute tool, with a 64 KB body cap. No key or sign-up needed.

Try it

Open in builder

Code samples

Live preview

Click Render to call the API.

Request body

FieldTypeDescription
titlestringHeading shown top-left at 22px bold, e.g. "Day 3 labs". An empty string hides it. Never put a patient name or identifier here: links carry the chart itself.
max 140 chars · default "Labs"
panelsrequiredobject[]The panels to draw (1–8), in order, two or three per row. Each has a `type` and its values as flat string keys; leave a key out to leave its position blank. More than 8 are dropped.
max 8 items
flagbooleanFlag numeric values outside the adult reference range: red with ↑ when high, blue with ↓ when low. Default true. Manual `flags` on a panel apply either way. Ranges vary by lab; this is a drawing aid, not clinical decision support.
default true
unitsstringWhich reference ranges the automatic flags use: "US" (conventional units: mg/dL, g/dL, %, mmHg; the default) or "SI" (mmol/L, µmol/L, g/L, L/L, kPa). It does not convert values.
"US", "SI" · default "US"
labelsbooleanShow a small analyte name (Na, K, Hgb…) beside every value. Default false: experienced readers know the positions; turn it on for teaching or for readers new to the shorthand.
default false
widthintegerChart width in pixels (640–2400). Omit it (recommended) and the chart sizes itself to its content with comfortable margins, between 880 and 1280px wide. PNG output renders at 2x.
640–2400
palettestring[]Hex colours; only the first is used, for the small panel-type tags. The skeletons stay monochrome, and flags are always red (high) and blue (low).
max 12 items · default ["#4f46e5","#0ea5e9","#10b981","#f59e0b","#ef4444","#6b7280"]

panels[] item

FieldTypeDescription
typestringWhich skeleton to draw, and which value keys it reads: "bmp" (basic metabolic panel / Chem-7: na, cl, bun over k, hco3, cr, with glu in the tail), "cbc" (wbc > hgb over hct < plt), "coag" (pt | ptt over inr), "lft" (hepatic panel: tp, ast, tbili over alb, alt, alp), "abg" (ph / pco2 / po2 / hco3) or "chem" (extended electrolytes: ca over mg | phos). Default "bmp". Keys that belong to another type are ignored with a warning.
"bmp", "cbc", "coag", "lft", "abg", "chem" · default "bmp"
captionstringOptional short caption above the panel, after its type tag, e.g. "06:00" or "Day 3, post-op". Never a patient name or identifier.
max 40 chars
nastringSodium (Na), BMP: top left. mmol/L, e.g. "138". A string of up to 8 characters; non-numeric text such as "<0.1", "pending" or "—" is shown as written and never flagged. Omit it to leave the position blank.
max 8 chars
kstringPotassium (K), BMP: bottom left. mmol/L, e.g. "4.1". A string of up to 8 characters; non-numeric text such as "<0.1", "pending" or "—" is shown as written and never flagged. Omit it to leave the position blank.
max 8 chars
clstringChloride (Cl), BMP: top middle. mmol/L, e.g. "102". A string of up to 8 characters; non-numeric text such as "<0.1", "pending" or "—" is shown as written and never flagged. Omit it to leave the position blank.
max 8 chars
hco3stringBicarbonate (HCO3): BMP bottom middle (serum CO2, mmol/L, e.g. "24"), or the last value of an ABG. A string of up to 8 characters; non-numeric text such as "<0.1", "pending" or "—" is shown as written and never flagged. Omit it to leave the position blank.
max 8 chars
bunstringBlood urea nitrogen (BUN), BMP: top right. mg/dL (US) or urea mmol/L (SI), e.g. "18". A string of up to 8 characters; non-numeric text such as "<0.1", "pending" or "—" is shown as written and never flagged. Omit it to leave the position blank.
max 8 chars
crstringCreatinine (Cr), BMP: bottom right. mg/dL (US) or µmol/L (SI), e.g. "1.1". A string of up to 8 characters; non-numeric text such as "<0.1", "pending" or "—" is shown as written and never flagged. Omit it to leave the position blank.
max 8 chars
glustringGlucose (Glu), BMP: in the tail on the right. mg/dL (US) or mmol/L (SI), e.g. "112". A string of up to 8 characters; non-numeric text such as "<0.1", "pending" or "—" is shown as written and never flagged. Omit it to leave the position blank.
max 8 chars
wbcstringWhite blood cells (WBC), CBC: left. ×10³/µL, e.g. "8.4". A string of up to 8 characters; non-numeric text such as "<0.1", "pending" or "—" is shown as written and never flagged. Omit it to leave the position blank.
max 8 chars
hgbstringHemoglobin (Hgb), CBC: top middle. g/dL (US) or g/L (SI), e.g. "13.2". A string of up to 8 characters; non-numeric text such as "<0.1", "pending" or "—" is shown as written and never flagged. Omit it to leave the position blank.
max 8 chars
hctstringHematocrit (Hct), CBC: bottom middle. % (US) or L/L (SI), e.g. "39.5". A string of up to 8 characters; non-numeric text such as "<0.1", "pending" or "—" is shown as written and never flagged. Omit it to leave the position blank.
max 8 chars
pltstringPlatelets (Plt), CBC: right. ×10³/µL, e.g. "245". A string of up to 8 characters; non-numeric text such as "<0.1", "pending" or "—" is shown as written and never flagged. Omit it to leave the position blank.
max 8 chars
ptstringProthrombin time (PT), coags: top left. Seconds, e.g. "12.8". A string of up to 8 characters; non-numeric text such as "<0.1", "pending" or "—" is shown as written and never flagged. Omit it to leave the position blank.
max 8 chars
inrstringINR, coags: below the line. e.g. "1.1". A string of up to 8 characters; non-numeric text such as "<0.1", "pending" or "—" is shown as written and never flagged. Omit it to leave the position blank.
max 8 chars
pttstringPartial thromboplastin time (PTT/aPTT), coags: top right. Seconds, e.g. "31". A string of up to 8 characters; non-numeric text such as "<0.1", "pending" or "—" is shown as written and never flagged. Omit it to leave the position blank.
max 8 chars
tpstringTotal protein (TP), LFT: top left. g/dL (US) or g/L (SI), e.g. "7.0". A string of up to 8 characters; non-numeric text such as "<0.1", "pending" or "—" is shown as written and never flagged. Omit it to leave the position blank.
max 8 chars
albstringAlbumin (Alb), LFT: bottom left. g/dL (US) or g/L (SI), e.g. "3.9". A string of up to 8 characters; non-numeric text such as "<0.1", "pending" or "—" is shown as written and never flagged. Omit it to leave the position blank.
max 8 chars
aststringAST, LFT: top middle. U/L, e.g. "32". A string of up to 8 characters; non-numeric text such as "<0.1", "pending" or "—" is shown as written and never flagged. Omit it to leave the position blank.
max 8 chars
altstringALT, LFT: bottom middle. U/L, e.g. "28". A string of up to 8 characters; non-numeric text such as "<0.1", "pending" or "—" is shown as written and never flagged. Omit it to leave the position blank.
max 8 chars
alpstringAlkaline phosphatase (ALP), LFT: bottom right. U/L, e.g. "88". A string of up to 8 characters; non-numeric text such as "<0.1", "pending" or "—" is shown as written and never flagged. Omit it to leave the position blank.
max 8 chars
tbilistringTotal bilirubin (T bili), LFT: top right. mg/dL (US) or µmol/L (SI), e.g. "0.8". A string of up to 8 characters; non-numeric text such as "<0.1", "pending" or "—" is shown as written and never flagged. Omit it to leave the position blank.
max 8 chars
phstringpH, ABG: first. e.g. "7.38". A string of up to 8 characters; non-numeric text such as "<0.1", "pending" or "—" is shown as written and never flagged. Omit it to leave the position blank.
max 8 chars
pco2stringpCO2, ABG: second. mmHg (US) or kPa (SI), e.g. "40". A string of up to 8 characters; non-numeric text such as "<0.1", "pending" or "—" is shown as written and never flagged. Omit it to leave the position blank.
max 8 chars
po2stringpO2, ABG: third. mmHg (US) or kPa (SI), e.g. "92". A string of up to 8 characters; non-numeric text such as "<0.1", "pending" or "—" is shown as written and never flagged. Omit it to leave the position blank.
max 8 chars
castringCalcium (Ca), Ca/Mg/Phos: above the line. mg/dL (US) or mmol/L (SI), e.g. "9.2". A string of up to 8 characters; non-numeric text such as "<0.1", "pending" or "—" is shown as written and never flagged. Omit it to leave the position blank.
max 8 chars
mgstringMagnesium (Mg), Ca/Mg/Phos: bottom left. mg/dL (US) or mmol/L (SI), e.g. "2.0". A string of up to 8 characters; non-numeric text such as "<0.1", "pending" or "—" is shown as written and never flagged. Omit it to leave the position blank.
max 8 chars
phosstringPhosphate (Phos), Ca/Mg/Phos: bottom right. mg/dL (US) or mmol/L (SI), e.g. "3.4". A string of up to 8 characters; non-numeric text such as "<0.1", "pending" or "—" is shown as written and never flagged. Omit it to leave the position blank.
max 8 chars
flagsobjectOptional manual flags that override the automatic ones for single values: { "k": "high" } draws K in red with ↑, "low" in blue with ↓, "normal" removes an automatic flag. Keys are the value keys above.

Endpoints

  • POST /api/render/labfishbone returns image/png; add ?format=svg for SVG.
  • GET /labfishbone.png?d=<payload> and /labfishbone.svg?d=<payload> render a chart from a link. The payload is the JSON body, raw-deflated and base64url-encoded. Nothing is stored: links are permanent and cached for a year.
  • /labfishbone#d=<payload> opens the same chart in the builder for editing.
  • GET /api/render/labfishbone?demo=1 returns the demo chart.
  • GET /api/schema/labfishbone returns the JSON Schema, for code generators and AIs.

Errors and adjustments

Input is lenient where the intent is clear: numeric strings become numbers, out-of-range values are clamped, and unknown fields are ignored. Adjustments are listed in the X-Render-Warnings header. Anything unclear returns a 400 that says how to fix it:

{
  "error": "Invalid payload",
  "issues": [{ "path": "tasks", "message": "must be an array" }],
  "example": { … }
}

Calling from an AI assistant?

Use the hosted MCP server instead. It gives Claude, Cursor and other MCP clients a create_lab_fishbone tool that returns the image plus image, SVG and edit links. See the MCP page →