> ## Documentation Index
> Fetch the complete documentation index at: https://docs.meibel.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# File Uploads

> Upload files to the Meibel API with streamed 64 KB chunks, resumable transfers, and endpoints for progress tracking.

The SDKs stream file uploads directly to the server in 64 KB chunks, so even large files are not fully buffered in memory.

## Endpoints

| Endpoint                            | Behaviour                                                                                               |
| ----------------------------------- | ------------------------------------------------------------------------------------------------------- |
| `POST /datasources/uploads`         | Returns immediately after upload. The server processes the file asynchronously. Track progress via SSE. |
| `POST /datasources/uploads/process` | Blocks until the server finishes processing and returns the result in one response.                     |

<Note>
  For files larger than 10 MB, use the async endpoint with progress streaming so your application stays responsive during server-side processing.
</Note>

## Basic Upload

<CodeGroup>
  ```python Python theme={null}
  from meibel import MeibelClient

  client = MeibelClient(api_key="your-api-key")

  # Upload a file to a datasource
  with open("document.pdf", "rb") as f:
      result = client.datasources.file_uploads.upload_content(
          datasource_id="ds_123",
          files=f,
          files_name="document.pdf",
      )

  print(result.upload_id)
  ```

  ```typescript TypeScript theme={null}
  import { MeibelClient } from 'meibel';
  import { readFileSync } from 'fs';

  const client = new MeibelClient({ apiKey: 'your-api-key' });

  // Upload a file to a datasource
  const file = new Blob([readFileSync('document.pdf')]);
  const result = await client.datasources.fileUploads.uploadContent('ds_123', file, 'document.pdf');
  console.log(result.uploadId);
  ```

  ```go Go theme={null}
  import v2 "github.com/meibel-ai/meibel-go/v2"

  client := v2.NewClient(v2.WithAPIKey("your-api-key"))
  ctx := context.Background()

  // Upload a file
  f, err := os.Open("document.pdf")
  if err != nil {
      log.Fatal(err)
  }
  defer f.Close()

  result, err := client.Agents.Sessions.SendChatMessageStream(ctx, "session_id_value", f, "document.pdf", nil)
  if err != nil {
      log.Fatal(err)
  }
  fmt.Println(result)
  ```
</CodeGroup>

## Upload with Processing Progress

After starting an upload, stream its progress in real time as the file is transferred and finalized:

<CodeGroup>
  ```python Python theme={null}
  from meibel import MeibelClient

  client = MeibelClient(api_key="your-api-key")

  # Upload the file. It streams directly to the server, never buffered in memory.
  with open("report.pdf", "rb") as f:
      upload = client.datasources.file_uploads.upload_content(
          datasource_id="ds_123",
          files=f,
          files_name="report.pdf",
      )

  print(f"Upload started: {upload.upload_id}")

  # Stream upload progress. Each event is an SSEEvent; parse its JSON payload.
  for event in client.datasources.file_uploads.stream_upload_progress(upload.upload_id):
      payload = event.json()
      if payload["type"] == "file_progress":
          data = payload["data"]
          print(f"{data['filename']}: {data['uploaded_bytes']}/{data['total_bytes']} bytes")
      elif payload["type"] == "file_complete" and payload["data"].get("error"):
          print("Error:", payload["data"]["error"])
      elif payload["type"] == "upload_complete":
          print(payload["data"]["message"])
  ```

  ```typescript TypeScript theme={null}
  import { MeibelClient } from 'meibel';
  import { readFileSync } from 'fs';

  const client = new MeibelClient({ apiKey: 'your-api-key' });

  // Upload the file. It streams directly to the server.
  const file = new Blob([readFileSync('report.pdf')]);
  const upload = await client.datasources.fileUploads.uploadContent('ds_123', file, 'report.pdf');

  console.log('Upload started:', upload.uploadId);

  // Stream upload progress. Each event is the parsed payload object.
  for await (const event of client.datasources.fileUploads.streamUploadProgress(upload.uploadId)) {
    if (event.type === 'file_progress') {
      console.log(`${event.data.filename}: ${event.data.uploaded_bytes}/${event.data.total_bytes} bytes`);
    } else if (event.type === 'file_complete' && event.data.error) {
      console.log('Error:', event.data.error);
    } else if (event.type === 'upload_complete') {
      console.log(event.data.message);
    }
  }
  ```

  ```go Go theme={null}
  import v2 "github.com/meibel-ai/meibel-go/v2"

  client := v2.NewClient(v2.WithAPIKey("your-api-key"))
  ctx := context.Background()

  // Upload the file. It streams directly to the server.
  f, err := os.Open("report.pdf")
  if err != nil {
      log.Fatal(err)
  }
  defer f.Close()

  upload, err := client.Agents.Sessions.SendChatMessageStream(ctx, f, "report.pdf")
  if err != nil {
      log.Fatal(err)
  }

  fmt.Println("Upload started:", upload.UploadID)

  // Track server-side processing progress
  stream, err := client.Datasources.FileUploads.StreamUploadProgress(ctx, upload.UploadID)
  if err != nil {
      log.Fatal(err)
  }
  for event := range stream.Events {
      fmt.Println(event)
  }
  ```
</CodeGroup>

## Upload with Synchronous Processing

For smaller files where you don't need progress tracking, use the synchronous endpoint. The file is still streamed to the server, but the request blocks until processing completes and returns the result directly.

<CodeGroup>
  ```python Python theme={null}
  from meibel import MeibelClient

  client = MeibelClient(api_key="your-api-key")

  # Upload a file
  with open("document.pdf", "rb") as f:
      result = client.datasources.file_uploads.upload_and_list_content("datasource_id_value", files=f, files_name="document.pdf")
      print(result)
  ```

  ```typescript TypeScript theme={null}
  import { MeibelClient } from 'meibel';

  const client = new MeibelClient({ apiKey: 'your-api-key' });

  import fs from 'fs';

  // Upload a file
  const file = fs.createReadStream('document.pdf');
  const result = await client.datasources.fileUploads.uploadAndListContent('datasource_id_value', file, 'document.pdf');
  console.log(result);
  ```

  ```go Go theme={null}
  import v2 "github.com/meibel-ai/meibel-go/v2"

  client := v2.NewClient(v2.WithAPIKey("your-api-key"))
  ctx := context.Background()

  // Upload a file
  f, err := os.Open("document.pdf")
  if err != nil {
      log.Fatal(err)
  }
  defer f.Close()

  result, err := client.Datasources.FileUploads.UploadAndListContent(ctx, "datasource_id_value", f, "document.pdf", nil)
  if err != nil {
      log.Fatal(err)
  }
  fmt.Println(result)
  ```
</CodeGroup>

## Supported File Types

The API accepts common document formats including PDF, DOCX, XLSX, CSV, TXT, and JSON files. Maximum file size is 100 MB.

## Error Handling

Upload errors are returned as standard API errors. When using progress streaming, errors are delivered as events:

```json theme={null}
{
  "type": "error",
  "message": "Unsupported file format"
}
```
