Skip to content

Files API

The Files API enables file upload, download, and management for data analysis workflows. Files can be used as data sources, exported as analysis outputs, or shared via share links.

https://api.querri.com/api

All Files API endpoints require JWT authentication, except when accessing via share tokens. See Authentication for details.

Querri supports multiple storage backends:

BackendDescriptionConfiguration
LOCALLocal filesystem storageDefault for development
S3Amazon S3 or S3-compatibleProduction recommended
GCSGoogle Cloud StorageEnterprise option
AZUREAzure Blob StorageEnterprise option

Storage backend is configured via environment variables and is transparent to API users.

Upload a file using multipart form data.

POST /api/files/upload

Headers:

Authorization: Bearer {JWT_TOKEN}
Content-Type: multipart/form-data

Form Parameters:

FieldTypeRequiredDescription
filefileYesFile to upload
namestringNoCustom filename (defaults to original)
project_uuidstringNoAssociate with specific project
descriptionstringNoFile description
tagsarrayNoTags for organization
visibilitystringNoprivate (default) or shared

Example Request (cURL):

Terminal window
curl -X POST "https://api.querri.com/api/files/upload" \
-H "Authorization: Bearer eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9..." \
-F "file=@/path/to/data.csv" \
-F "name=customer_data.csv" \
-F "project_uuid=proj_01ABCDEF" \
-F "description=Customer data export from CRM" \
-F "tags[]=customers" \
-F "tags[]=export"

Example Request (JavaScript):

const formData = new FormData();
formData.append('file', fileInput.files[0]);
formData.append('name', 'customer_data.csv');
formData.append('project_uuid', 'proj_01ABCDEF');
formData.append('description', 'Customer data export from CRM');
formData.append('tags', JSON.stringify(['customers', 'export']));
fetch('https://api.querri.com/api/files/upload', {
method: 'POST',
headers: {
'Authorization': `Bearer ${token}`
},
body: formData
})
.then(response => response.json())
.then(data => console.log(data));

Response: 201 Created

{
"file_id": "file_01ABCDEF",
"name": "customer_data.csv",
"original_name": "data.csv",
"path": "users/user_01ABCDEF/projects/proj_01ABCDEF/customer_data.csv",
"size_bytes": 1048576,
"mime_type": "text/csv",
"checksum": "sha256:a1b2c3d4...",
"project_uuid": "proj_01ABCDEF",
"description": "Customer data export from CRM",
"tags": ["customers", "export"],
"visibility": "private",
"storage_backend": "s3",
"metadata": {
"encoding": "utf-8",
"delimiter": ",",
"row_count": 15000,
"column_count": 12
},
"uploaded_by": "user_01ABCDEF",
"uploaded_at": "2025-01-15T10:00:00Z",
"download_url": "/api/files/stream/users/user_01ABCDEF/projects/proj_01ABCDEF/customer_data.csv",
"expires_at": null
}

File Size Limits:

PlanMax File SizeMax Storage
Free100 MB1 GB
Pro1 GB100 GB
Enterprise10 GBUnlimited

Error Responses:

// 400 Bad Request - File too large
{
"error": "file_too_large",
"message": "File size exceeds limit of 100 MB",
"size_bytes": 209715200,
"limit_bytes": 104857600
}
// 400 Bad Request - Unsupported file type
{
"error": "unsupported_file_type",
"message": "File type 'application/x-executable' is not allowed",
"mime_type": "application/x-executable"
}
// 507 Insufficient Storage
{
"error": "storage_quota_exceeded",
"message": "Storage quota exceeded",
"used_bytes": 1073741824,
"quota_bytes": 1073741824
}

Download a file with streaming support for large files.

GET /api/files/stream/{path}

Path Parameters:

ParameterTypeDescription
pathstringFull file path (URL-encoded)

Query Parameters:

ParameterTypeDefaultDescription
downloadbooleanfalseForce download vs. inline display
share_tokenstring-Share token for public access

Example Request:

Terminal window
# Direct download
curl "https://api.querri.com/api/files/stream/users/user_01ABCDEF/projects/proj_01ABCDEF/customer_data.csv" \
-H "Authorization: Bearer eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9..." \
-o customer_data.csv
# Force download (adds Content-Disposition header)
curl "https://api.querri.com/api/files/stream/users/user_01ABCDEF/projects/proj_01ABCDEF/customer_data.csv?download=true" \
-H "Authorization: Bearer ${JWT_TOKEN}" \
-o customer_data.csv

Response: 200 OK

File content streamed as binary data.

Response Headers:

Content-Type: text/csv
Content-Length: 1048576
Content-Disposition: attachment; filename="customer_data.csv"
ETag: "a1b2c3d4..."
Last-Modified: Wed, 15 Jan 2025 10:00:00 GMT
Accept-Ranges: bytes

Range Requests:

The API supports partial content requests for resumable downloads:

Terminal window
curl "https://api.querri.com/api/files/stream/path/to/file.csv" \
-H "Authorization: Bearer ${JWT_TOKEN}" \
-H "Range: bytes=0-1023" \
-o partial.csv

