# Validate diagram

> Page: https://docs.plotwork.dev/api/post-v1-diagrams-validate. Index of every page: https://docs.plotwork.dev/llms.txt

Check diagram source.

`POST /v1/diagrams/validate`

## TL;DR

| Question | Answer |
|---|---|
| What does it do? | Check diagram source. |
| Which tool does the same? | [`validate_diagram`](https://docs.plotwork.dev/mcp/tools/validate-diagram.md) |
| What does it take? | A JSON body of type [`DiagramSourceInput`](https://docs.plotwork.dev/api/schemas.md#diagramsourceinput). |
| What does it return? | Status 200 with a body of type [`ValidateResponse`](https://docs.plotwork.dev/api/schemas.md#validateresponse). |
| What can go wrong? | `400` the body failed schema validation; `401` the api key is missing or not valid; `403` the account is on the free plan, which does not include the rest drawing and checking routes (plan.rest_not_included); `413` the body is larger than the size cap; `429` too many requests. Every failure uses the one error envelope. |

## What it does

Parses the source and returns every error found in one pass, each with a line, column, and fix hint, plus quality warnings for a valid diagram. Invalid source is a normal 200 result with valid false, so callers can loop until it is valid. Nothing is rendered.

## Request body

The body has the type [`DiagramSourceInput`](https://docs.plotwork.dev/api/schemas.md#diagramsourceinput).

| Field | Type | Required | Description |
|---|---|---|---|
| `source` | `string` | yes | Diagram source; the first line is the header, such as flow "Title" (draw_diagram lists every kind). at least 1 character; at most 50000 characters. |
| `settings` | `object` | no | The repo's plotwork.config.json, if any. Schema: https://docs.plotwork.dev/schemas/plotwork.config.json. |

## Responses

| Status | Meaning | Body |
|---|---|---|
| 200 | Validation result. | [`ValidateResponse`](https://docs.plotwork.dev/api/schemas.md#validateresponse) |
| 400 | The body failed schema validation. | [`ErrorResponse`](https://docs.plotwork.dev/api/schemas.md#errorresponse) |
| 401 | The API key is missing or not valid. | [`ErrorResponse`](https://docs.plotwork.dev/api/schemas.md#errorresponse) |
| 403 | The account is on the Free plan, which does not include the REST drawing and checking routes (plan.rest_not_included). | [`ErrorResponse`](https://docs.plotwork.dev/api/schemas.md#errorresponse) |
| 413 | The body is larger than the size cap. | [`ErrorResponse`](https://docs.plotwork.dev/api/schemas.md#errorresponse) |
| 429 | Too many requests. | [`ErrorResponse`](https://docs.plotwork.dev/api/schemas.md#errorresponse) |

## Response body

A 200 answer has the type [`ValidateResponse`](https://docs.plotwork.dev/api/schemas.md#validateresponse).

| Field | Type | Required | Description |
|---|---|---|---|
| `valid` | `boolean` | yes | True when there are no errors; warnings do not make a diagram invalid. |
| `kind` | `string \| null` | yes | The diagram kind, or null when the header could not be read. |
| `errors` | `Diagnostic[]` | yes | Every error found in one pass, so they can be fixed together. |
| `errors[].code` | `"E100" \| "E101" \| "E110" \| "E111" \| "E120" \| "E121" \| "E122" \| "E123" \| "E124" \| "E125" \| "E130" \| "E131" \| "E132" \| "E133" \| "E134" \| "E135" \| "E136" \| "E137" \| "E138" \| "E139" \| "E140" \| "W200" \| "W201" \| "W202" \| "W203" \| "W204" \| "W205" \| "W206" \| "W207" \| "W500" \| "M100" \| "M101" \| "M102" \| "M103" \| "M104" \| "M110" \| "M200" \| "M201" \| "M202" \| "M203" \| "M204" \| "M205" \| "M206" \| "M207" \| "M208" \| "M209" \| "M210" \| "M211" \| "M212" \| "M213" \| "M214" \| "M215" \| "M216" \| "M217" \| "M218" \| "E300" \| "E301" \| "E302" \| "E303" \| "E304" \| "W300" \| "W301" \| "W302" \| "W303" \| "M120" \| "M220" \| "M221" \| "M222" \| "E340" \| "E341" \| "E342" \| "E343" \| "E344" \| "E345" \| "W320" \| "W321" \| "W322" \| "W323" \| "M240" \| "M241" \| "M242" \| "E360" \| "E361" \| "E362" \| "E363" \| "E364" \| "E365" \| "E366" \| "E367" \| "W330" \| "W331" \| "W332" \| "W333" \| "W334" \| "M250" \| "M251" \| "E400" \| "E401" \| "E402" \| "E403" \| "W350" \| "W351" \| "W352" \| "W353" \| "M270" \| "M271" \| "E420" \| "E421" \| "E422" \| "E423" \| "E424" \| "W360" \| "W361" \| "W362" \| "W363" \| "W364" \| "M180" \| "M280" \| "M281" \| "M282" \| "E320" \| "E321" \| "E322" \| "E323" \| "E324" \| "E325" \| "E326" \| "E327" \| "E328" \| "E329" \| "E330" \| "W310" \| "W311" \| "W312" \| "W313" \| "W314" \| "M130" \| "M131" \| "M132" \| "M230" \| "M231" \| "M232" \| "M233" \| "M234" \| "M235" \| "M236" \| "M237" \| "M238" \| "E380" \| "E381" \| "E382" \| "E383" \| "W340" \| "W341" \| "W342" \| "W343" \| "M260" \| "I100" \| "I101" \| "I102" \| "I103" \| "I104" \| "I105" \| "I200" \| "I201" \| "I202" \| "I203" \| "I204" \| "I206" \| "R100" \| "R101" \| "R200" \| "R201" \| "R202" \| "R203" \| "R204" \| "R205" \| "R206" \| "R207" \| "S100" \| "S200" \| "S101" \| "S102" \| "S103" \| "S104" \| "S201" \| "S202" \| "S203"` | yes | Stable code to branch on; E-codes are errors, W-codes are warnings. |
| `errors[].severity` | `"error" \| "warning"` | yes | Errors stop rendering; warnings never do. |
| `errors[].message` | `string` | yes | What is wrong, in one sentence. |
| `errors[].line` | `integer` | yes | 1-based line in the submitted source. minimum 1. |
| `errors[].column` | `integer` | yes | 1-based column in that line. minimum 1. |
| `errors[].length` | `integer` | yes | Number of characters the problem covers. minimum 1. |
| `errors[].hint` | `string \| null` | yes | A concrete suggestion for fixing it, or null. |
| `warnings` | `Diagnostic[]` | yes | Quality warnings for a valid diagram, such as too dense or too wide. |
| `warnings[].code` | `"E100" \| "E101" \| "E110" \| "E111" \| "E120" \| "E121" \| "E122" \| "E123" \| "E124" \| "E125" \| "E130" \| "E131" \| "E132" \| "E133" \| "E134" \| "E135" \| "E136" \| "E137" \| "E138" \| "E139" \| "E140" \| "W200" \| "W201" \| "W202" \| "W203" \| "W204" \| "W205" \| "W206" \| "W207" \| "W500" \| "M100" \| "M101" \| "M102" \| "M103" \| "M104" \| "M110" \| "M200" \| "M201" \| "M202" \| "M203" \| "M204" \| "M205" \| "M206" \| "M207" \| "M208" \| "M209" \| "M210" \| "M211" \| "M212" \| "M213" \| "M214" \| "M215" \| "M216" \| "M217" \| "M218" \| "E300" \| "E301" \| "E302" \| "E303" \| "E304" \| "W300" \| "W301" \| "W302" \| "W303" \| "M120" \| "M220" \| "M221" \| "M222" \| "E340" \| "E341" \| "E342" \| "E343" \| "E344" \| "E345" \| "W320" \| "W321" \| "W322" \| "W323" \| "M240" \| "M241" \| "M242" \| "E360" \| "E361" \| "E362" \| "E363" \| "E364" \| "E365" \| "E366" \| "E367" \| "W330" \| "W331" \| "W332" \| "W333" \| "W334" \| "M250" \| "M251" \| "E400" \| "E401" \| "E402" \| "E403" \| "W350" \| "W351" \| "W352" \| "W353" \| "M270" \| "M271" \| "E420" \| "E421" \| "E422" \| "E423" \| "E424" \| "W360" \| "W361" \| "W362" \| "W363" \| "W364" \| "M180" \| "M280" \| "M281" \| "M282" \| "E320" \| "E321" \| "E322" \| "E323" \| "E324" \| "E325" \| "E326" \| "E327" \| "E328" \| "E329" \| "E330" \| "W310" \| "W311" \| "W312" \| "W313" \| "W314" \| "M130" \| "M131" \| "M132" \| "M230" \| "M231" \| "M232" \| "M233" \| "M234" \| "M235" \| "M236" \| "M237" \| "M238" \| "E380" \| "E381" \| "E382" \| "E383" \| "W340" \| "W341" \| "W342" \| "W343" \| "M260" \| "I100" \| "I101" \| "I102" \| "I103" \| "I104" \| "I105" \| "I200" \| "I201" \| "I202" \| "I203" \| "I204" \| "I206" \| "R100" \| "R101" \| "R200" \| "R201" \| "R202" \| "R203" \| "R204" \| "R205" \| "R206" \| "R207" \| "S100" \| "S200" \| "S101" \| "S102" \| "S103" \| "S104" \| "S201" \| "S202" \| "S203"` | yes | Stable code to branch on; E-codes are errors, W-codes are warnings. |
| `warnings[].severity` | `"error" \| "warning"` | yes | Errors stop rendering; warnings never do. |
| `warnings[].message` | `string` | yes | What is wrong, in one sentence. |
| `warnings[].line` | `integer` | yes | 1-based line in the submitted source. minimum 1. |
| `warnings[].column` | `integer` | yes | 1-based column in that line. minimum 1. |
| `warnings[].length` | `integer` | yes | Number of characters the problem covers. minimum 1. |
| `warnings[].hint` | `string \| null` | yes | A concrete suggestion for fixing it, or null. |
| `summary` | `string \| null` | yes | One-line description of the diagram, or null when invalid. |
| `size` | `object \| null` | yes | Natural rendered size, or null when invalid. |
| `size.width` | `integer` | yes | Width in px. minimum 1. |
| `size.height` | `integer` | yes | Height in px. minimum 1. |
| `quality` | `object` | no | How clean the laid-out diagram looks, with up to three changes; absent when invalid. |
| `quality.score` | `integer` | yes | 0 to 100; 100 is a picture with nothing to fix. The same diagram always gets the same score. minimum 0; maximum 100. |
| `quality.grade` | `"clean" \| "fair" \| "cluttered"` | yes | clean is 85 or more, fair 60 or more, cluttered below. |
| `quality.measures` | `object` | yes | What the score is made from: crossings, lineOverBox, labelOverlaps, smallestTextPx (in an 880px column), aspectRatio, emptySpace (0 to 1), longestLine (px), detour (1 is straight), the counts of boxes, lines, labels, series, and slices, and any measure the kind adds. |
| `quality.hints` | `string[]` | yes | Up to three changes, the one worth most first, each naming the statement or option to edit. |
| `quality.line` | `string` | yes | The grade, the score, and the first hint in one line. |
| `notices` | `Note[]` | no | Information notes, such as an icon alias resolved to a real icon; absent when there is none. |
| `notices[].code` | `string` | yes | A stable code, such as I122 for an icon alias. |
| `notices[].severity` | `"info"` | yes | A note never stops a drawing and is not a warning. |
| `notices[].message` | `string` | yes |  |
| `notices[].line` | `integer` | yes | minimum 1. |
| `notices[].column` | `integer` | yes | minimum 1. |
| `notices[].length` | `integer` | yes | minimum 1. |
| `notices[].hint` | `string \| null` | yes | The text to write instead. |

## See also

| Doc | Why |
|---|---|
| [API reference](https://docs.plotwork.dev/api/reference.md) | Every endpoint, and the error envelope |
| [Schemas](https://docs.plotwork.dev/api/schemas.md) | Every request and response type |
| [`validate_diagram`](https://docs.plotwork.dev/mcp/tools/validate-diagram.md) | The same operation as an MCP tool |
| [Tool reference](https://docs.plotwork.dev/mcp/tools.md) | The operations as callable tools |
