jsonnorm / developer API

Anonymous endpoint · JSON in, CSV out

Developer API · v1

Move JSON into deterministic CSV pipelines.

Send JSON or NDJSON to the same loss-aware normalization service behind the jsonnorm converter. Get a CSV response or compact conversion metadata, with stable fields, explicit errors, and no account setup.

Endpoint

Post one JSON document, NDJSON stream, or multipart file upload. jsonnorm detects null and missing fields separately, but the default CSV representation renders both as empty cells. The default plan discovers a union schema, preserves field order deterministically, and writes standards-compliant CSV.

POST https://jsonnorm.com/api/v1/convert
Content-Type: application/json

[{"id":1,"name":"Ada"}]

The endpoint accepts JSON, NDJSON, or a multipart file upload. Add ?response=metadata to receive JSON with row, column, input, and output counts instead of the CSV body.

Quickstarts

curl

output="$(mktemp)"
if curl --fail-with-body --silent --show-error \
  -X POST https://jsonnorm.com/api/v1/convert \
  -H 'Content-Type: application/json' \
  --data-binary @orders.json \
  --output "$output"; then
  mv "$output" orders.csv
else
  cat "$output" >&2
  rm -f "$output"
  exit 1
fi

curl · NDJSON

curl --fail-with-body --silent --show-error \
  -X POST https://jsonnorm.com/api/v1/convert \
  -H 'Content-Type: application/x-ndjson' \
  --data-binary @orders.ndjson

curl · multipart file

curl --fail-with-body --silent --show-error \
  -X POST https://jsonnorm.com/api/v1/convert \
  -F '[email protected];type=application/json'

curl · metadata

curl --fail-with-body --silent --show-error \
  -X POST 'https://jsonnorm.com/api/v1/convert?response=metadata' \
  -H 'Content-Type: application/json' \
  --data-binary @orders.json

Python

import requests

with open("orders.json", "rb") as source, open("orders.csv", "wb") as target:
    with requests.post(
        "https://jsonnorm.com/api/v1/convert",
        headers={"Content-Type": "application/json"},
        data=source,
        stream=True,
    ) as response:
        response.raise_for_status()
        for chunk in response.iter_content(chunk_size=1024 * 1024):
            if chunk:
                target.write(chunk)

Node.js / TypeScript

import { createWriteStream } from "node:fs";
import { readFile } from "node:fs/promises";
import { Readable } from "node:stream";
import { pipeline } from "node:stream/promises";

const response = await fetch("https://jsonnorm.com/api/v1/convert", {
  method: "POST",
  headers: { "Content-Type": "application/json" },
  body: await readFile("orders.json"),
});
if (!response.ok) throw new Error(response.status + ": " + await response.text());
if (!response.body) throw new Error("The API returned no response body.");
await pipeline(
  Readable.fromWeb(response.body),
  createWriteStream("orders.csv"),
);

PowerShell 7

Invoke-WebRequest -Uri 'https://jsonnorm.com/api/v1/convert' -Method Post -ContentType 'application/json' -InFile .\orders.json -OutFile .\orders.csv
Invoke-RestMethod -Uri 'https://jsonnorm.com/api/v1/convert?response=metadata' -Method Post -ContentType 'application/json' -InFile .\orders.json

Fair-use limits

Automated abuse protection, fair-use limits, input and output budgets, and concurrency safeguards apply to every request. If you reach a limit, the API returns 429 with a Retry-After value. These safeguards protect availability and keep retries from becoming an accidental request storm.

Plan for bounded requests and retry with backoff.

If the service is temporarily unavailable, retry after the Retry-After delay and use backoff.

Errors

Failures use a JSON envelope with error.code, error.message, and an optional privacy-safe warning.

StatusCodesMeaning
400JSON_PARSE_ERROR, TOKEN_TOO_LARGE, KEY_TOO_LARGE, DEPTH_LIMIT_EXCEEDED, COLUMN_LIMIT_EXCEEDED, ROW_LIMIT_EXCEEDED, GENERATED_CELL_LIMIT_EXCEEDED, PLAN_VALIDATION_ERROR, or INVALID_INPUTThe JSON/NDJSON content or conversion options are invalid.
408DEADLINE_EXCEEDEDThe bounded conversion deadline elapsed.
413INPUT_TOO_LARGE or OUTPUT_LIMIT_EXCEEDEDThe input or generated CSV exceeds a bounded size.
415UNSUPPORTED_MEDIA_TYPEUse application/json, application/x-ndjson, or multipart/form-data.
429RATE_LIMITED or CONCURRENCY_LIMIT_EXCEEDEDA fair-use or concurrency safeguard asked you to wait.
500INTERNAL_ERRORAn unexpected failure occurred. Retry later.
503SERVICE_UNAVAILABLEThe service is temporarily busy. Retry after the delay in Retry-After.

Privacy by default

Request payloads are processed temporarily. jsonnorm keeps no conversion history and does not log payload contents or CSV output.