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: uploadingprocessingready | 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.