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

# OpenAI

> OpenAI API conversion guide - what to know when using OpenAI through Bifrost

## Overview

OpenAI is the **baseline schema** for Bifrost. When using OpenAI directly, parameters are passed through with minimal conversion - mostly validation and filtering of OpenAI-specific features.

### Supported Operations

| Operation            | Non-Streaming | Streaming | Endpoint                   |
| -------------------- | ------------- | --------- | -------------------------- |
| Chat Completions     | ✅             | ✅         | `/v1/chat/completions`     |
| Responses API        | ✅             | ✅         | `/v1/responses`            |
| Text Completions     | ✅             | ✅         | `/v1/completions`          |
| Embeddings           | ✅             | -         | `/v1/embeddings`           |
| Speech (TTS)         | ✅             | ✅         | `/v1/audio/speech`         |
| Transcriptions (STT) | ✅             | ✅         | `/v1/audio/transcriptions` |
| Image Generation     | ✅             | ✅         | `/v1/images/generations`   |
| Image Edit           | ✅             | ✅         | `/v1/images/edits`         |
| Image Variation      | ✅             | -         | `/v1/images/variations`    |
| Files                | ✅             | -         | `/v1/files`                |
| Batch                | ✅             | -         | `/v1/batches`              |
| Video Generation     | ✅             | -         | `/v1/videos`               |
| List Models          | ✅             | -         | `/v1/models`               |

***

# 1. Chat Completions

**Request Parameters**

