JSON to Excel API reference

Base URL: https://api.justapi.tech (alias: https://xlsx.justapi.tech)

MethodPathDescriptionModes
POST /v1/xlsx/generate Generate a spreadsheet sync, async (sync: 5,000 rows)

Native payload

{
  "sheets": [{
    "name": "Report",
    "columns": [
      { "header": "ID", "key": "id", "width": 32 },
      { "header": "Amount", "key": "amount", "format": "$#,##0.00", "type": "number" }
    ],
    "rows": [{ "id": "f477...", "amount": 1520.5 }],
    // SheetStyle is flat, not nested. Every field is optional; the first
    // three default to true.
    "style": {
      "headerBold": true, "headerBackground": "#1F2937", "headerColor": "#FFFFFF",
      "freezeHeader": true, "autofilter": true, "autofit": true
    }
  }],
  "options": { "filename": "report-2026-03.xlsx", "creator": "My App", "allowFormulas": false }
}

filename is also accepted at the root as a convenience for the download name (options.filename wins if both are present). Zebra striping ("zebra": true) is not implemented yet — it is silently ignored rather than documented as if it worked.

Legacy payload (Excelerant-compatible, unchanged)

[{ "name": "This is a Test",
   "cols": [{"header":"ID","id":"id"}],
   "rows": [{"id":"f477...","first_name":"Cornelius"}] }]

Detected by shape (a root array of sheets with cols/rows) and normalized internally. The adapter also tolerates, without losing data or failing: an unwrapped single sheet, an empty first sheet, key/field instead of id, row tuples instead of objects, and a missing sheet name (falls back to SheetN).

Sync vs async

mode defaults to "sync" here — the opposite of every other service — because the legacy array payload has nowhere to put a mode field, and the already-integrated Bubble client expects its 200 with a URL. "mode": "async" gets you the 202 from the shared envelope once the balance is reserved; a webhook is required with it (webhook without mode: "async" is a 400).

Row ceiling: 200,000 in both modes (MAX_SYNC_ROWS, a Worker CPU budget, not a memory one — see docs/10-carga-xlsx.md). Over that, sync returns 400 sync_not_available and async 413 file_too_large. Format ceiling is 1,048,576 rows × 16,384 columns either way.

Example

curl https://api.justapi.tech/v1/xlsx/generate \
  -H "Authorization: Bearer ak_live_..." \
  -H "Content-Type: application/json" \
  -d '{"sheets":[{"name":"Report","columns":[{"header":"ID","key":"id"}],"rows":[{"id":"1"}]}]}'

Full envelope, error catalog and billing rule are the same across every JustAPI service — see the API reference index and error codes.