---
title: "Files and Batch API"
description: "Upload files and create batch jobs for asynchronous processing using the Google GenAI SDK through Bifrost across multiple providers."
icon: "folder-open"
---

## Overview

Bifrost supports the Google GenAI Files API and Batch API with **cross-provider routing**. This means you can use the Google GenAI SDK to manage files and batch jobs across multiple providers including Gemini, OpenAI, Anthropic, and Bedrock.

The provider is specified using the `x-model-provider` header in `HttpOptions`.

<Note>
**Bedrock Limitation:** Bedrock batch operations require file-based input with S3 storage, which is not fully supported via the GenAI SDK's batch API. For Bedrock batch operations, use the [Bedrock SDK](../bedrock-sdk/files-and-batch) directly.
</Note>

---

## Client Setup

### Gemini Provider (Default)

```python
from google import genai
from google.genai.types import HttpOptions

client = genai.Client(
    api_key="your-gemini-api-key",
    http_options=HttpOptions(base_url="http://localhost:8080/genai")
)
```

### Cross-Provider Client Setup

To route requests to different providers, add the `x-model-provider` header:

<Tabs group="provider">
<Tab title="Gemini Provider (Default)">

```python
from google import genai
from google.genai.types import HttpOptions

client = genai.Client(
    api_key="your-gemini-api-key",
    http_options=HttpOptions(
        base_url="http://localhost:8080/genai",
        headers={"x-model-provider": "gemini"}
    )
)
```

</Tab>
<Tab title="OpenAI Provider">

```python
from google import genai
from google.genai.types import HttpOptions

client = genai.Client(
    api_key="your-openai-api-key",
    http_options=HttpOptions(
        base_url="http://localhost:8080/genai",
        headers={"x-model-provider": "openai"}
    )
)
```

</Tab>
<Tab title="Anthropic Provider">

```python
from google import genai
from google.genai.types import HttpOptions

client = genai.Client(
    api_key="your-anthropic-api-key",
    http_options=HttpOptions(
        base_url="http://localhost:8080/genai",
        headers={"x-model-provider": "anthropic"}
    )
)
```

<Note>
Anthropic batch operations use inline requests. File uploads for batch processing are not supported for Anthropic.
</Note>

</Tab>
<Tab title="Bedrock Provider">

```python
from google import genai
from google.genai.types import HttpOptions

client = genai.Client(
    api_key="your-api-key",
    http_options=HttpOptions(
        base_url="http://localhost:8080/genai",
        headers={"x-model-provider": "bedrock"}
    )
)
```

<Warning>
Bedrock requires S3-based file storage for batch operations. Use the [Bedrock SDK](../bedrock-sdk/files-and-batch) for full batch support.
</Warning>

</Tab>
</Tabs>

### Helper Function for Provider-Specific Clients

```python
from google import genai
from google.genai.types import HttpOptions

def get_provider_client(provider: str, api_key: str):
    """Create GenAI client with x-model-provider header"""
    return genai.Client(
        api_key=api_key,
        http_options=HttpOptions(
            base_url="http://localhost:8080/genai",
            headers={"x-model-provider": provider}
        )
    )

# Usage
gemini_client = get_provider_client("gemini", "your-gemini-key")
openai_client = get_provider_client("openai", "your-openai-key")
```

---

## Files API

Files are managed through the `client.files` namespace.

### Upload a File

<Tabs group="provider">
<Tab title="Gemini Provider">

```python
from google import genai
from google.genai.types import HttpOptions, UploadFileConfig
import json
import tempfile

def add_gemini_header():
    return {"x-model-provider": "gemini"}

client = genai.Client(
    api_key="your-gemini-api-key",
    http_options=HttpOptions(
        base_url="http://localhost:8080/genai",
        headers=add_gemini_header()
    )
)

# Create JSON content for Gemini batch format
def create_gemini_batch_json(num_requests: int = 2) -> str:
    requests_list = []
    for i in range(num_requests):
        request = {
            "key": f"request_{i+1}",
            "request": {
                "contents": [
                    {
                        "parts": [{"text": f"Hello, this is test message {i+1}. Say hi back briefly."}],
                        "role": "user"
                    }
                ]
            }
        }
        requests_list.append(json.dumps(request))
    return "\n".join(requests_list)

# Write content to a temporary file
json_content = create_gemini_batch_json(num_requests=2)
with tempfile.NamedTemporaryFile(mode='w', suffix='.json', delete=False) as f:
    f.write(json_content)
    temp_file_path = f.name

# Upload the file
response = client.files.upload(
    file=temp_file_path,
    config=UploadFileConfig(display_name='batch_input_gemini')
)

print(f"File name: {response.name}")
print(f"Display name: {response.display_name}")
```