Response: 206 Partial Content

Content-Range: bytes 0-1023/1048576
Content-Length: 1024

Permission Required: file:read on the file, or valid share token.

Error Responses:

// 404 Not Found
{
"error": "not_found",
"message": "File not found or access denied"
}
// 410 Gone - File expired
{
"error": "file_expired",
"message": "This file has expired and is no longer available",
"expired_at": "2025-01-10T00:00:00Z"
}

Retrieve files uploaded by the user or accessible via project permissions.

GET /api/files

Query Parameters:

ParameterTypeDefaultDescription
pageinteger1Page number
limitinteger20Results per page (max 100)
project_uuidstring-Filter by project
tagsstring-Filter by tags (comma-separated)
mime_typestring-Filter by MIME type
searchstring-Search in filename and description
sortstringuploaded_atSort field
orderstringdescSort order: asc or desc

Example Request:

Terminal window
curl "https://api.querri.com/api/files?project_uuid=proj_01ABCDEF&tags=export&limit=50" \
-H "Authorization: Bearer eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9..."

Response: 200 OK

{
"data": [
{
"file_id": "file_01ABCDEF",
"name": "customer_data.csv",
"path": "users/user_01ABCDEF/projects/proj_01ABCDEF/customer_data.csv",
"size_bytes": 1048576,
"mime_type": "text/csv",
"project_uuid": "proj_01ABCDEF",
"description": "Customer data export from CRM",
"tags": ["customers", "export"],
"visibility": "private",
"uploaded_by": "user_01ABCDEF",
"uploaded_at": "2025-01-15T10:00:00Z",
"download_url": "/api/files/stream/users/user_01ABCDEF/projects/proj_01ABCDEF/customer_data.csv",
"permissions": {
"can_read": true,
"can_delete": true,
"can_share": true
}
}
],
"pagination": {
"page": 1,
"limit": 50,
"total": 142,
"total_pages": 3,
"has_next": true,
"has_prev": false
},
"storage_summary": {
"total_files": 142,
"total_size_bytes": 52428800,
"quota_bytes": 107374182400,
"used_percentage": 0.049
}
}

Retrieve metadata for a specific file without downloading content.

GET /api/files/{file_id}

Example Request:

Terminal window
curl "https://api.querri.com/api/files/file_01ABCDEF" \
-H "Authorization: Bearer eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9..."

Response: 200 OK

{
"file_id": "file_01ABCDEF",
"name": "customer_data.csv",
"original_name": "data.csv",
"path": "users/user_01ABCDEF/projects/proj_01ABCDEF/customer_data.csv",
"size_bytes": 1048576,
"mime_type": "text/csv",
"checksum": "sha256:a1b2c3d4...",
"project_uuid": "proj_01ABCDEF",
"description": "Customer data export from CRM",
"tags": ["customers", "export"],
"visibility": "private",
"storage_backend": "s3",
"metadata": {
"encoding": "utf-8",
"delimiter": ",",
"row_count": 15000,
"column_count": 12,
"columns": [
{"name": "customer_id", "type": "integer"},
{"name": "name", "type": "string"},
{"name": "email", "type": "string"}
]
},
"uploaded_by": "user_01ABCDEF",
"uploaded_at": "2025-01-15T10:00:00Z",
"last_accessed_at": "2025-01-15T14:30:00Z",
"access_count": 42,
"download_url": "/api/files/stream/users/user_01ABCDEF/projects/proj_01ABCDEF/customer_data.csv",
"share_links": [],
"expires_at": null
}

Update file properties like name, description, or tags.

PATCH /api/files/{file_id}

Request Body:

{
"name": "q4_customer_data.csv",
"description": "Q4 2024 customer data export",
"tags": ["customers", "export", "q4", "2024"],
"visibility": "shared"
}

Response: 200 OK

Returns updated file metadata object.

Permission Required: file:edit (file owner or project editor).


Permanently delete a file.

DELETE /api/files/{file_id}

Example Request:

Terminal window
curl -X DELETE "https://api.querri.com/api/files/file_01ABCDEF" \
-H "Authorization: Bearer eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9..."

Response: 204 No Content

Permission Required: file:delete (file owner only).

Error Responses:

// 409 Conflict - File in use
{
"error": "conflict",
"message": "Cannot delete file: currently in use by 2 active steps",
"usage": [
{"step_id": "step_01ABCDEF", "project_uuid": "proj_01ABCDEF"},
{"step_id": "step_02GHIJKL", "project_uuid": "proj_01ABCDEF"}
]
}

Generate a public share link for a file.

POST /api/files/{file_id}/share

Request Body:

{
"expires_at": "2025-02-15T00:00:00Z",
"password_protected": false,
"max_downloads": 100
}

Parameters:

FieldTypeRequiredDescription
expires_atstringNoExpiration timestamp (ISO 8601)
password_protectedbooleanNoRequire password for access
passwordstringConditionalPassword (if password_protected is true)
max_downloadsintegerNoMaximum download count

Response: 201 Created

