> ## 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

> How to upload files with streaming and progress tracking

# File Uploads

The SDKs stream file uploads directly to the server in 64 KB chunks — files are never fully buffered in memory, so you can upload files of any size.

## 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
  with open("document.pdf", "rb") as f:
      result = client.agents.sessions.send_chat_message_stream("session_id_value", file=f, filename="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.agents.sessions.sendChatMessageStream('session_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.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 uploading, the server processes the file (parsing, extraction, indexing). You can stream server-side processing progress in real time:

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

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

  # Upload the file — streams directly to the server, never buffered in memory
  with open("report.pdf", "rb") as f:
      upload = client.agents.sessions.send_chat_message_stream(file=f, file_name="report.pdf")

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

  # Track server-side processing progress
  for event in client.datasources.file_uploads.stream_upload_progress(upload.upload_id):
      if event.get("type") == "progress":
          pct = event["percent_complete"]
          print(f"Processing: {pct}%")
      elif event.get("type") == "complete":
          print("Processing complete!", event.get("result"))
      elif event.get("type") == "error":
          print("Error:", event.get("message"))
  ```

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

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

  // Upload the file — streams directly to the server
  const file = new Blob([readFileSync('report.pdf')]);
  const upload = await client.agents.sessions.sendChatMessageStream(file, 'report.pdf');

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

  // Track server-side processing progress
  for await (const event of client.datasources.fileUploads.streamUploadProgress(upload.uploadId)) {
    if (event.type === 'progress') {
      console.log(`Processing: ${event.percentComplete}%`);
    } else if (event.type === 'complete') {
      console.log('Processing complete!', event.result);
    } else if (event.type === 'error') {
      console.log('Error:', event.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 — 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", file=f, filename="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"
}
```
