sheet2sql api

API reference

A simple HTTP endpoint that converts an uploaded Excel workbook into:

  • CSVs of the logical tables extracted from the workbook
  • SQL queries that reproduce the logic of the workbook

Disclaimers

  • This API is currently in early access. We may change the API without notice.
  • Sheet2SQL can make mistakes. Review its outputs carefully before using them.

Quick Start

curl -X POST "https://api.sheet2sql.com/api/extract" \
  -H "x-api-token: $API_TOKEN" \
  -F file=@examples/sales_analysis.xlsx \
  -F filename=sales_analysis.xlsx \
  -F 'config={"generalPrompt":"Format dates as YYYY-MM-DD in all SQL queries."}'

The response is an NDJSON stream. Read it line-by-line until the connection closes. The final line contains the generated CSVs and SQL.

Endpoint

  • URL: /api/extract
  • Method: POST
  • Response: application/x-ndjson stream (one JSON object per line)

Authentication

All requests require an API token.

  • Provide via header x-api-token: <your-token> or Authorization: Bearer <your-token>.
  • Tokens must have remaining quota.
  • Concurrency: one in-flight request per token. A second concurrent request returns 409.

Example:

curl -X POST "https://api.sheet2sql.com/api/extract" \
  -H "x-api-token: $API_TOKEN" \
  -F file=@examples/sales_analysis.xlsx \
  -F filename=sales_analysis.xlsx \
  -F 'config={"generalPrompt":"Format dates as YYYY-MM-DD in all SQL queries."}'

Supported Files

  • Excel: .xlsx only

Limits

Currently, the API will return an error if the workbook exceeds the following limits or contains unsupported features:

  • Maximum file size: 2 MB
  • Maximum sheet count: 10
  • Minimum visible sheets: 1
  • Maximum non-empty cells: 100,000
  • Maximum formula cells: 50,000
  • Maximum formula length: 500 characters
  • Volatile functions present (NOW, TODAY, RAND, RANDBETWEEN, RANDARRAY)
  • External workbook references present

When making an API call, the server will return an error if the workbook exceeds these limits. Please contact us if you need to increase these limits.

Request Formats

Two primary upload styles are supported:

Multipart form-data

POST /api/extract
Content-Type: multipart/form-data; boundary=...

file=<binary excel file>
config=<JSON string>
FieldRequiredNotes
fileYes*Raw Excel file.
filenameNoDisplay name used for artifacts when the upload lacks one.
configNoJSON string (see Config payload).
fileUrlNoHTTPS URL to download the workbook if file is omitted.
Flat fieldsNogeneralPrompt, sheetPrompts are accepted if config is not supplied.

*You may omit file and provide fileUrl instead; the server will fetch the workbook.

JSON (file URL)

POST /api/extract
Content-Type: application/json

{
  "fileUrl": "https://example.com/workbook.xlsx",
  "filename": "workbook.xlsx",
  "config": {
    "generalPrompt": "Format dates as YYYY-MM-DD in all SQL queries.",
    "sheetPrompts": { "Revenue Per Product": "Split the top table into two: Revenue Per Product and Revenue Per Customer." }
  }
}
FieldRequiredNotes
fileUrlYesHTTPS URL to download the workbook.
filenameNoDisplay name used in artifact metadata.
configNoSame schema as multipart.

Config payload

You can specify the following config options:

  • generalPrompt (string): Global instructions (e.g., "Format dates as YYYY-MM-DD in all SQL queries.")
  • sheetPrompts (object): Per-sheet overrides (e.g., { "Revenue Per Product": "Split the top table into two: Revenue Per Product and Revenue Per Customer." })

We recommend making the first request without any generalPrompt or sheetPrompts. This will give you the raw tables and SQL queries as they are generated by the AI agent. You can then review the results and update the generalPrompt or sheetPrompts to refine the results.

Response Stream

The server responds with newline-delimited JSON (NDJSON). Handle each line separately:

  • Status updates
  • { "event": "status", "message": "Excel -> SQL processing started. This can take several minutes depending on file complexity." }
  • { "event": "status", "message": "Computing workbook summary stats..." }
  • Final result
  • { "event": "complete", "filename": "sales_analysis.xlsx", "csvTables": [...], "sqlQueries": [...] }
  • csvTables items have shape:
  • { "kind": "raw" | "full" | "sql_result", "tableName": string, "filename": string, "csv": string }
  • sqlQueries items have shape:
  • { "tableId": string, "queryId": string, "executionOrder": number, "sql": string }
  • Error
  • { "event": "error", "error": "Readable message", "hint": "Optional suggestion" }

csvTables contains CSV strings for the tables extracted. sqlQueries contains SQL text and the order in which to run them.

Status Codes

CodeMeaning
200Request accepted; stream follows.
400Invalid request (missing file, malformed config, etc.).
401Missing API token.
403Invalid or inactive token.
405Method not allowed (only POST).
409Another request already running for this token.
422Workbook failed preflight policy checks.
429Quota exhausted for this token.
500Unexpected server error.

All error responses include application/json bodies when headers have not been flushed yet. Once the NDJSON stream starts, errors are reported via an event: "error" record followed by connection close.

Examples

Multipart upload

curl -X POST "https://api.sheet2sql.com/api/extract" \
  -H "x-api-token: $API_TOKEN" \
  -F file=@examples/sales_analysis.xlsx \
  -F filename=sales_analysis.xlsx \
  -F 'config={"generalPrompt":"Format dates as YYYY-MM-DD in all SQL queries."}'

JSON with fileUrl

curl -X POST "https://api.sheet2sql.com/api/extract" \
  -H "x-api-token: $API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "fileUrl": "https://example.com/sales_analysis.xlsx",
    "filename": "sales_analysis.xlsx",
    "config": { "sheetPrompts": { "Revenue Per Product": "Split the top table into two: Revenue Per Product and Revenue Per Customer." } }
  }'

Notes

  • Processing time depends on workbook size and complexity; very large, very messy or formula-heavy files can take up to 13 minutes.
  • Read the stream until it ends to ensure all results are received.
  • Use HTTPS for fileUrl uploads; HTTP is rejected.