> ## Documentation Index
> Fetch the complete documentation index at: https://edenai-docs-github-copilot-integration.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

> Learn how to upload and manage files with V3's persistent file storage system.

# File upload

export const TechArticleSchema = ({title, description, path, articleSection, about, proficiencyLevel = "Beginner", dependencies, keywords = [], datePublished, dateModified, image, inLanguage = "en"}) => {
  const baseUrl = "https://www.edenai.co/docs";
  const canonicalUrl = `${baseUrl}/${path}`.replace(/\/+$/, "");
  const ogParams = new URLSearchParams({
    division: articleSection || "",
    title: title || "",
    description: description || ""
  });
  const resolvedImage = image || `https://edenai.mintlify.app/_mintlify/api/og?${ogParams.toString()}`;
  const data = {
    "@context": "https://schema.org",
    "@type": "TechArticle",
    "@id": `${canonicalUrl}#techarticle`,
    mainEntityOfPage: {
      "@type": "WebPage",
      "@id": canonicalUrl
    },
    headline: title,
    name: title,
    description: description,
    url: canonicalUrl,
    inLanguage: inLanguage,
    isPartOf: {
      "@type": "WebSite",
      name: "Eden AI Documentation",
      url: baseUrl
    },
    author: [{
      "@type": "Organization",
      name: "Eden AI",
      url: "https://www.edenai.co/"
    }],
    publisher: {
      "@type": "Organization",
      name: "Eden AI",
      url: "https://www.edenai.co/",
      logo: {
        "@type": "ImageObject",
        url: "https://www.edenai.co/assets/logo.png"
      }
    }
  };
  if (articleSection) data.articleSection = articleSection;
  if (about) data.about = {
    "@type": "Thing",
    name: about
  };
  if (proficiencyLevel) data.proficiencyLevel = proficiencyLevel;
  if (dependencies) data.dependencies = dependencies;
  if (keywords && keywords.length) data.keywords = keywords;
  if (datePublished) data.datePublished = datePublished;
  if (dateModified) data.dateModified = dateModified;
  data.image = Array.isArray(resolvedImage) ? resolvedImage : [resolvedImage];
  const json = JSON.stringify(data);
  const schemaId = `techarticle-${canonicalUrl}`;
  React.useEffect(() => {
    if (typeof document === "undefined") return;
    document.querySelectorAll(`script[data-schema-id="${schemaId}"]`).forEach(n => n.remove());
    const script = document.createElement("script");
    script.type = "application/ld+json";
    script.dataset.schemaId = schemaId;
    script.textContent = json;
    document.head.appendChild(script);
    return () => script.remove();
  }, [json, schemaId]);
  return null;
};

<TechArticleSchema title={"File Upload"} description={"Learn how to upload and manage files with V3's persistent file storage system."} path="v3/llms/file-upload" articleSection="LLMs" about={"LLM API"} proficiencyLevel="Intermediate" keywords={["Eden AI", "AI API", "LLM API", "chat completion", "OpenAI compatible"]} datePublished="2026-05-06T00:00:00Z" dateModified="2026-05-07T00:00:00Z" />

Learn how to upload and manage files with V3's persistent file storage system.

## Overview

V3 introduces **persistent file storage** that allows you to:

* Upload files once and reference them across multiple requests
* Reduce upload overhead and latency
* Manage file lifecycle with automatic expiration

**Endpoint:**

```
POST /v3/upload
```

## File Intent (purpose)

The `purpose` field is optional. When provided, it tags the file with its intended use making it easy to filter your uploaded files by intent when retrieving them later.

| Purpose            | Use case                                                   |
| ------------------ | ---------------------------------------------------------- |
| `assistants`       | Attach the file to an LLM chat completion (PDF, documents) |
| `ocr`              | Extract text from documents or images                      |
| `financial_parser` | Parse invoices, receipts, and financial documents          |
| `identity_parser`  | Extract data from IDs, passports, and similar documents    |
| `resume_parser`    | Extract structured data from CVs and resumes               |
| `speech`           | Transcribe audio files                                     |

