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-ndjsonstream (one JSON object per line)
Authentication
All requests require an API token.
- Provide via header
x-api-token: <your-token>orAuthorization: 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:
.xlsxonly
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>| Field | Required | Notes |
|---|---|---|
| file | Yes* | Raw Excel file. |
| filename | No | Display name used for artifacts when the upload lacks one. |
| config | No | JSON string (see Config payload). |
| fileUrl | No | HTTPS URL to download the workbook if file is omitted. |
| Flat fields | No | generalPrompt, 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." }
}
}| Field | Required | Notes |
|---|---|---|
| fileUrl | Yes | HTTPS URL to download the workbook. |
| filename | No | Display name used in artifact metadata. |
| config | No | Same 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": [...] }csvTablesitems have shape:{ "kind": "raw" | "full" | "sql_result", "tableName": string, "filename": string, "csv": string }sqlQueriesitems 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
| Code | Meaning |
|---|---|
| 200 | Request accepted; stream follows. |
| 400 | Invalid request (missing file, malformed config, etc.). |
| 401 | Missing API token. |
| 403 | Invalid or inactive token. |
| 405 | Method not allowed (only POST). |
| 409 | Another request already running for this token. |
| 422 | Workbook failed preflight policy checks. |
| 429 | Quota exhausted for this token. |
| 500 | Unexpected 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
fileUrluploads; HTTP is rejected.