</Tab>
<Tab title="OpenAI Provider">

```python
from google import genai
from google.genai.types import HttpOptions, UploadFileConfig
import json
import tempfile

client = genai.Client(
    api_key="your-openai-api-key",
    http_options=HttpOptions(
        base_url="http://localhost:8080/genai",
        headers={"x-model-provider": "openai"}
    )
)

# Create JSONL content for OpenAI batch format
def create_openai_batch_jsonl(model_id: str, num_requests: int = 2) -> str:
    lines = []
    for i in range(num_requests):
        record = {
            "custom_id": f"request-{i+1}",
            "method": "POST",
            "url": "/v1/chat/completions",
            "body": {
                "model": model_id,
                "messages": [
                    {"role": "user", "content": f"Hello, this is test message {i+1}. Say hi back briefly."}
                ],
                "max_tokens": 100,
            },
        }
        lines.append(json.dumps(record))
    return "\n".join(lines)

# Write content to a temporary file
jsonl_content = create_openai_batch_jsonl("gpt-4o-mini")
with tempfile.NamedTemporaryFile(mode='w', suffix='.jsonl', delete=False) as f:
    f.write(jsonl_content)
    temp_file_path = f.name

# Upload the file
response = client.files.upload(
    file=temp_file_path,
    config=UploadFileConfig(display_name='batch_input_openai')
)

print(f"File name: {response.name}")
```

</Tab>
<Tab title="Anthropic Provider">

<Warning>
Anthropic does not support file uploads for batch processing via this API. Use inline batch requests instead (see Batch API section).
</Warning>

</Tab>
<Tab title="Bedrock Provider">

<Warning>
Bedrock requires S3-based file storage. Use the [Bedrock SDK](../bedrock-sdk/files-and-batch) for file operations.
</Warning>

</Tab>
</Tabs>

### List Files

<Tabs group="provider">
<Tab title="Gemini Provider">

```python
from google import genai
from google.genai.types import HttpOptions

client = genai.Client(
    api_key="your-gemini-api-key",
    http_options=HttpOptions(
        base_url="http://localhost:8080/genai",
        headers={"x-model-provider": "gemini"}
    )
)

# List files
for file in client.files.list(config={'page_size': 50}):
    print(f"File name: {file.name}")
    print(f"Display name: {file.display_name}")
    if hasattr(file, 'size_bytes'):
        print(f"Size: {file.size_bytes} bytes")
    print("---")
```

</Tab>
<Tab title="OpenAI Provider">

```python
from google import genai
from google.genai.types import HttpOptions

client = genai.Client(
    api_key="your-openai-api-key",
    http_options=HttpOptions(
        base_url="http://localhost:8080/genai",
        headers={"x-model-provider": "openai"}
    )
)

# List files from OpenAI
for file in client.files.list(config={'page_size': 50}):
    print(f"File name: {file.name}")
    print(f"Display name: {file.display_name}")
    print("---")
```

</Tab>
<Tab title="Anthropic Provider">

<Warning>
File listing is not supported for Anthropic via this API.
</Warning>

</Tab>
<Tab title="Bedrock Provider">

<Warning>
Use the [Bedrock SDK](../bedrock-sdk/files-and-batch) for file listing with S3 storage.
</Warning>

</Tab>
</Tabs>

### Retrieve File Metadata

```python
from google import genai
from google.genai.types import HttpOptions

client = genai.Client(
    api_key="your-api-key",
    http_options=HttpOptions(
        base_url="http://localhost:8080/genai",
        headers={"x-model-provider": "gemini"}  # or "openai"
    )
)

# Retrieve file metadata by name
file_name = "files/abc123"
response = client.files.get(name=file_name)

print(f"File name: {response.name}")
print(f"Display name: {response.display_name}")
if hasattr(response, 'size_bytes'):
    print(f"Size: {response.size_bytes} bytes")
```