## Upload a File

<CodeGroup>
  ```python Python theme={null}
  import requests

  url = "https://api.edenai.run/v3/upload"
  headers = {
      "Authorization": "Bearer YOUR_API_KEY"
  }

  # Upload file
  files = {
      "file": open("document.pdf", "rb")
  }

  data = {
      "purpose": "assistants"  # Optional: describe intended use
  }

  response = requests.post(url, headers=headers, files=files, data=data)
  result = response.json()

  print(f"File ID: {result['file_id']}")
  print(f"Filename: {result['file_name']}")
  print(f"Size: {result['file_size']} bytes")
  print(f"Expires at: {result['expires_at']}")
  ```

  ```bash cURL theme={null}
  curl -X POST https://api.edenai.run/v3/upload \
    -H "Authorization: Bearer YOUR_API_KEY" \
    -F "file=@document.pdf" \
    -F "purpose=assistants"
  ```

  ```javascript JavaScript theme={null}
  const formData = new FormData();
  formData.append('file', fileInput.files[0]);
  formData.append('purpose', 'assistants');

  const response = await fetch('https://api.edenai.run/v3/upload', {
    method: 'POST',
    headers: {
      'Authorization': 'Bearer YOUR_API_KEY'
    },
    body: formData
  });

  const result = await response.json();
  console.log('File ID:', result.file_id);
  ```
</CodeGroup>

### Response

```json theme={null}
{
  "file_id": "550e8400-e29b-41d4-a716-446655440000",
  "file_name": "document.pdf",
  "file_size": 152340,
  "file_mimetype": "application/pdf",
  "purpose": "ocr-processing",
  "metadata": {},
  "created_at": "2024-01-15T10:30:00Z",
  "expires_at": "2024-01-22T10:30:00Z"
}
```

## Use Uploaded File

Once uploaded, reference the file by its `file_id` in an LLM chat completion:

<CodeGroup>
  ```python Python theme={null}
  import requests

  url = "https://api.edenai.run/v3/chat/completions"
  headers = {
      "Authorization": "Bearer YOUR_API_KEY",
      "Content-Type": "application/json"
  }

  payload = {
      "model": "openai/gpt-4o",
      "messages": [
          {
              "role": "user",
              "content": [
                  {"type": "text", "text": "Summarize this document."},
                  {"type": "file", "file": {"file_id": "550e8400-e29b-41d4-a716-446655440000"}}
              ]
          }
      ]
  }

  response = requests.post(url, headers=headers, json=payload)
  result = response.json()
  print(result["choices"][0]["message"]["content"])
  ```
</CodeGroup>

## File Size Limits

* **Default maximum**: 100 MB per file
* Actual limits may vary by feature and provider
* Check provider-specific documentation for exact limits

## File Expiration

Files are automatically deleted after a retention period:

* **Default retention**: 7 days
* Files expire at the timestamp shown in `expires_at`
* Expired files cannot be recovered
* Upload new files as needed

## Upload Multiple Files

<CodeGroup>
  ```python Python theme={null}
  import requests

  url = "https://api.edenai.run/v3/upload"
  headers = {"Authorization": "Bearer YOUR_API_KEY"}

  files_to_upload = [
      "invoice1.pdf",
      "invoice2.pdf",
      "invoice3.pdf"
  ]

  file_ids = []

  for filepath in files_to_upload:
      files = {"file": open(filepath, "rb")}
      data = {"purpose": "assistants"}
          
      response = requests.post(url, headers=headers, files=files, data=data)
      result = response.json()
          
      file_ids.append({
          "filename": filepath,
          "file_id": result["file_id"]
      })
          
      print(f"Uploaded {filepath}: {result['file_id']}")

  # Use file IDs in subsequent requests
  for item in file_ids:
      print(f"{item['filename']}: {item['file_id']}")
  ```
</CodeGroup>

## Error Handling

