Skip to main content
The Firebolt HTTP API accepts multipart/form-data POST requests that carry a SQL statement together with one or more files (Parquet, CSV, …). The statement reads each file with the upload:// URL scheme through table-valued functions such as READ_PARQUET, READ_CSV, READ_AVRO, and READ_TEXT. This lets you query a file on your machine, or load it into a table, without staging it in Amazon S3 first. Uploaded files exist on the engine’s local disk only while the request runs and are deleted when it finishes. Nothing is persisted unless the statement writes the data, for example with INSERT INTO ... SELECT.

Request format

Send a POST request with a Content-Type of multipart/form-data to an engine, authenticated like any other API request. The request must contain:
  • Exactly one part with the name directive set to sql, holding the SQL statement in UTF-8.
  • Any number of file parts. Each file part needs a filename directive (the value is ignored) and a name directive that matches the regex [_0-9a-zA-Z.-]+ and is unique within the request. The SQL statement references the part as upload://<name>.
With curl, --form "sql=<statement>" produces the statement part and --form "<name>=@<path>" produces a file part.

Query an uploaded file

curl "https://<user engine URL>?database=<database>" \
  --header 'Authorization: Bearer <access token>' \
  --form "sql=SELECT * FROM READ_PARQUET('upload://my_file')" \
  --form "my_file=@./sales.parquet"
The statement references the part name (my_file), not the local file name (sales.parquet). The upload:// URL must match a part name exactly; glob patterns are not supported.

Upload multiple files

A statement can reference any number of uploaded files, each by its own part name:
curl "https://<user engine URL>?database=<database>" \
  --header 'Authorization: Bearer <access token>' \
  --form "sql=SELECT * FROM READ_PARQUET('upload://my_sales') CROSS JOIN READ_CSV('upload://my_targets', HEADER => TRUE, INFER_SCHEMA => TRUE)" \
  --form "my_sales=@./sales.parquet" \
  --form "my_targets=@./targets.csv"

Load an uploaded file into a table

The upload:// scheme works only in read table-valued functions. COPY FROM and external tables reject it. To persist uploaded data, insert the function’s result into a table:
curl "https://<user engine URL>?database=<database>" \
  --header 'Authorization: Bearer <access token>' \
  --form "sql=INSERT INTO sales SELECT * FROM READ_PARQUET('upload://my_sales')" \
  --form "my_sales=@./sales.parquet"

Compress parts

To reduce transfer size, compress individual parts and declare the codec with a per-part Content-Encoding header. The engine decompresses each part on arrival. Supported encodings are gzip, deflate, br, xz, zstd, lz4, and snappy. Both file parts and the sql part can be compressed.
gzip targets.csv
curl "https://<user engine URL>?database=<database>" \
  --header 'Authorization: Bearer <access token>' \
  --form "sql=SELECT * FROM READ_CSV('upload://targets', HEADER => TRUE, INFER_SCHEMA => TRUE)" \
  --form "targets=@./targets.csv.gz;headers=Content-Encoding: gzip"
A top-level Content-Encoding header on the request is rejected; compress per part instead.

Limits

  • The file parts of one request can hold at most 1 GB of data in total, measured after decompression.