### Delete a File

```python
from google import genai
from google.genai.types import HttpOptions

client = genai.Client(
    api_key="your-api-key",
    http_options=HttpOptions(
        base_url="http://localhost:8080/genai",
        headers={"x-model-provider": "gemini"}  # or "openai"
    )
)

# Delete a file
file_name = "files/abc123"
client.files.delete(name=file_name)

print(f"Deleted file: {file_name}")
```

---

## Batch API

Batches are managed through the `client.batches` namespace. The GenAI SDK supports both file-based and inline batch creation.

### Create a Batch with File

<Tabs group="provider">
<Tab title="Gemini Provider">

```python
from google import genai
from google.genai.types import HttpOptions, UploadFileConfig
import json
import tempfile

client = genai.Client(
    api_key="your-gemini-api-key",
    http_options=HttpOptions(
        base_url="http://localhost:8080/genai",
        headers={"x-model-provider": "gemini"}
    )
)

# Create batch input JSON content (Gemini format)
batch_request = json.dumps({
    "key": "request_1",
    "request": {
        "contents": [
            {"parts": [{"text": "Hello! Say hi back briefly."}], "role": "user"}
        ]
    }
})

# Write to temporary file and upload
with tempfile.NamedTemporaryFile(mode='w', suffix='.json', delete=False) as f:
    f.write(batch_request)
    temp_file_path = f.name

uploaded_file = client.files.upload(
    file=temp_file_path,
    config=UploadFileConfig(display_name='batch_input_gemini')
)

# Create batch job using file reference
batch_job = client.batches.create(
    model="gemini-1.5-flash",
    src=uploaded_file.name,
)

print(f"Batch name: {batch_job.name}")
print(f"State: {batch_job.state}")
```

</Tab>
<Tab title="OpenAI Provider">

```python
from google import genai
from google.genai.types import HttpOptions, UploadFileConfig
import json
import tempfile

client = genai.Client(
    api_key="your-openai-api-key",
    http_options=HttpOptions(
        base_url="http://localhost:8080/genai",
        headers={"x-model-provider": "openai"}
    )
)

# Create batch input JSONL content (OpenAI format)
batch_request = json.dumps({
    "custom_id": "request-1",
    "method": "POST",
    "url": "/v1/chat/completions",
    "body": {
        "model": "gpt-4o-mini",
        "messages": [{"role": "user", "content": "Hello! Say hi back briefly."}],
        "max_tokens": 100
    }
})

# Write to temporary file and upload
with tempfile.NamedTemporaryFile(mode='w', suffix='.jsonl', delete=False) as f:
    f.write(batch_request)
    temp_file_path = f.name

uploaded_file = client.files.upload(
    file=temp_file_path,
    config=UploadFileConfig(display_name='batch_input_openai')
)

# Create batch job using file reference
batch_job = client.batches.create(
    model="gpt-4o-mini",
    src=uploaded_file.name,
)

print(f"Batch name: {batch_job.name}")
print(f"State: {batch_job.state}")
```

</Tab>
<Tab title="Anthropic Provider">

<Warning>
Anthropic does not support file-based batch creation. Use inline requests instead.
</Warning>

</Tab>
<Tab title="Bedrock Provider">

<Warning>
Use the [Bedrock SDK](../bedrock-sdk/files-and-batch) for Bedrock batch operations with S3 storage.
</Warning>

</Tab>
</Tabs>

### Create a Batch with Inline Requests

<Tabs group="provider">
<Tab title="Gemini Provider">

```python
from google import genai
from google.genai.types import HttpOptions

client = genai.Client(
    api_key="your-gemini-api-key",
    http_options=HttpOptions(
        base_url="http://localhost:8080/genai",
        headers={"x-model-provider": "gemini"}
    )
)

# Create inline requests
inline_requests = [
    {
        "contents": [
            {
                "parts": [{"text": "What is 2+2?"}],
                "role": "user"
            }
        ],
        "config": {"response_modalities": ["TEXT"]}
    },
    {
        "contents": [
            {
                "parts": [{"text": "What is the capital of France?"}],
                "role": "user"
            }
        ],
        "config": {"response_modalities": ["TEXT"]}
    }
]

# Create batch job with inline requests
batch_job = client.batches.create(
    model="gemini-1.5-flash",
    src=inline_requests,
)

print(f"Batch name: {batch_job.name}")
print(f"State: {batch_job.state}")
```

