API & MCP
Downloads API
The downloads endpoints export a query result to a file (CSV, JSON, or Parquet) and give you a link to fetch it. Unlike the 1,000-row cap on live queries, a download can be any size — it streams the full result straight to object storage. This is the API behind the app's Downloads & exports.
Create a download — POST /downloads#
The one surprise: create is a streamed connection, not a fire-and-forget id. You POST the request and hold the connection open; the server reports progress as Server-Sent Events and delivers the finished download link in the final event.
curl -N -X POST "https://<your-gopie-host>/v1/api/downloads" \
-H "Authorization: Bearer gp_pub_…" \
-H "Content-Type: application/json" \
-d '{
"dataset_id": "gp_DzuutVJef9rSG",
"sql": "SELECT * FROM gp_DzuutVJef9rSG WHERE region = '\''West'\''",
"format": "csv"
}'| Body field | Required | Meaning |
|---|---|---|
dataset_id | yes | the dataset UUID or its gp_… table name (either works) |
sql | yes | the read-only SQL to export |
format | yes | csv, json, or parquet |
snapshot_version | no | export a past version |
The stream is a sequence of data: events. Progress arrives as status_update, a heartbeat fires every 15 seconds so the connection stays alive, and the terminal complete event carries the presigned download URL in its message:
data: {"event":"status_update","message":"Processing query..."}
data: {"event":"status_update","message":"Executing data export to S3..."}
data: {"event":"complete","message":"https://<storage>/…/export.csv?signature=…"}Fetch that URL to get the file. It expires 24 hours after creation. If a failure occurs mid-export it arrives as an error event rather than an HTTP status code — the connection had already upgraded to a stream.
NoteIdentical requests are deduplicated. If you ask for the same
(dataset, SQL, format, version)you exported recently and the data hasn't changed, thecompleteevent returns the existing link immediately instead of re-running the query.
List your downloads — GET /downloads#
Returns your recent downloads (a bare JSON array, newest paged by limit/offset):
[
{
"id": "550e8400-…",
"sql": "SELECT * FROM gp_DzuutVJef9rSG WHERE region = 'West'",
"dataset_id": "…", "status": "completed", "format": "csv",
"pre_signed_url": "https://<storage>/…/export.csv?signature=…",
"expires_at": "2026-07-05T…", "completed_at": "2026-07-04T…"
}
]status is one of pending, processing, completed, or failed. The pre_signed_url and expires_at are populated once a download completes.
Get or delete one — GET / DELETE /downloads/{id}#
GET /downloads/{id} returns a single download record by its UUID — handy for re-fetching a still-valid link. DELETE /downloads/{id} removes the record and returns 204 No Content.