<CodeGroup>
  ```python Python theme={null}
  import requests
  from requests.exceptions import RequestException

  def safe_upload(filepath):
      """Upload file with error handling"""
          
      url = "https://api.edenai.run/v3/upload"
      headers = {"Authorization": "Bearer YOUR_API_KEY"}
          
      try:
          with open(filepath, "rb") as f:
              files = {"file": f}
              response = requests.post(url, headers=headers, files=files)
              response.raise_for_status()
                  
              result = response.json()
              return {
                  "success": True,
                  "file_id": result["file_id"],
                  "file_name": result["file_name"]
              }
                  
      except FileNotFoundError:
          return {"success": False, "error": "File not found"}
      except RequestException as e:
          return {"success": False, "error": str(e)}
      except Exception as e:
          return {"success": False, "error": f"Unexpected error: {str(e)}"}

  # Usage
  result = safe_upload("document.pdf")
  if result["success"]:
      print(f"Uploaded: {result['file_id']}")
  else:
      print(f"Error: {result['error']}")
  ```
</CodeGroup>

## Best Practices

### 1. Reuse Files

Upload once, use in multiple requests:

```python theme={null}
import requests

upload_url = "https://api.edenai.run/v3/upload"
llm_url = "https://api.edenai.run/v3/chat/completions"
headers = {"Authorization": "Bearer YOUR_API_KEY"}
files = {"file": open("document.pdf", "rb")}

# Upload file once
upload_response = requests.post(upload_url, headers=headers, files=files)
file_id = upload_response.json()["file_id"]

# Query with multiple models without re-uploading
models = [
    "openai/gpt-4o",
    "anthropic/claude-sonnet-4-5",
    "google/gemini-2.5-flash"
]

for model in models:
    response = requests.post(
        llm_url,
        headers=headers,
        json={
            "model": model,
            "messages": [
                {
                    "role": "user",
                    "content": [
                        {"type": "text", "text": "Summarize this document."},
                        {"type": "file", "file": {"file_id": file_id}}
                    ]
                }
            ]
        }
    )
```

### 2. Track File Metadata

Keep track of uploaded files:

```python theme={null}
import requests

upload_url = "https://api.edenai.run/v3/upload"
headers = {"Authorization": "Bearer YOUR_API_KEY"}

uploaded_files = {}

def upload_and_track(filepath, purpose=None):
    files = {"file": open(filepath, "rb")}
    data = {"purpose": purpose} if purpose else {}

    response = requests.post(upload_url, headers=headers, files=files, data=data)
    result = response.json()
    
    # Store metadata
    uploaded_files[result["file_id"]] = {
        "file_name": result["file_name"],
        "uploaded_at": result["created_at"],
        "expires_at": result["expires_at"],
        "purpose": purpose
    }
    
    return result["file_id"]
```

### 3. Handle Large Files

For large files, show upload progress:

```python theme={null}
import os
import requests
from tqdm import tqdm

upload_url = "https://api.edenai.run/v3/upload"
headers = {"Authorization": "Bearer YOUR_API_KEY"}

def upload_with_progress(filepath):
    """Upload file with progress bar"""

    file_size = os.path.getsize(filepath)

    with open(filepath, 'rb') as f:
        with tqdm(total=file_size, unit='B', unit_scale=True) as pbar:
            files = {'file': f}
            response = requests.post(
                upload_url,
                headers=headers,
                files=files
            )
            pbar.update(file_size)

    return response.json()
```

## Common Errors

### 413 Payload Too Large

File exceeds size limit. Compress or split the file.

### 415 Unsupported Media Type

File format not supported. Check supported formats above.

### 422 Validation Error

Invalid request format. Ensure file field is properly set.

## Next Steps

<CardGroup cols={2}>
  <Card title="Chat Completions" icon="comment-dots" href="/v3/llms/chat-completions">
    Use uploaded files in LLM conversations
  </Card>

  <Card title="Streaming" icon="bolt" href="/v3/llms/streaming">
    Stream responses when processing documents
  </Card>
</CardGroup>