</Tab>
<Tab title="OpenAI Provider">

```python
from google import genai
from google.genai.types import HttpOptions

client = genai.Client(
    api_key="your-openai-api-key",
    http_options=HttpOptions(
        base_url="http://localhost:8080/genai",
        headers={"x-model-provider": "openai"}
    )
)

# Create inline requests (OpenAI format via Bifrost translation)
inline_requests = [
    {
        "contents": [
            {
                "parts": [{"text": "What is 2+2?"}],
                "role": "user"
            }
        ],
        "config": {"response_modalities": ["TEXT"]}
    },
    {
        "contents": [
            {
                "parts": [{"text": "What is the capital of France?"}],
                "role": "user"
            }
        ],
        "config": {"response_modalities": ["TEXT"]}
    }
]

batch_job = client.batches.create(
    model="gpt-4o-mini",
    src=inline_requests,
)

print(f"Batch name: {batch_job.name}")
print(f"State: {batch_job.state}")
```

</Tab>
<Tab title="Anthropic Provider">

```python
from google import genai
from google.genai.types import HttpOptions

client = genai.Client(
    api_key="your-anthropic-api-key",
    http_options=HttpOptions(
        base_url="http://localhost:8080/genai",
        headers={"x-model-provider": "anthropic"}
    )
)

# Create inline requests for Anthropic
inline_requests = [
    {
        "contents": [
            {
                "parts": [{"text": "What is 2+2?"}],
                "role": "user"
            }
        ],
        "config": {"response_modalities": ["TEXT"]}
    },
    {
        "contents": [
            {
                "parts": [{"text": "What is the capital of France?"}],
                "role": "user"
            }
        ],
        "config": {"response_modalities": ["TEXT"]}
    }
]

batch_job = client.batches.create(
    model="claude-3-sonnet-20240229",
    src=inline_requests,
)

print(f"Batch name: {batch_job.name}")
print(f"State: {batch_job.state}")
```

</Tab>
<Tab title="Bedrock Provider">

<Warning>
Use the [Bedrock SDK](../bedrock-sdk/files-and-batch) for Bedrock batch operations.
</Warning>

</Tab>
</Tabs>

### List Batches

```python
from google import genai
from google.genai.types import HttpOptions, ListBatchJobsConfig

client = genai.Client(
    api_key="your-api-key",
    http_options=HttpOptions(
        base_url="http://localhost:8080/genai",
        headers={"x-model-provider": "gemini"}  # or "openai", "anthropic"
    )
)

# List batch jobs
for job in client.batches.list(config=ListBatchJobsConfig(page_size=10)):
    print(f"Batch name: {job.name}")
    print(f"State: {job.state}")
    print("---")
```

### Retrieve Batch Status

```python
from google import genai
from google.genai.types import HttpOptions

client = genai.Client(
    api_key="your-api-key",
    http_options=HttpOptions(
        base_url="http://localhost:8080/genai",
        headers={"x-model-provider": "gemini"}  # or "openai", "anthropic"
    )
)

# Get batch job status
batch_name = "batches/abc123"
batch_job = client.batches.get(name=batch_name)

print(f"Batch name: {batch_job.name}")
print(f"State: {batch_job.state}")
```

### Cancel a Batch

```python
from google import genai
from google.genai.types import HttpOptions

client = genai.Client(
    api_key="your-api-key",
    http_options=HttpOptions(
        base_url="http://localhost:8080/genai",
        headers={"x-model-provider": "gemini"}  # or "openai", "anthropic"
    )
)

# Cancel batch job
batch_name = "batches/abc123"
cancelled_job = client.batches.cancel(name=batch_name)

print(f"Batch name: {cancelled_job.name}")
print(f"State: {cancelled_job.state}")  # JOB_STATE_CANCELLING or JOB_STATE_CANCELLED
```

### Delete a Batch

```python
from google import genai
from google.genai.types import HttpOptions

client = genai.Client(
    api_key="your-api-key",
    http_options=HttpOptions(
        base_url="http://localhost:8080/genai",
        headers={"x-model-provider": "gemini"}  # or "openai", "anthropic"
    )
)

# Delete batch job
batch_name = "batches/abc123"
client.batches.delete(name=batch_name)

print(f"Deleted batch: {batch_name}")
```

