Documentation

JSONSheet API Documentation

Convert any public Excel or Google‑Sheet link into clean JSON.
Perfect for dashboards, automation workflows and backend jobs.

Overview

JSONSheet is a stateless, open-source web API. It streams an .xlsx file from a public URL, parses every worksheet and returns typed JSON. No temp storage, no spreadsheet SDKs, no vendor lock-in.

Key Features

  • Latency < 200 ms for small workbooks
  • AI-assisted cleanup (headers, dates, currency)
  • Blank-row & duplicate-row removal
  • Per-IP rate-limiting + HSTS (edge-terminated)
  • Runs anywhere via Docker

How It Works

  1. Upload Excel to Google Drive, Dropbox.
  2. Create a public-view link.
  3. POST that link to JSONSheet.
  4. Receive structured JSON instantly.

Base URL

https://jsonsheet.com

Endpoints

MethodPathDescription
GET/api/v1/jsonsheet/versionHealth-check – returns semantic version + UTC time
POST/api/v1/jsonsheet/converterParse workbook → JSON (no cleanup, fastest)
/api/v1/jsonsheet/converter?cleanup=trueParse + normalise headers, dates, currency
/api/v1/jsonsheet/converter?cleanup=true&removeBlankRows=true&removeDuplicateRows=trueFull cleanup + blank / duplicate-row filters

Request Payload

Content-Type: application/json

{
  "url": "https://docs.google.com/spreadsheets/d/<FILE_ID>/export?format=xlsx"
}

Query Parameters

ParameterTypeDefaultDescription
cleanupboolfalseEnable AI cleanup pipeline
fixHeadersbooltrueSnake-case, trim & deduplicate header row
normDatesbooltrueConvert 60+ date formats → ISO 8601
normCurrencybooltrueStrip currency symbols & thousand seps
removeBlankRowsboolfalseDrop rows where all cells are empty
removeDuplicateRowsboolfalseHash-compare rows; remove dupes

Typical Response

{
  "tables": [
    {
      "sheetName": "Sample",
      "rows": [
        { "id": "1", "name": "Alice" },
        { "id": "2", "name": "Bob"   }
      ]
    }
  ]
}

Supported Source Links

  • Google Sheets export (…/export?format=xlsx)
  • Google Drive file links (public)
  • Dropbox (?dl=0 or ?raw=1)
  • Any HTTPS URL (e.g. S3 presigned link)
  • OneDrive – planned Q3 2025

Rate Limits

  • 100 requests / minute / IP (free tier)
  • 5 000 requests / day / IP
  • Higher throughput? Contact us

Error Responses

StatusMessageReason & Resolution
400Invalid or missing URLBody must include a public .xlsx link
413File too large (10 MB)Split workbook or compress content
429Too Many RequestsRate-limit exceeded – retry ≤ 60 s
500Could not parse filePassword protected or malformed workbook

Quick-Start Code Snippets

Shell (cURL)

curl -X POST \
  https://api.jsonsheet.com/api/v1/jsonsheet/converter?cleanup=true \
  -H "Content-Type: application/json" \
  -d '{"url":"https://docs.google.com/spreadsheets/d/FILE_ID/export?format=xlsx"}'

JavaScript (Fetch API)

fetch("https://api.jsonsheet.com/api/v1/jsonsheet/converter?cleanup=true", {
  method: "POST",
  headers: {"Content-Type": "application/json"},
  body: JSON.stringify({ url: excelLink })
}).then(r => r.json()).then(console.log);

Next.js (API Route)

// pages/api/convert.js
export default async function handler(req, res) {
  const response = await fetch(
    "https://api.jsonsheet.com/api/v1/jsonsheet/converter?cleanup=true",
    {
      method: "POST",
      headers: {"Content-Type": "application/json"},
      body: JSON.stringify({ url: req.body.url })
    });
  res.status(200).json(await response.json());
}

Python (requests)

