Docs / Developer tools

Data format tools API

JSON, YAML, TOML, CSV and XML to each other; text and JSON differences; spreadsheets to JSON and back.

Everyday conversions for scripts and pipelines. What you send is never logged.

Base URL https://api.dharun.devNo key needed for most600 units a minute, 3000 with a free keyThis page as Markdown

Convert between data formats

GET/v1/convertPOST

Reads JSON, YAML, TOML, CSV or XML and writes any of them. The input format is guessed when from is not given.

Also takes POST: The document, as text/plain, or JSON {"text": "...", "from": "yaml", "to": "json"}. Send it as text/plain, or as JSON {"text": "..."} with the other options beside it, up to 256 KB.

What you send here is never written to the log, and the answer is not cached.

ParameterDescription
textqueryThe document, for short ones.
fromqueryIts format. Default: guessed. One of: json, yaml, toml, csv, xml.
toqueryDefault json. One of: json, yaml, toml, csv, xml.
rawquerytrue answers with the converted document itself.

curl

curl "https://api.dharun.dev/v1/convert?to=yaml&text=%7B%22name%22%3A%22India%20API%22%2C%22tags%22%3A%5B%22a%22%2C%22b%22%5D%7D&utm_medium=docs"

JavaScript

const response = await fetch("https://api.dharun.dev/v1/convert?to=yaml&text=%7B%22name%22%3A%22India%20API%22%2C%22tags%22%3A%5B%22a%22%2C%22b%22%5D%7D&utm_medium=docs");
const body = await response.json();
if (!response.ok) throw new Error(body.error.message);
console.log(body.data);

Python

import requests

response = requests.get("https://api.dharun.dev/v1/convert?to=yaml&text=%7B%22name%22%3A%22India%20API%22%2C%22tags%22%3A%5B%22a%22%2C%22b%22%5D%7D&utm_medium=docs", timeout=10)
body = response.json()
if not response.ok:
    raise RuntimeError(body["error"]["message"])
print(body["data"])
Try it here

Change the values and send the request from your browser. Needs JavaScript.

Response, with lists and long text shortened

{
  "data": {
    "from": "json",
    "output": "name: India API\ntags:\n  - a\n  - b\n",
    "to": "yaml"
  },
  "meta": {
    "note": "XML elements become keys, repeated ones lists, attributes keys starting with @. CSV rows become objects named by the first line. raw=true answers with the conve…"
  }
}

Compare two texts or JSON documents

POST/v1/diff

Text: a unified patch and counts of added and removed lines. JSON: a list of JSON Patch (RFC 6902) changes with the old values.

Send: JSON: {"a": "...", "b": "...", "mode": "text" or "json", "context": 3, "changes": false}. a and b may be JSON values for mode json.

What you send here is never written to the log, and the answer is not cached.

curl

curl -H "Content-Type: application/json" --data '{"a": "rice\ndal\noil\n", "b": "rice\nmoong dal\noil\nsalt\n"}' "https://api.dharun.dev/v1/diff?utm_medium=docs"

JavaScript

const response = await fetch("https://api.dharun.dev/v1/diff?utm_medium=docs", {
  method: "POST",
  headers: { "Content-Type": "application/json" },
  body: JSON.stringify({"a": "rice\ndal\noil\n", "b": "rice\nmoong dal\noil\nsalt\n"}),
});
const body = await response.json();
if (!response.ok) throw new Error(body.error.message);
console.log(body.data);

Python

import requests

response = requests.post("https://api.dharun.dev/v1/diff?utm_medium=docs", data="{\"a\": \"rice\\ndal\\noil\\n\", \"b\": \"rice\\nmoong dal\\noil\\nsalt\\n\"}", headers={"Content-Type": "application/json"}, timeout=60)
body = response.json()
if not response.ok:
    raise RuntimeError(body["error"]["message"])
print(body["data"])

invoice.json

{"a": "rice\ndal\noil\n", "b": "rice\nmoong dal\noil\nsalt\n"}
Try it here

Change the values and send the request from your browser. Needs JavaScript.

Response

{
  "data": {
    "same": false,
    "added": 2,
    "removed": 1,
    "patch": "--- a\n+++ b\n@@ -1,3 +1,4 @@\n rice\n-dal\n+moong dal\n oil\n+salt\n"
  },
  "meta": {}
}