---

## End-to-End Workflows

### Gemini Batch Workflow

```python
import time
from google import genai
from google.genai.types import HttpOptions, UploadFileConfig, ListBatchJobsConfig
import json
import tempfile
import os

# Configuration
provider = "gemini"
model = "gemini-1.5-flash"

client = genai.Client(
    api_key="your-gemini-api-key",
    http_options=HttpOptions(
        base_url="http://localhost:8080/genai",
        headers={"x-model-provider": provider}
    )
)

# Step 1: Create batch input file
print("Step 1: Creating batch input file...")

def create_gemini_batch_json(num_requests: int) -> str:
    requests_list = []
    for i in range(num_requests):
        request = {
            "key": f"request_{i+1}",
            "request": {
                "contents": [
                    {
                        "parts": [{"text": f"What is {i+1} + {i+1}? Answer briefly."}],
                        "role": "user"
                    }
                ]
            }
        }
        requests_list.append(json.dumps(request))
    return "\n".join(requests_list)

json_content = create_gemini_batch_json(num_requests=3)

with tempfile.NamedTemporaryFile(mode='w', suffix='.json', delete=False) as f:
    f.write(json_content)
    temp_file_path = f.name

# Step 2: Upload batch input file
print("Step 2: Uploading batch input file...")
uploaded_file = client.files.upload(
    file=temp_file_path,
    config=UploadFileConfig(display_name='batch_e2e_gemini')
)
print(f"  Uploaded file: {uploaded_file.name}")

# Step 3: Create batch job
print("Step 3: Creating batch job...")
batch_job = client.batches.create(
    model=model,
    src=uploaded_file.name,
)
print(f"  Created batch: {batch_job.name}, state: {batch_job.state}")

# Step 4: Poll for completion
print("Step 4: Polling batch status...")
terminal_states = ["JOB_STATE_SUCCEEDED", "JOB_STATE_FAILED", "JOB_STATE_CANCELLED"]

for i in range(20):
    batch_job = client.batches.get(name=batch_job.name)
    print(f"  Poll {i+1}: state = {batch_job.state}")
    
    if batch_job.state in terminal_states:
        print(f"  Batch reached terminal state: {batch_job.state}")
        break
    
    time.sleep(5)

# Step 5: Verify batch is in list
print("Step 5: Verifying batch in list...")
found = False
for job in client.batches.list(config=ListBatchJobsConfig(page_size=20)):
    if job.name == batch_job.name:
        found = True
        break

assert found, f"Batch {batch_job.name} should be in list"
print(f"  Verified batch {batch_job.name} is in list")

# Cleanup
os.remove(temp_file_path)
try:
    client.files.delete(name=uploaded_file.name)
    client.batches.delete(name=batch_job.name)
except Exception as e:
    print(f"Cleanup note: {e}")

print(f"\nSuccess! Batch workflow completed for {batch_job.name}")
```

### OpenAI via GenAI SDK Workflow

```python
import time
from google import genai
from google.genai.types import HttpOptions, ListBatchJobsConfig

# Configuration
provider = "openai"
model = "gpt-4o-mini"

client = genai.Client(
    api_key="your-openai-api-key",
    http_options=HttpOptions(
        base_url="http://localhost:8080/genai",
        headers={"x-model-provider": provider}
    )
)

# Step 1: Create inline requests
print("Step 1: Creating inline requests...")
inline_requests = [
    {
        "contents": [
            {"parts": [{"text": "What is 2+2?"}], "role": "user"}
        ],
        "config": {"response_modalities": ["TEXT"]}
    },
    {
        "contents": [
            {"parts": [{"text": "What is the capital of France?"}], "role": "user"}
        ],
        "config": {"response_modalities": ["TEXT"]}
    }
]
print(f"  Created {len(inline_requests)} inline requests")

# Step 2: Create batch job
print("Step 2: Creating batch job...")
batch_job = client.batches.create(
    model=model,
    src=inline_requests,
)
print(f"  Created batch: {batch_job.name}, state: {batch_job.state}")

# Step 3: Poll for completion
print("Step 3: Polling batch status...")
terminal_states = ["JOB_STATE_SUCCEEDED", "JOB_STATE_FAILED", "JOB_STATE_CANCELLED"]

for i in range(10):
    batch_job = client.batches.get(name=batch_job.name)
    print(f"  Poll {i+1}: state = {batch_job.state}")
    
    if batch_job.state in terminal_states:
        break
    
    time.sleep(5)

# Cleanup
try:
    client.batches.delete(name=batch_job.name)
except Exception as e:
    print(f"Cleanup note: {e}")

print(f"\nSuccess! Cross-provider batch {batch_job.name} completed via GenAI SDK.")
```

