File Upload
The Hatz API provides the functionality to upload files, which you can then use across chat, app builder, and workflows.
Upload Methods
There are two ways to upload files:
| Method | Best for | How it works |
|---|---|---|
Single-request upload (POST /v1/files/upload) |
Server-to-server / API integrations | One multipart POST; the API streams the file to storage and returns a file_id for polling |
Presigned URL upload (POST /v1/files/upload-url) |
Browser / mobile clients | Request a signed URL, PUT the file directly, then poll for completion |
Both methods trigger the same asynchronous processing pipeline (text extraction, embeddings). Poll GET /v1/files/{file_id}/status until status is ready.
Firewall note: Presigned URL uploads use the domain
uploads.hatz.ai. Enterprise customers should whitelist this domain for outbound HTTPS traffic.
Single-Request Upload
Best for API integrations where you want a single HTTP call.
Step 1: Upload the file
curl -X POST 'https://ai.hatz.ai/v1/files/upload' \
-H 'X-API-Key: $HATZ_API_KEY' \
-F 'file=@report.pdf' \
-F 'scope_type=chat' \
-F 'scope_id=a90cb2a4-a4d5-4403-9b6a-6def06b0d4af'
Response:
{
"file_id": "8fb5bc1d-5a8d-4015-86a6-b0ca394e7793",
"status": "uploading",
"message": "File uploaded successfully. Poll GET /v1/files/{file_id}/status for processing status."
}
Step 2: Poll for completion
curl 'https://ai.hatz.ai/v1/files/8fb5bc1d-5a8d-4015-86a6-b0ca394e7793/status' \
-H 'X-API-Key: $HATZ_API_KEY'
Status values: uploading → processing → ready | failed
Presigned URL Upload
Best for browser and mobile clients. Keeps large file transfers off the API server and provides a stable domain (uploads.hatz.ai) for enterprise firewall whitelisting.
Step 1: Request an upload URL
curl -X POST 'https://ai.hatz.ai/v1/files/upload-url' \
-H 'X-API-Key: $HATZ_API_KEY' \
-H 'Content-Type: application/json' \
-d '{
"file_name": "report.pdf",
"file_size": 1048576,
"mime_type": "application/pdf",
"scope_type": "chat",
"scope_id": "a90cb2a4-a4d5-4403-9b6a-6def06b0d4af"
}'
Response:
{
"presigned_url": "https://uploads.hatz.ai/uploads/...",
"file_id": "8fb5bc1d-5a8d-4015-86a6-b0ca394e7793",
"expires_in": 900
}
Step 2: Upload the file
PUT the file directly to the presigned URL. The URL is valid for 15 minutes.
curl -X PUT "$PRESIGNED_URL" \
-H 'Content-Type: application/pdf' \
--data-binary '@report.pdf'
Step 3: Poll for completion
Same as single-request upload — poll GET /v1/files/{file_id}/status.
Parameters
POST /v1/files/upload (multipart form)
| Parameter | Required | Description |
|---|---|---|
file |
Yes | The file to upload (max 50 MB) |
scope_type |
Yes | Context where this file will be used. One of: chat, workflow, app, agent, workflow_run, user, entity |
scope_id |
Yes | The ID of the resource specified by scope_type (e.g. the chat_id, app_id, etc.) |
purpose |
No | File purpose. One of: context (default), tmp, tool_output |
only_calculate_tokens |
No | If true, returns the token count without storing the file |
POST /v1/files/upload-url (JSON body)
| Parameter | Required | Description |
|---|---|---|
file_name |
Yes | Original filename |
file_size |
Yes | File size in bytes (max 50 MB) |
mime_type |
Yes | MIME type of the file |
scope_type |
Yes | Context where this file will be used. One of: chat, workflow, app, agent, workflow_run, user, entity |
scope_id |
Yes | The ID of the resource specified by scope_type (e.g. the chat_id, app_id, etc.) |
purpose |
No | File purpose. One of: context (default), tmp, tool_output |
GET /v1/files/{file_id}/status
Returns the current processing status of a file.
| Field | Description |
|---|---|
file_uuid |
The file identifier |
status |
One of: uploading, processing, ready, failed |
tokens |
Token count (populated when ready) |
error |
Error message (populated when failed) |
Using Files
Once a file reaches ready status, use its file_id across the API.
Chat Completions
curl 'https://ai.hatz.ai/v1/chat/completions' \
-H 'X-API-Key: $HATZ_API_KEY' \
-H 'Content-Type: application/json' \
-d '{
"messages": [{"role": "user", "content": "tell me about this file"}],
"model": "gpt-4o",
"stream": false,
"file_uuids": ["8fb5bc1d-5a8d-4015-86a6-b0ca394e7793"]
}'
App Builder
curl 'https://ai.hatz.ai/v1/app/5ae6e9dd-0296-4409-8fe4-1fc646bb22f7/query' \
-H 'X-API-Key: $HATZ_API_KEY' \
-H 'Content-Type: application/json' \
-d '{
"inputs": {
"report_file": "8fb5bc1d-5a8d-4015-86a6-b0ca394e7793"
},
"stream": false
}'
Workflows
curl -X POST 'https://ai.hatz.ai/v1/workflows/run' \
-H 'X-API-Key: $HATZ_API_KEY' \
-H 'Content-Type: application/json' \
-d '{
"app_id": "5ae6e9dd-0296-4409-8fe4-1fc646bb22f7",
"inputs": {
"report_file": "8fb5bc1d-5a8d-4015-86a6-b0ca394e7793"
}
}'
In all cases, pass the file's UUID as the input value for any file_upload input.