API reference

Lint JSON

Validate JSON strictly and report every lint finding with its position.

GET POST /api/json/lint MCP tool json_lint

Parses input as strict RFC 8259 JSON and runs the lint rules: syntax, duplicate-keys, number-precision, string-encoding, indent-style, indent, trailing-spaces, final-newline, line-endings, byte-order-mark, line-length. Every finding has a rule ID, severity, message, line, column and offset. Invalid JSON is a 200 response with valid: false. Use json_format for the formatted output and statistics.

Browser version (runs locally): JSON Format & Validate.

Try it

Credentials
Remember these credentials

Not saved: you will paste them again next time.

No credentials yet? Get a client ID and secret. They are sent only to this site, in an Authorization: Basic header.

POST /api/json/lint with a JSON body

Parameters

Parameter Type Default Description
input required string (≤ 500000 chars) — JSON text, up to 500,000 characters.
indent 2 | 4 | tab | none 2 Expected indentation unit for the indent rule.
max_line_length integer (0–10000) 120 Limit for the line-length rule; 0 disables it.

Also accepted on every endpoint: format (json | text). Parameters may come from the query string, a JSON object body, an urlencoded or multipart form, or (for input) a text/plain body.

Global parameters
Parameter Type Default Description
format json | text json json returns the documented object. text returns only the primary value as text/plain (see "Text output").

Response 200 application/json

Field Type Description
valid boolean No error findings.
summary object
summary.valid boolean True when there are no error findings.
summary.errors integer Number of errors.
summary.warnings integer Number of warnings.
summary.infos integer Number of informational findings.
diagnostics array of object Findings in document order.
diagnostics[].rule string Rule ID, e.g. syntax, duplicate-keys, trailing-spaces.
diagnostics[].severity "error" | "warning" | "info" error makes the document invalid; warning and info are style.
diagnostics[].message string What is wrong and how to fix it.
diagnostics[].line integer 1-based line where the problem starts.
diagnostics[].column integer 1-based column (Unicode code points).
diagnostics[].offset integer 0-based UTF-16 offset into the input.
diagnostics[].endLine optional integer 1-based end line, when the problem spans a range.
diagnostics[].endColumn optional integer 1-based end column.
diagnostics[].endOffset optional integer 0-based end offset.

Errors

Errors are JSON: {"error": "<message>", "code": "<code>", "param": "<name>"?}.

Status Code When
400 missing_parameter A required parameter is absent.
400 unknown_parameter A parameter name is not in the table above (typos are rejected, not ignored).
400 invalid_parameter A value has the wrong type, is out of range, or is not an allowed value.
413 payload_too_large The request body exceeds 1 MiB.
405 method_not_allowed A method other than GET, POST or OPTIONS.

Behaviour

  • Idempotent: the same arguments always return the same result.
  • Requires a client ID and secret (authentication). Each call is recorded as one metadata row against your client ID; inputs and outputs are never stored or logged. Responses carry cache-control: no-store.
  • CORS: any origin may call this endpoint from a browser, using your credentials.

Examples

Responses below were produced by running each request through this code at build time. Long strings are shortened.

Duplicate key and a trailing space

curl -X POST 'https://util.caruana.me/api/json/lint' \
  -H 'content-type: application/json' \
  -d '{"input":"{\n  \"id\": 1,\n  \"id\": 2 \n}\n"}'

Response 200

{
  "valid": false,
  "summary": {
    "valid": false,
    "errors": 1,
    "warnings": 1,
    "infos": 0
  },
  "diagnostics": [
    {
      "rule": "duplicate-keys",
      "severity": "error",
      "message": "Duplicate key \"id\" at /id (first defined at line 2, column 3). Only the last value survives JSON.parse.",
      "line": 3,
      "column": 3,
      "offset": 15
    },
    {
      "rule": "trailing-spaces",
      "severity": "warning",
      "message": "Trailing whitespace.",
      "line": 3,
      "column": 10,
      "offset": 22,
      "endLine": 3,
      "endColumn": 11,
      "endOffset": 23
    }
  ]
}
Same call as an MCP tools/call
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "json_lint",
    "arguments": {
      "input": "{\n  \"id\": 1,\n  \"id\": 2 \n}\n"
    }
  }
}

Syntax error

curl -X POST 'https://util.caruana.me/api/json/lint' \
  -H 'content-type: application/json' \
  -d '{"input":"{\"a\": [1, 2,]}"}'

Response 200

{
  "valid": false,
  "summary": {
    "valid": false,
    "errors": 1,
    "warnings": 1,
    "infos": 0
  },
  "diagnostics": [
    {
      "rule": "syntax",
      "severity": "error",
      "message": "Trailing comma before \"]\": JSON does not allow a comma after the last element. Remove it.",
      "line": 1,
      "column": 13,
      "offset": 12
    },
    {
      "rule": "final-newline",
      "severity": "warning",
      "message": "Missing line break at the end of the text.",
      "line": 1,
      "column": 15,
      "offset": 14
    }
  ]
}
Same call as an MCP tools/call
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "json_lint",
    "arguments": {
      "input": "{\"a\": [1, 2,]}"
    }
  }
}