{
"share_link": "https://api.querri.com/api/files/stream/users/user_01ABCDEF/projects/proj_01ABCDEF/customer_data.csv?share_token=share_abc123",
"share_token": "share_abc123",
"file_id": "file_01ABCDEF",
"expires_at": "2025-02-15T00:00:00Z",
"password_protected": false,
"max_downloads": 100,
"download_count": 0,
"created_at": "2025-01-15T10:00:00Z"
}
Terminal window
# Via share token
curl "https://api.querri.com/api/files/stream/path/to/file.csv?share_token=share_abc123" \
-o file.csv
# With password (if required)
curl "https://api.querri.com/api/files/stream/path/to/file.csv?share_token=share_abc123" \
-H "X-Share-Password: secret123" \
-o file.csv

ExtensionMIME TypeAuto-Detection
.csvtext/csvDelimiter, encoding, schema
.jsonapplication/jsonSchema validation
.jsonlapplication/jsonlinesLine count
.parquetapplication/octet-streamSchema, row count
.xlsxapplication/vnd.openxmlformats-officedocument.spreadsheetml.sheetSheets, schema
.xlsapplication/vnd.ms-excelSheets, schema
ExtensionMIME Type
.pdfapplication/pdf
.txttext/plain
.mdtext/markdown
ExtensionMIME Type
.pngimage/png
.jpg, .jpegimage/jpeg
.gifimage/gif
.svgimage/svg+xml

Executable files and scripts are blocked for security:

  • .exe, .dll, .bat, .sh, .app
  • .js, .py, .rb (unless explicitly allowed)

Uploaded files are automatically processed based on type:

CSV/Excel:

  • Schema detection
  • Row/column count
  • Data type inference
  • Sample data extraction

JSON:

  • Schema validation
  • Flattening nested structures
  • Array detection

Parquet:

  • Metadata extraction
  • Schema reading
  • Statistics collection

Trigger manual processing for updated files:

Terminal window
curl -X POST "https://api.querri.com/api/files/file_01ABCDEF/process" \
-H "Authorization: Bearer ${JWT_TOKEN}" \
-H "Content-Type: application/json" \
-d '{
"operations": ["detect_schema", "generate_preview"],
"options": {
"sample_size": 1000
}
}'

Response:

{
"processing_id": "proc_01ABCDEF",
"file_id": "file_01ABCDEF",
"status": "processing",
"operations": ["detect_schema", "generate_preview"],
"started_at": "2025-01-15T10:00:00Z"
}

Terminal window
curl "https://api.querri.com/api/files/storage/quota" \
-H "Authorization: Bearer ${JWT_TOKEN}"

Response:

{
"quota_bytes": 107374182400,
"used_bytes": 52428800,
"available_bytes": 107321753600,
"used_percentage": 0.049,
"file_count": 142,
"breakdown": {
"projects": 45000000,
"uploads": 7000000,
"exports": 428800
}
}

Delete files older than specified date:

Terminal window
curl -X POST "https://api.querri.com/api/files/cleanup" \
-H "Authorization: Bearer ${JWT_TOKEN}" \
-H "Content-Type: application/json" \
-d '{
"older_than": "2024-01-01T00:00:00Z",
"exclude_tags": ["important", "archive"],
"dry_run": true
}'

Response:

{
"files_to_delete": 23,
"space_to_free_bytes": 12582912,
"files": [
{
"file_id": "file_01ABCDEF",
"name": "old_data.csv",
"size_bytes": 524288,
"uploaded_at": "2023-06-15T10:00:00Z"
}
]
}

Files support versioning when updated:

Terminal window
curl -X POST "https://api.querri.com/api/files/file_01ABCDEF/versions" \
-H "Authorization: Bearer ${JWT_TOKEN}" \
-F "file=@/path/to/updated_data.csv" \
-F "change_message=Updated with Q4 data"

Response:

{
"version_id": "ver_01ABCDEF",
"file_id": "file_01ABCDEF",
"version": 2,
"size_bytes": 1150000,
"change_message": "Updated with Q4 data",
"created_at": "2025-01-15T15:00:00Z",
"download_url": "/api/files/stream/path/to/file.csv?version=2"
}

List versions:

Terminal window
curl "https://api.querri.com/api/files/file_01ABCDEF/versions" \
-H "Authorization: Bearer ${JWT_TOKEN}"

  1. Use descriptive filenames - Include dates, data sources, or purposes
  2. Tag files appropriately - Use consistent tagging for easier filtering
  3. Set expiration dates - For temporary uploads or exports
  4. Monitor storage quota - Regularly cleanup unused files
  5. Use streaming for large files - Avoid loading entire files into memory
  6. Validate file integrity - Check checksums after upload
  7. Compress large files - Use gzip or parquet compression

CodeDescription
200Success (GET, PATCH)
201Created (POST upload)
204No Content (DELETE)
206Partial Content (range request)
400Bad Request (validation error)
401Unauthorized
403Forbidden (insufficient permissions)
404Not Found
409Conflict (file in use)
410Gone (file expired)
413Payload Too Large (file size limit)
416Range Not Satisfiable
429Too Many Requests
507Insufficient Storage
500Internal Server Error