### Anthropic via GenAI SDK Workflow

```python
import time
from google import genai
from google.genai.types import HttpOptions

# Configuration
provider = "anthropic"
model = "claude-3-sonnet-20240229"

client = genai.Client(
    api_key="your-anthropic-api-key",
    http_options=HttpOptions(
        base_url="http://localhost:8080/genai",
        headers={"x-model-provider": provider}
    )
)

# Step 1: Create inline requests
print("Step 1: Creating inline requests...")
inline_requests = [
    {
        "contents": [
            {"parts": [{"text": "What is 15 * 7?"}], "role": "user"}
        ],
        "config": {"response_modalities": ["TEXT"]}
    },
    {
        "contents": [
            {"parts": [{"text": "What is the largest ocean?"}], "role": "user"}
        ],
        "config": {"response_modalities": ["TEXT"]}
    }
]
print(f"  Created {len(inline_requests)} inline requests")

# Step 2: Create batch job
print("Step 2: Creating batch job...")
batch_job = client.batches.create(
    model=model,
    src=inline_requests,
)
print(f"  Created batch: {batch_job.name}, state: {batch_job.state}")

# Step 3: Poll for completion
print("Step 3: Polling batch status...")
terminal_states = ["JOB_STATE_SUCCEEDED", "JOB_STATE_FAILED", "JOB_STATE_CANCELLED", "ended"]

for i in range(10):
    batch_job = client.batches.get(name=batch_job.name)
    print(f"  Poll {i+1}: state = {batch_job.state}")
    
    if batch_job.state in terminal_states:
        break
    
    time.sleep(5)

print(f"\nSuccess! Anthropic batch {batch_job.name} completed via GenAI SDK.")
```

---

## Batch Job States

| State | Description |
|-------|-------------|
| `JOB_STATE_QUEUED` | Job is queued and waiting to start |
| `JOB_STATE_PENDING` | Job is pending processing |
| `JOB_STATE_RUNNING` | Job is currently running |
| `JOB_STATE_SUCCEEDED` | Job completed successfully |
| `JOB_STATE_FAILED` | Job failed |
| `JOB_STATE_CANCELLING` | Job is being cancelled |
| `JOB_STATE_CANCELLED` | Job was cancelled |

---

## JSON Format Reference

### Gemini Batch Format

```json
{"key": "request-1", "request": {"contents": [{"parts": [{"text": "Hello!"}], "role": "user"}]}}
```

### Inline Request Format

```python
{
    "contents": [
        {"parts": [{"text": "Hello!"}], "role": "user"}
    ],
    "config": {"response_modalities": ["TEXT"]}
}
```

---

## Provider-Specific Notes

| Provider | Header Value | File Upload | Batch Type | Models |
|----------|--------------|-------------|------------|--------|
| **Gemini** | `gemini` or omit | Native storage | File or Inline | `gemini-1.5-*` |
| **OpenAI** | `openai` | Native storage | File or Inline | `gpt-4o-*`, `gpt-4-*` |
| **Anthropic** | `anthropic` | Not supported | Inline only | `claude-3-*` |
| **Bedrock** | `bedrock` | Use Bedrock SDK | Use Bedrock SDK | `anthropic.claude-*` |

<Note>
- **Gemini** and **OpenAI** support both file-based and inline batch creation
- **Anthropic** only supports inline batch requests via this SDK
- **Bedrock** requires the [Bedrock SDK](../bedrock-sdk/files-and-batch) for full batch support
</Note>

---

## Next Steps

- **[Overview](./overview)** - GenAI SDK integration basics
- **[Configuration](../../quickstart/gateway/provider-configuration)** - Bifrost setup and configuration
- **[Core Features](../../features/)** - Governance, semantic caching, and more