Spreadsheet to JSON

POST/v1/sheet/to-json

Every sheet of an XLSX workbook (or a CSV file) as records named by the first row. Options go in the query string, or as form fields when the file is sent as multipart/form-data.

Send: An XLSX workbook or a CSV file, up to 10 MB. Post the file as the request body, or as multipart/form-data. Try it with this sample.

What you send here is never written to the log, and the answer is not cached.

ParameterDescription
sheetqueryOnly this sheet.
headerqueryfalse gives rows of values instead of records. Default true.

curl

# a sample to try: https://api.dharun.dev/samples/table.csv
curl -F "[email protected]" "https://api.dharun.dev/v1/sheet/to-json?utm_medium=docs"

JavaScript

// input is an <input type="file"> element
const form = new FormData();
form.append("file", input.files[0]);
const response = await fetch("https://api.dharun.dev/v1/sheet/to-json?utm_medium=docs", { method: "POST", body: form });
const body = await response.json();
if (!response.ok) throw new Error(body.error.message);
console.log(body.data);

Python

import requests

files = [("file", open("table.csv", "rb"))]
response = requests.post("https://api.dharun.dev/v1/sheet/to-json?utm_medium=docs", files=files, timeout=90)
body = response.json()
if not response.ok:
    raise RuntimeError(body["error"]["message"])
print(body["data"])
Try it here

Change the values and send the request from your browser. Needs JavaScript.

Response, with lists and long text shortened

{
  "data": [
    {
      "columns": [
        "pincode",
        "office",
        "district"
      ],
      "name": "Sheet1",
      "records": [
        {
          "district": "Namakkal",
          "office": "Namakkal H.O",
          "pincode": "637001",
          "state": "Tamil Nadu"
        },
        {
          "district": "Chennai",
          "office": "Chennai G.P.O.",
          "pincode": "600001",
          "state": "Tamil Nadu"
        },
        {
          "district": "New Delhi",
          "office": "New Delhi G.P.O.",
          "pincode": "110001",
          "state": "Delhi"
        }
      ],
      "rows": 4
    }
  ],
  "meta": {
    "note": "Cell values as the sheet shows them (formatted). With header=false, rows of values instead of records named by the first row."
  }
}

JSON to a spreadsheet

POST/v1/sheet/from-json

Records in, an XLSX workbook out, with the header row frozen.

Send: JSON: {"records": [{...}]} for one sheet, or {"sheets": [{"name": "...", "records": [...]}, {"name": "...", "values": [[...]]}]}.

The answer returns an XLSX workbook; errors are JSON as everywhere else.

What you send here is never written to the log, and the answer is not cached.

curl

curl -H "Content-Type: application/json" --data '{"records": [{"pincode": "637001", "district": "Namakkal"}, {"pincode": "600001", "district": "Chennai"}]}' -o sheet.xlsx "https://api.dharun.dev/v1/sheet/from-json?utm_medium=docs"

JavaScript

const response = await fetch("https://api.dharun.dev/v1/sheet/from-json?utm_medium=docs", {
  method: "POST",
  headers: { "Content-Type": "application/json" },
  body: "{\"records\": [{\"pincode\": \"637001\", \"district\": \"Namakkal\"}, {\"pincode\": \"600001\", \"district\": \"Chennai\"}]}",
});
if (!response.ok) throw new Error((await response.json()).error.message);
const file = await response.blob();

Python

import requests

response = requests.post("https://api.dharun.dev/v1/sheet/from-json?utm_medium=docs", data="{\"records\": [{\"pincode\": \"637001\", \"district\": \"Namakkal\"}, {\"pincode\": \"600001\", \"district\": \"Chennai\"}]}", headers={"Content-Type": "application/json"}, timeout=60)
if not response.ok:
    raise RuntimeError(response.json()["error"]["message"])
open("sheet.xlsx", "wb").write(response.content)

invoice.json

{"records": [{"pincode": "637001", "district": "Namakkal"}, {"pincode": "600001", "district": "Chennai"}]}
Try it here

Change the values and send the request from your browser. Needs JavaScript.

Using an AI assistant? Connect the MCP server and it can call this API by itself. Want every endpoint on one bench? Open the playground.