diff --git a/docs/my-website/docs/container_files.md b/docs/my-website/docs/container_files.md
index 25b58a043c8..1ef7687ea77 100644
--- a/docs/my-website/docs/container_files.md
+++ b/docs/my-website/docs/container_files.md
@@ -21,6 +21,7 @@ Looking for how to use Code Interpreter? See the [Code Interpreter Guide](/docs/
| Endpoint | Method | Description |
|----------|--------|-------------|
+| `/v1/containers/{container_id}/files` | POST | Upload file to container |
| `/v1/containers/{container_id}/files` | GET | List files in container |
| `/v1/containers/{container_id}/files/{file_id}` | GET | Get file metadata |
| `/v1/containers/{container_id}/files/{file_id}/content` | GET | Download file content |
@@ -28,6 +29,45 @@ Looking for how to use Code Interpreter? See the [Code Interpreter Guide](/docs/
## LiteLLM Python SDK
+### Upload Container File
+
+Upload files directly to a container session. This is useful when `/chat/completions` or `/responses` sends files to the container but the input file type is limited to PDF. This endpoint lets you work with other file types like CSV, Excel, Python scripts, etc.
+
+```python showLineNumbers title="upload_container_file.py"
+from litellm import upload_container_file
+
+# Upload a CSV file
+file = upload_container_file(
+ container_id="cntr_123...",
+ file=("data.csv", open("data.csv", "rb").read(), "text/csv"),
+ custom_llm_provider="openai"
+)
+
+print(f"Uploaded: {file.id}")
+print(f"Path: {file.path}")
+```
+
+**Async:**
+
+```python showLineNumbers title="aupload_container_file.py"
+from litellm import aupload_container_file
+
+file = await aupload_container_file(
+ container_id="cntr_123...",
+ file=("script.py", b"print('hello world')", "text/x-python"),
+ custom_llm_provider="openai"
+)
+```
+
+**Supported file formats:**
+- CSV (`.csv`)
+- Excel (`.xlsx`)
+- Python scripts (`.py`)
+- JSON (`.json`)
+- Markdown (`.md`)
+- Text files (`.txt`)
+- And more...
+
### List Container Files
```python showLineNumbers title="list_container_files.py"
@@ -103,6 +143,40 @@ print(f"Deleted: {result.deleted}")
import Tabs from '@theme/Tabs';
import TabItem from '@theme/TabItem';
+### Upload File
+
+
+
+
+```python showLineNumbers title="upload_file.py"
+from openai import OpenAI
+
+client = OpenAI(
+ api_key="sk-1234",
+ base_url="http://localhost:4000"
+)
+
+file = client.containers.files.create(
+ container_id="cntr_123...",
+ file=open("data.csv", "rb")
+)
+
+print(f"Uploaded: {file.id}")
+print(f"Path: {file.path}")
+```
+
+
+
+
+```bash showLineNumbers title="upload_file.sh"
+curl "http://localhost:4000/v1/containers/cntr_123.../files" \
+ -H "Authorization: Bearer sk-1234" \
+ -F file="@data.csv"
+```
+
+
+
+
### List Files
@@ -236,6 +310,13 @@ curl -X DELETE "http://localhost:4000/v1/containers/cntr_123.../files/cfile_456.
## Parameters
+### Upload File
+
+| Parameter | Type | Required | Description |
+|-----------|------|----------|-------------|
+| `container_id` | string | Yes | Container ID |
+| `file` | FileTypes | Yes | File to upload. Can be a tuple of (filename, content, content_type), file-like object, or bytes |
+
### List Files
| Parameter | Type | Required | Description |
diff --git a/litellm/llms/custom_httpx/container_handler.py b/litellm/llms/custom_httpx/container_handler.py
index ed112e4dd58..73017eaaf30 100644
--- a/litellm/llms/custom_httpx/container_handler.py
+++ b/litellm/llms/custom_httpx/container_handler.py
@@ -88,6 +88,34 @@ def _build_query_params(
return params
+def _prepare_multipart_file_upload(
+ file: Any,
+ headers: Dict[str, Any],
+) -> tuple:
+ """
+ Prepare file and headers for multipart upload.
+
+ Returns:
+ Tuple of (files_dict, headers_without_content_type)
+ """
+ from litellm.litellm_core_utils.prompt_templates.common_utils import (
+ extract_file_data,
+ )
+
+ extracted = extract_file_data(file)
+ filename = extracted.get("filename") or "file"
+ content = extracted.get("content") or b""
+ content_type = extracted.get("content_type") or "application/octet-stream"
+ files = {"file": (filename, content, content_type)}
+
+ # Remove content-type header - httpx will set it automatically for multipart
+ headers_copy = headers.copy()
+ headers_copy.pop("content-type", None)
+ headers_copy.pop("Content-Type", None)
+
+ return files, headers_copy
+
+
class GenericContainerHandler:
"""
Generic handler for container file API endpoints.
@@ -210,6 +238,7 @@ class GenericContainerHandler:
# Make request
method = endpoint_config["method"].upper()
returns_binary = endpoint_config.get("returns_binary", False)
+ is_multipart = endpoint_config.get("is_multipart", False)
try:
if method == "GET":
@@ -217,7 +246,11 @@ class GenericContainerHandler:
elif method == "DELETE":
response = http_client.delete(url=url, headers=headers, params=query_params)
elif method == "POST":
- response = http_client.post(url=url, headers=headers, params=query_params)
+ if is_multipart and "file" in kwargs:
+ files, headers = _prepare_multipart_file_upload(kwargs["file"], headers)
+ response = http_client.post(url=url, headers=headers, params=query_params, files=files)
+ else:
+ response = http_client.post(url=url, headers=headers, params=query_params)
else:
raise ValueError(f"Unsupported HTTP method: {method}")
@@ -307,6 +340,7 @@ class GenericContainerHandler:
# Make request
method = endpoint_config["method"].upper()
returns_binary = endpoint_config.get("returns_binary", False)
+ is_multipart = endpoint_config.get("is_multipart", False)
try:
if method == "GET":
@@ -314,7 +348,11 @@ class GenericContainerHandler:
elif method == "DELETE":
response = await http_client.delete(url=url, headers=headers, params=query_params)
elif method == "POST":
- response = await http_client.post(url=url, headers=headers, params=query_params)
+ if is_multipart and "file" in kwargs:
+ files, headers = _prepare_multipart_file_upload(kwargs["file"], headers)
+ response = await http_client.post(url=url, headers=headers, params=query_params, files=files)
+ else:
+ response = await http_client.post(url=url, headers=headers, params=query_params)
else:
raise ValueError(f"Unsupported HTTP method: {method}")
diff --git a/provider_endpoints_support.json b/provider_endpoints_support.json
index bc5dea7b97c..617e9d1e3d5 100644
--- a/provider_endpoints_support.json
+++ b/provider_endpoints_support.json
@@ -1515,7 +1515,7 @@
"list_containers": true,
"retrieve_container": true,
"delete_container": true,
- "create_container_file": false,
+ "create_container_file": true,
"list_container_files": true,
"retrieve_container_file": true,
"retrieve_container_file_content": true,