import requests, json, pprint
payload = {"url":
  "https://docs.google.com/spreadsheets/d/FILE_ID/export?format=xlsx"}
r = requests.post(
  "https://api.jsonsheet.com/api/v1/jsonsheet/converter?cleanup=true",
  json=payload, timeout=30)
pprint.pprint(r.json())

ASP.NET (C# HttpClient)

using var client = new HttpClient();
var body = new StringContent(
  JsonSerializer.Serialize(new { url = link }),
  Encoding.UTF8, "application/json");

var resp = await client.PostAsync(
  "https://api.jsonsheet.com/api/v1/jsonsheet/converter?cleanup=true",
  body);
var json = await resp.Content.ReadAsStringAsync();

Java 17 (HttpClient)

HttpClient http = HttpClient.newHttpClient();
String json = """
{ "url": "https://docs..." }""";
HttpRequest req = HttpRequest.newBuilder()
    .uri(URI.create("https://api.jsonsheet.com/api/v1/jsonsheet/converter?cleanup=true"))
    .header("Content-Type", "application/json")
    .POST(HttpRequest.BodyPublishers.ofString(json))
    .build();
String out = http.send(req, BodyHandlers.ofString()).body();

Go

payload := map[string]string{"url":"https://docs..."}
buf, _ := json.Marshal(payload)
req, _ := http.NewRequest("POST",
  "https://api.jsonsheet.com/api/v1/jsonsheet/converter?cleanup=true",
  bytes.NewReader(buf))
req.Header.Set("Content-Type", "application/json")
client := &http.Client{}
res, _ := client.Do(req)

Integration Scenarios

Frontend — Angular 16 +

// app.component.html
<form [formGroup]="fg" (ngSubmit)="submit()" class="row gap-2 align-items-center">
  <input class="form-control flex-grow-1"
         formControlName="url"
         placeholder="Public Excel link (.xlsx or G-Sheets export)"
         required />
  <button class="btn btn-primary" type="submit">Fetch JSON</button>
</form>

// app.component.ts
export class AppComponent {
    fg = this.fb.group({ url: [''] });

  constructor(private fb: FormBuilder,
              private http: HttpClient) {}

  submit() {
    if (this.fg.invalid) return;

    const body = { url: this.fg.value.url };
    this.http.post(
      'https://api.jsonsheet.com/api/v1/jsonsheet/converter?cleanup=true&removeBlankRows=true',
      body
    ).subscribe(console.log);
  }
}

Frontend — React 18 +

import { useState } from 'react';

export default function Converter() {
    const [url, setUrl] = useState('');
    const [result, setResult] = useState(null);

    async function handleSubmit(e) {
    e.preventDefault();
    const res = await fetch(
      'https://api.jsonsheet.com/api/v1/jsonsheet/converter?cleanup=true',
      {
        method: 'POST',
        headers: {'Content-Type': 'application/json'},
        body: JSON.stringify({ url })
      }
    );
    setResult(await res.json());
  }

  return (
    <>
      <form onSubmit={handleSubmit}>
        <input value={url}
               onChange={e => setUrl(e.target.value)}
               placeholder="Excel link" required />
        <button>Fetch</button>
      </form>
      <pre>{result && JSON.stringify(result, null, 2)}</pre>
    </>
  );
}

No-Code Automation (Zapier)

  1. Trigger • file uploaded to Dropbox.
  2. Zapier Webhook → …/converter?cleanup=true.
  3. Parse JSON → Airtable / Google Sheets / email.

FAQ

  • Production-ready? Yes, the API is stateless and containerised.
  • Do you store data? No. Files are streamed, parsed, then deleted.
  • Max workbook size? 10 MB on free tier (higher on request).
  • Cold start? After 15 min idle the first request may take ≈ 50 s.

Roadmap 2025

v1.0 delivers sheet-to-JSON conversion with optional AI cleanup.
Upcoming: Data-viz dashboards, scheduled PDF/CSV export, webhook push notifications.