| Parameter               | Type                                                                                              | Required | Notes                                                                                                                                                                                                         |
| ----------------------- | ------------------------------------------------------------------------------------------------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `model`                 | string                                                                                            | ✅        | Model identifier                                                                                                                                                                                              |
| `messages`              | [array](https://github.com/maximhq/bifrost/blob/main/core/schemas/chatcompletions.go#L15)         | ✅        | [`ChatMessage`](https://github.com/maximhq/bifrost/blob/main/core/schemas/chatcompletions.go#L370) array with roles ([docs](https://platform.openai.com/docs/api-reference/chat/create#chat-create-messages)) |
| `temperature`           | float                                                                                             | ❌        | Sampling temperature (0-2)                                                                                                                                                                                    |
| `top_p`                 | float                                                                                             | ❌        | Nucleus sampling parameter                                                                                                                                                                                    |
| `stop`                  | string/array                                                                                      | ❌        | Stop sequences                                                                                                                                                                                                |
| `max_completion_tokens` | int                                                                                               | ❌        | Min 16, max output tokens                                                                                                                                                                                     |
| `frequency_penalty`     | float                                                                                             | ❌        | Frequency penalty (-2 to 2)                                                                                                                                                                                   |
| `presence_penalty`      | float                                                                                             | ❌        | Presence penalty (-2 to 2)                                                                                                                                                                                    |
| `logit_bias`            | [object](https://github.com/maximhq/bifrost/blob/main/core/schemas/chatcompletions.go#L25)        | ❌        | Token logit adjustments                                                                                                                                                                                       |
| `logprobs`              | bool                                                                                              | ❌        | Include log probabilities                                                                                                                                                                                     |
| `top_logprobs`          | int                                                                                               | ❌        | Number of log probabilities per token                                                                                                                                                                         |
| `seed`                  | int                                                                                               | ❌        | Reproducibility seed                                                                                                                                                                                          |
| `response_format`       | [object](https://github.com/maximhq/bifrost/blob/main/core/schemas/chatcompletions.go#L23)        | ❌        | Output format ([docs](https://platform.openai.com/docs/api-reference/chat/create#chat-create-response_format))                                                                                                |
| `tools`                 | [array](https://github.com/maximhq/bifrost/blob/main/core/schemas/chatcompletions.go#L21)         | ❌        | [`Tool`](https://github.com/maximhq/bifrost/blob/main/core/schemas/chatcompletions.go#L600) objects ([docs](https://platform.openai.com/docs/api-reference/chat/create#chat-create-tools))                    |
| `tool_choice`           | string/[object](https://github.com/maximhq/bifrost/blob/main/core/schemas/chatcompletions.go#L22) | ❌        | `"auto"`, `"none"`, `"required"`, or specific tool                                                                                                                                                            |
| `parallel_tool_calls`   | bool                                                                                              | ❌        | Allow multiple simultaneous tool calls                                                                                                                                                                        |
| `stream_options`        | [object](https://github.com/maximhq/bifrost/blob/main/core/schemas/chatcompletions.go#L26)        | ❌        | Streaming options ([docs](https://platform.openai.com/docs/api-reference/chat/create#chat-create-stream_options))                                                                                             |
| `reasoning`             | [object](https://github.com/maximhq/bifrost/blob/main/core/schemas/chatcompletions.go#L24)        | ❌        | Reasoning parameters ([Bifrost docs](/providers/reasoning), [OpenAI docs](https://platform.openai.com/docs/api-reference/chat/create#chat-create-reasoning))                                                  |
| `user`                  | string                                                                                            | ❌        | **Truncated to 64 chars**                                                                                                                                                                                     |
| `metadata`              | [object](https://github.com/maximhq/bifrost/blob/main/core/schemas/chatcompletions.go#L27)        | ❌        | Custom metadata                                                                                                                                                                                               |
| `store`                 | bool                                                                                              | ❌        | **Filtered for non-OpenAI routing**                                                                                                                                                                           |
| `service_tier`          | string                                                                                            | ❌        | **Filtered for non-OpenAI routing**                                                                                                                                                                           |
| `prompt_cache_key`      | string                                                                                            | ❌        | **Filtered for non-OpenAI routing**                                                                                                                                                                           |
| `prediction`            | [object](https://github.com/maximhq/bifrost/blob/main/core/schemas/chatcompletions.go#L28)        | ❌        | Predicted output for acceleration                                                                                                                                                                             |
| `audio`                 | [object](https://github.com/maximhq/bifrost/blob/main/core/schemas/chatcompletions.go#L29)        | ❌        | Audio output config                                                                                                                                                                                           |
| `modalities`            | [array](https://github.com/maximhq/bifrost/blob/main/core/schemas/chatcompletions.go#L30)         | ❌        | Response modalities (text, audio)                                                                                                                                                                             |

***

* **Reasoning:** OpenAI supports `reasoning.effort` (`minimal`, `low`, `medium`, `high`) and `reasoning.max_tokens` - both passed through directly. When routing to other providers, `"minimal"` effort is converted to `"low"` for compatibility. See [Bifrost reasoning docs](/providers/reasoning).
* **Messages:** All message roles are supported: `system`, `user`, `assistant`, `tool`, `developer` (treated as system). Content types: text, images via URL (`image_url`), audio input (`input_audio`). Tool messages include a `tool_call_id`.
* **Tools:** Standard OpenAI tool format with strict mode support. Tool choice: `"auto"`, `"none"`, `"required"`, or specific tool by name.
* **Responses:** Passed through in standard OpenAI format. Finish reasons: `stop`, `length`, `tool_calls`, `content_filter`. Usage includes token counts and optionally cached/reasoning token details.
* **Streaming:** Server-Sent Events format with `delta.content`, `delta.tool_calls`, `finish_reason`, and `usage` (final chunk only, automatically included by Bifrost). `stream_options: { include_usage: true }` is set by default for all streaming calls.
* **Cache Control:** `cache_control` fields are stripped from messages, their content blocks, and tools before sending.
* **Token Enforcement:** `max_completion_tokens` is enforced to have a minimum of 16. Values below 16 are automatically set to 16.
* **Special handling:** `user` field is truncated to 64 characters; `prompt_cache_key`, `store`, `service_tier` are filtered when routing to non-OpenAI providers

***

# 2. Responses API

The Responses API is OpenAI's structured output API.

**Request Parameters**

| Parameter              | Type                                                                                         | Required | Notes                                                                                                                                                                                                        |
| ---------------------- | -------------------------------------------------------------------------------------------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `model`                | string                                                                                       | ✅        | Model identifier                                                                                                                                                                                             |
| `input`                | string/[array](https://github.com/maximhq/bifrost/blob/main/core/schemas/responses.go#L40)   | ✅        | Text or [`ContentBlock`](https://github.com/maximhq/bifrost/blob/main/core/schemas/responses.go#L500) array ([docs](https://platform.openai.com/docs/api-reference/responses/create#responses-create-input)) |
| `max_output_tokens`    | int                                                                                          | ✅        | Maximum output length                                                                                                                                                                                        |
| `background`           | bool                                                                                         | ❌        | Run request in background mode                                                                                                                                                                               |
| `conversation`         | string                                                                                       | ❌        | Conversation ID for continuing a conversation                                                                                                                                                                |
| `include`              | array                                                                                        | ❌        | Array of fields to include in response (e.g., `"web_search_call.action.sources"`)                                                                                                                            |
| `instructions`         | string                                                                                       | ❌        | System instructions                                                                                                                                                                                          |
| `max_tool_calls`       | int                                                                                          | ❌        | Maximum number of tool calls                                                                                                                                                                                 |
| `metadata`             | [object](https://github.com/maximhq/bifrost/blob/main/core/schemas/responses.go#L94)         | ❌        | Custom metadata                                                                                                                                                                                              |
| `parallel_tool_calls`  | bool                                                                                         | ❌        | Allow multiple simultaneous tool calls                                                                                                                                                                       |
| `previous_response_id` | string                                                                                       | ❌        | ID of previous response to continue from                                                                                                                                                                     |
| `prompt_cache_key`     | string                                                                                       | ❌        | Prompt caching key                                                                                                                                                                                           |
| `reasoning`            | [object](https://github.com/maximhq/bifrost/blob/main/core/schemas/responses.go#L238)        | ❌        | [`ResponsesParametersReasoning`](https://github.com/maximhq/bifrost/blob/main/core/schemas/responses.go#L238) configuration ([Bifrost docs](/providers/reasoning))                                           |
| `safety_identifier`    | string                                                                                       | ❌        | Safety identifier for content filtering                                                                                                                                                                      |
| `service_tier`         | string                                                                                       | ❌        | Service tier for the request                                                                                                                                                                                 |
| `stream_options`       | [object](https://github.com/maximhq/bifrost/blob/main/core/schemas/responses.go#L116)        | ❌        | [`ResponsesStreamOptions`](https://github.com/maximhq/bifrost/blob/main/core/schemas/responses.go#L116) configuration                                                                                        |
| `store`                | bool                                                                                         | ❌        | Store the response for later retrieval                                                                                                                                                                       |
| `temperature`          | float                                                                                        | ❌        | Sampling temperature                                                                                                                                                                                         |
| `text`                 | [object](https://github.com/maximhq/bifrost/blob/main/core/schemas/responses.go#L120)        | ❌        | [`ResponsesTextConfig`](https://github.com/maximhq/bifrost/blob/main/core/schemas/responses.go#L120) for output formatting                                                                                   |
| `top_logprobs`         | int                                                                                          | ❌        | Number of log probabilities to return per token                                                                                                                                                              |
| `top_p`                | float                                                                                        | ❌        | Nucleus sampling parameter                                                                                                                                                                                   |
| `tool_choice`          | string/[object](https://github.com/maximhq/bifrost/blob/main/core/schemas/responses.go#L969) | ❌        | [`ResponsesToolChoice`](https://github.com/maximhq/bifrost/blob/main/core/schemas/responses.go#L969) strategy                                                                                                |
| `tools`                | [array](https://github.com/maximhq/bifrost/blob/main/core/schemas/responses.go#L1050)        | ❌        | [`ResponsesTool`](https://github.com/maximhq/bifrost/blob/main/core/schemas/responses.go#L1050) objects ([docs](https://platform.openai.com/docs/api-reference/responses/create#responses-create-tools))     |
| `truncation`           | string                                                                                       | ❌        | Truncation strategy (`auto` or `off`)                                                                                                                                                                        |
| `user`                 | string                                                                                       | ❌        | **Truncated to 64 chars**                                                                                                                                                                                    |

***

**Special Message Handling (gpt-oss vs other models):**

OpenAI models handle reasoning differently depending on the model family:

* **Non-gpt-oss models** (GPT-4o, o1, etc.): Send reasoning as **summaries**. Reasoning-only messages (with no summary and only content blocks) are filtered out since these models don't support reasoning content blocks in the request format.
* **gpt-oss models**: Send reasoning as **content blocks**. Reasoning summaries in the request are converted to content blocks since gpt-oss expects reasoning as structured blocks, not summaries.

This conversion ensures compatibility across different model architectures for the structured Responses API. See [Bifrost reasoning docs](/providers/reasoning) for detailed reasoning handling.

**Token & Parameter Enforcement:**

* `max_output_tokens` is enforced to have a minimum of 16. Values below 16 are automatically set to 16.
* `reasoning.max_tokens` field is automatically removed from JSON output (OpenAI Responses API doesn't accept it).

**Other conversions:**

* Action types `zoom` and `region` are converted to `screenshot`
* `cache_control` fields are stripped from messages and tools
* Unsupported tool types are silently filtered (only these are supported: `function`, `file_search`, `computer_use_preview`, `web_search`, `mcp`, `code_interpreter`, `image_generation`, `local_shell`, `custom`, `web_search_preview`)

**Response:** Includes `id`, `status` (`completed`, `incomplete`, `pending`, `error`), `output` array with message content, and token `usage`.

**Streaming:** Server-Sent Events with types: `response.created`, `response.in_progress`, `response.output_item.added`, `response.content_part.added`, `response.output_text.delta`, `response.function_call_arguments.delta`, `response.completed`, `response.incomplete`. `stream_options: { include_usage: true }` is set by default for all streaming calls.

***

# 3. Text Completions (Legacy)

<Warning>
  Text Completions is a legacy API. Use Chat Completions for new implementations.
</Warning>

**Request Parameters**

| Parameter     | Type         | Required | Notes                     |
| ------------- | ------------ | -------- | ------------------------- |
| `model`       | string       | ✅        | Model identifier          |
| `prompt`      | string/array | ✅        | Completion prompt(s)      |
| `max_tokens`  | int          | ❌        | Maximum output tokens     |
| `temperature` | float        | ❌        | Sampling temperature      |
| `top_p`       | float        | ❌        | Nucleus sampling          |
| `stop`        | string/array | ❌        | Stop sequences            |
| `user`        | string       | ❌        | **Truncated to 64 chars** |

***

* Array prompts generate multiple completions. Finish reasons: `stop` or `length`. Streaming uses SSE format. `stream_options: { include_usage: true }` is set by default for streaming calls.
* `user` field is truncated to 64 characters or set to nil if it exceeds the limit.

***

# 4. Embeddings

**Request Parameters**

| Parameter         | Type                                                                                       | Required | Notes                                                                                                               |
| ----------------- | ------------------------------------------------------------------------------------------ | -------- | ------------------------------------------------------------------------------------------------------------------- |
| `model`           | string                                                                                     | ✅        | Model identifier                                                                                                    |
| `input`           | string/[array](https://github.com/maximhq/bifrost/blob/main/core/schemas/embedding.go#L12) | ✅        | Text(s) to embed ([docs](https://platform.openai.com/docs/api-reference/embeddings/create#embeddings-create-input)) |
| `encoding_format` | string                                                                                     | ❌        | `float` or `base64`                                                                                                 |
| `dimensions`      | int                                                                                        | ❌        | Output embedding dimensions                                                                                         |
| `user`            | string                                                                                     | ❌        | **NOT truncated** (unlike chat/text)                                                                                |

***

* No streaming support. Returns [`embedding`](https://github.com/maximhq/bifrost/blob/main/core/schemas/embedding.go#L30) array with usage counts.

***

# 5. Speech (Text-to-Speech)

**Request Parameters**

| Parameter         | Type   | Required | Notes                                   |
| ----------------- | ------ | -------- | --------------------------------------- |
| `model`           | string | ✅        | `tts-1` or `tts-1-hd`                   |
| `input`           | string | ✅        | Text to convert to speech               |
| `voice`           | string | ✅        | alloy, echo, fable, onyx, nova, shimmer |
| `response_format` | string | ❌        | mp3, opus, aac, flac, wav, pcm          |
| `speed`           | float  | ❌        | 0.25 to 4.0 (default 1.0)               |

***

* Returns raw binary audio. Streaming supported in SSE format (base64 chunks), but not all models support streaming. `stream_options: { include_usage: true }` is set by default for streaming calls.

***

# 6. Transcriptions (Speech-to-Text)

<Warning>
  Requests use **multipart/form-data**, not JSON.
</Warning>

**Request Parameters**

| Parameter         | Type   | Required | Notes                               |
| ----------------- | ------ | -------- | ----------------------------------- |
| `file`            | binary | ✅        | Audio file (multipart form-data)    |
| `model`           | string | ✅        | `whisper-1`                         |
| `language`        | string | ❌        | ISO-639-1 language code             |
| `prompt`          | string | ❌        | Optional prompt for context         |
| `temperature`     | float  | ❌        | Sampling temperature                |
| `response_format` | string | ❌        | json, text, srt, vtt, verbose\_json |

***

* **Supported audio formats:** mp3, mp4, mpeg, mpga, m4a, wav, webm
* **Response:** Includes `text`, `task`, `language`, `duration`, and optionally word-level timing. Streaming supported in SSE format. `stream_options: { include_usage: true }` is set by default for streaming calls.

***

# 7. Image Generation

**Request Parameters**

| Parameter            | Type   | Required | Notes                                                                                                                     |
| -------------------- | ------ | -------- | ------------------------------------------------------------------------------------------------------------------------- |
| `model`              | string | ✅        | Model identifier (e.g., `dall-e-3`)                                                                                       |
| `prompt`             | string | ✅        | Text description of the image to generate                                                                                 |
| `n`                  | int    | ❌        | Number of images to generate (1-10)                                                                                       |
| `size`               | string | ❌        | Image size: `"256x256"`, `"512x512"`, `"1024x1024"`, `"1792x1024"`, `"1024x1792"`, `"1536x1024"`, `"1024x1536"`, `"auto"` |
| `quality`            | string | ❌        | Image quality: `"auto"`, `"high"`, `"medium"`, `"low"`, `"hd"`, `"standard"`                                              |
| `style`              | string | ❌        | Image style: `"natural"`, `"vivid"`                                                                                       |
| `response_format`    | string | ❌        | Response format: `"url"` or `"b64_json"`                                                                                  |
| `background`         | string | ❌        | Background: `"transparent"`, `"opaque"`, `"auto"`                                                                         |
| `output_format`      | string | ❌        | Output format: `"png"`, `"webp"`, `"jpeg"`                                                                                |
| `output_compression` | int    | ❌        | Compression level (0-100%)                                                                                                |
| `partial_images`     | int    | ❌        | Number of partial images (0-3)                                                                                            |
| `moderation`         | string | ❌        | Moderation level: `"low"`, `"auto"`                                                                                       |
| `user`               | string | ❌        | User identifier                                                                                                           |

***

**Request Conversion**

OpenAI is the baseline schema for image generation. Parameters are passed through with minimal conversion:

* **Model & Prompt**: `bifrostReq.Model` → `req.Model`, `bifrostReq.Prompt` → `req.Prompt`
* **Parameters**: All fields from `bifrostReq` (`ImageGenerationParameters`) are embedded directly into the OpenAI request struct via struct embedding. No field mapping or transformation is performed.
* **Streaming**: When streaming is requested, `stream: true` is set in the request body.

**Response Conversion**

* **Non-streaming**: OpenAI responses are unmarshaled directly into `BifrostImageGenerationResponse` since Bifrost's response schema is a superset of OpenAI's format. All fields are passed through as-is.
* **Streaming**: OpenAI streaming responses use Server-Sent Events (SSE) format with event types:

  * `image_generation.partial_image`: Intermediate image chunks with `b64_json` data
  * `image_generation.completed`: Final chunk for each image with usage information
  * `error`: Error events

  Each chunk includes:

  * `type`: Event type
  * `sequence_number`: Sequence number of the chunk
  * `partial_image_index`: Image index (0-N) for partial images
  * `b64_json`: Base64-encoded image data (pointer, may be nil)
  * `usage`: Token usage (only in completed events)
  * `created_at`, `size`, `quality`, `background`, `output_format`: Additional metadata

  Bifrost converts these to `BifrostImageGenerationStreamResponse` chunks with:

  * Per-image `chunkIndex` tracking for proper ordering within each image
  * `Index` field indicating which image (0-N) the chunk belongs to
  * `PartialImageIndex` set only for partial images (not completed events)
  * Usage information attached to completed chunks
  * Latency tracking per chunk

**Endpoint**: `/v1/images/generations`

***

# 8. Image Edit

<Warning>
  Requests use **multipart/form-data**, not JSON.
</Warning>

**Request Parameters**

| Parameter            | Type   | Required | Notes                                                                                       |
| -------------------- | ------ | -------- | ------------------------------------------------------------------------------------------- |
| `model`              | string | ✅        | Model identifier                                                                            |
| `prompt`             | string | ✅        | Text description of the edit                                                                |
| `image[]`            | binary | ✅        | Image file(s) to edit (multipart form-data, supports multiple images)                       |
| `mask`               | binary | ❌        | Mask image file (multipart form-data)                                                       |
| `n`                  | int    | ❌        | Number of images to generate (1-10)                                                         |
| `size`               | string | ❌        | Image size: `"256x256"`, `"512x512"`, `"1024x1024"`, `"1536x1024"`, `"1024x1536"`, `"auto"` |
| `quality`            | string | ❌        | Image quality: `"auto"`, `"high"`, `"medium"`, `"low"`, `"standard"`                        |
| `response_format`    | string | ❌        | Response format: `"url"` or `"b64_json"`                                                    |
| `background`         | string | ❌        | Background: `"transparent"`, `"opaque"`, `"auto"`                                           |
| `input_fidelity`     | string | ❌        | Input fidelity: `"low"`, `"high"`                                                           |
| `partial_images`     | int    | ❌        | Number of partial images (0-3)                                                              |
| `output_format`      | string | ❌        | Output format: `"png"`, `"webp"`, `"jpeg"`                                                  |
| `output_compression` | int    | ❌        | Compression level (0-100%)                                                                  |
| `user`               | string | ❌        | User identifier                                                                             |
| `stream`             | bool   | ❌        | Enable streaming response                                                                   |

***

**Request Conversion**

* **Model & Input**: `bifrostReq.Model` → `req.Model`, `bifrostReq.Input.Images` → `req.Input.Images`, `bifrostReq.Input.Prompt` → `req.Input.Prompt`
* **Parameters**: All fields from `bifrostReq.Params` (`ImageEditParameters`) are embedded directly into the OpenAI request struct via struct embedding. No field mapping or transformation is performed.
* **Multipart Form Data**: The request is serialized as `multipart/form-data`:
  * **Model & Prompt**: Written as form fields (`model`, `prompt`)
  * **Images**: Each image in `Input.Images` is written as a separate `image[]` field with proper MIME type detection (`image/jpeg`, `image/webp`, `image/png`) and Content-Type headers
  * **Mask**: If present, written as a `mask` field with MIME type detection and appropriate filename (`mask.png`, `mask.jpg`, `mask.webp`)
  * **Optional Parameters**: All optional parameters (`n`, `size`, `quality`, `response_format`, `background`, `input_fidelity`, `partial_images`, `output_format`, `output_compression`, `user`) are written as form fields
  * **Integer Conversion**: Integer fields (`n`, `partial_images`, `output_compression`) are converted to strings using `strconv.Itoa`
  * **Streaming**: When streaming is requested, `stream: "true"` is written as a form field

**Response Conversion**

* **Non-streaming**: OpenAI responses are unmarshaled directly into `BifrostImageGenerationResponse` since Bifrost's response schema is a superset of OpenAI's format. All fields are passed through as-is.
* **Streaming**: OpenAI streaming responses use Server-Sent Events (SSE) format with event types:

  * `image_edit.partial_image`: Intermediate image chunks with `b64_json` data
  * `image_edit.completed`: Final chunk for each image with usage information
  * `error`: Error events

  Each chunk includes:

  * `type`: Event type (`image_edit.partial_image` or `image_edit.completed`)
  * `sequence_number`: Sequence number of the chunk
  * `partial_image_index`: Image index (0-N) for partial images
  * `b64_json`: Base64-encoded image data (pointer, may be nil)
  * `usage`: Token usage (only in completed events)

  Bifrost converts these to `BifrostImageGenerationStreamResponse` chunks with:

  * Per-image `chunkIndex` tracking for proper ordering within each image
  * `Index` field indicating which image (0-N) the chunk belongs to
  * `PartialImageIndex` set only for partial images (not completed events)
  * Usage information attached to completed chunks
  * Latency tracking per chunk
  * Robust handling of interleaved chunks using incomplete image tracking

**Endpoint**: `/v1/images/edits`

***

# 9. Image Variation

<Warning>
  Requests use **multipart/form-data**, not JSON.
</Warning>

**Request Parameters**

| Parameter         | Type   | Required | Notes                                                                                                                     |
| ----------------- | ------ | -------- | ------------------------------------------------------------------------------------------------------------------------- |
| `model`           | string | ✅        | Model identifier                                                                                                          |
| `image`           | binary | ✅        | Image file to create variations from (multipart form-data)                                                                |
| `n`               | int    | ❌        | Number of images to generate (1-10)                                                                                       |
| `size`            | string | ❌        | Image size: `"256x256"`, `"512x512"`, `"1024x1024"`, `"1792x1024"`, `"1024x1792"`, `"1536x1024"`, `"1024x1536"`, `"auto"` |
| `response_format` | string | ❌        | Response format: `"url"` or `"b64_json"`                                                                                  |
| `user`            | string | ❌        | User identifier                                                                                                           |

***

**Request Conversion**

* **Model & Input**: `bifrostReq.Model` → `req.Model`, `bifrostReq.Input.Image.Image` → `req.Input.Image.Image`
* **Parameters**: All fields from `bifrostReq.Params` (`ImageVariationParameters`) are embedded directly into the OpenAI request struct via struct embedding. No field mapping or transformation is performed.
* **Multipart Form Data**: The request is serialized as `multipart/form-data`:
  * **Model**: Written as form field (`model`)
  * **Image**: The image is written as an `image` field with proper MIME type detection (`image/jpeg`, `image/webp`, `image/png`) and Content-Type headers. If MIME type cannot be detected, defaults to `image/png`
  * **Optional Parameters**: All optional parameters (`n`, `size`, `response_format`, `user`) are written as form fields
  * **Integer Conversion**: Integer field (`n`) is converted to string using `strconv.Itoa`
* **Multiple Images**: Additional images beyond the first one (if present in `ExtraParams["images"]`) are stored in `ExtraParams` but only the first image is sent to OpenAI (OpenAI API only supports single image input)

**Response Conversion**

* **Non-streaming**: OpenAI responses are unmarshaled directly into `BifrostImageVariationResponse` (which is a type alias for `BifrostImageGenerationResponse`). All fields are passed through as-is.
* **Streaming**: Not supported for image variation requests.

**Endpoint**: `/v1/images/variations`

***

# 10. Files API

## Upload

**Request Parameters**

| Parameter  | Type   | Required | Notes                                    |
| ---------- | ------ | -------- | ---------------------------------------- |
| `file`     | binary | ✅        | File to upload (multipart form-data)     |
| `purpose`  | string | ✅        | batch, fine-tune, or assistants          |
| `filename` | string | ❌        | Custom filename (defaults to file.jsonl) |

Response: [`FileObject`](https://github.com/maximhq/bifrost/blob/main/core/schemas/files.go#L40) with `id`, `bytes`, `created_at`, `filename`, `purpose`, `status` ([docs](https://platform.openai.com/docs/api-reference/files/create))

## List Files

**Query Parameters**

| Parameter | Type   | Required | Notes             |
| --------- | ------ | -------- | ----------------- |
| `purpose` | string | ❌        | Filter by purpose |
| `limit`   | int    | ❌        | Results per page  |
| `after`   | string | ❌        | Pagination cursor |
| `order`   | string | ❌        | asc or desc       |

Cursor-based pagination with `has_more` flag.

## Retrieve / Delete / Content

Operations:

* GET `/v1/files/{file_id}` - Retrieve file metadata
* DELETE `/v1/files/{file_id}` - Delete file
* GET `/v1/files/{file_id}/content` - Download file content

***

# 11. Batch API

## Create Batch

**Request Parameters**

| Parameter           | Type                                                                             | Required    | Notes                                                                                                                     |
| ------------------- | -------------------------------------------------------------------------------- | ----------- | ------------------------------------------------------------------------------------------------------------------------- |
| `input_file_id`     | string                                                                           | Conditional | File ID OR requests array (not both)                                                                                      |
| `requests`          | [array](https://github.com/maximhq/bifrost/blob/main/core/schemas/batch.go#L75)  | Conditional | [`BatchRequestItem`](https://github.com/maximhq/bifrost/blob/main/core/schemas/batch.go#L31) objects (converted to JSONL) |
| `endpoint`          | string                                                                           | ✅           | Target endpoint (e.g., /v1/chat/completions)                                                                              |
| `completion_window` | string                                                                           | ❌           | 24h (default)                                                                                                             |
| `metadata`          | [object](https://github.com/maximhq/bifrost/blob/main/core/schemas/batch.go#L89) | ❌           | Custom metadata                                                                                                           |

**Response:** [`BifrostBatchCreateResponse`](https://github.com/maximhq/bifrost/blob/main/core/schemas/batch.go#L91) with `id`, `endpoint`, `input_file_id`, `status`, `created_at`, `request_counts` ([docs](https://platform.openai.com/docs/api-reference/batch/create)). Statuses: [`BatchStatus`](https://github.com/maximhq/bifrost/blob/main/core/schemas/batch.go#L5) (validating, failed, in\_progress, finalizing, completed, expired, cancelling, cancelled)

## List Batches

**Query Parameters**

| Parameter | Type   | Required | Notes             |
| --------- | ------ | -------- | ----------------- |
| `limit`   | int    | ❌        | Results per page  |
| `after`   | string | ❌        | Pagination cursor |

## Retrieve / Cancel Batch

Operations:

* GET `/v1/batches/{batch_id}` - Get batch [`BifrostBatchRetrieveResponse`](https://github.com/maximhq/bifrost/blob/main/core/schemas/batch.go#L167) ([docs](https://platform.openai.com/docs/api-reference/batch/retrieve))
* POST `/v1/batches/{batch_id}/cancel` - Cancel batch ([docs](https://platform.openai.com/docs/api-reference/batch/cancel))

## Get Results

1. Batch must be `completed` (has `output_file_id`)
2. Download output file via Files API
3. Parse JSONL - each [`BatchResultItem`](https://github.com/maximhq/bifrost/blob/main/core/schemas/batch.go#L254): `{id, custom_id, response: {status_code, body}}`

***

# 12. List Models

GET `/v1/models` - Lists available models with metadata. Model IDs in Bifrost responses are prefixed with `openai/` (e.g., `openai/gpt-4o`). Results are aggregated from all configured API keys. No request body or parameters required.

***

# 13. Video Generation

## Generate (`POST /v1/videos`)

**Request Parameters**

| Parameter         | Type   | Required | Notes                                                                                                                           |
| ----------------- | ------ | -------- | ------------------------------------------------------------------------------------------------------------------------------- |
| `model`           | string | ✅        | e.g., `sora-2`                                                                                                                  |
| `prompt`          | string | ✅        | Text description of the video                                                                                                   |
| `input_reference` | string | ❌        | Input image for image-to-video. **Must be a base64 data URL** (e.g., `data:image/png;base64,...`). Plain URLs are not accepted. |
| `seconds`         | string | ❌        | Duration in seconds                                                                                                             |
| `size`            | string | ❌        | Resolution: `720x1280` (default), `1280x720`, `1024x1792`, `1792x1024`                                                          |

**Response**: [`BifrostVideoGenerationResponse`](https://github.com/maximhq/bifrost/blob/main/core/schemas/videos.go) - `id`, `status`, `model`, `prompt`, `created_at`

**Job Statuses**: `queued` → `in_progress` → `completed` / `failed`

## Retrieve / Download / Delete / List / Remix

| Operation  | Endpoint                      | Notes                                   |
| ---------- | ----------------------------- | --------------------------------------- |
| Get status | `GET /v1/videos/{id}`         | Poll until `status: completed`          |
| Download   | `GET /v1/videos/{id}/content` | Returns raw video bytes                 |
| Delete     | `DELETE /v1/videos/{id}`      | Removes video job                       |
| List jobs  | `GET /v1/videos`              | Query params: `after`, `limit`, `order` |
| Remix      | `POST /v1/videos/{id}/remix`  | Body: `{"prompt": "..."}`               |

***

## Common Error Codes

HTTP Status → Error Type mapping:

* `400` - `invalid_request_error`
* `401` - `authentication_error`
* `403` - `permission_error`
* `404` - `not_found_error`
* `429` - `rate_limit_error`
* `500` - `api_error`
