# How to Use the OpenAI Responses API Endpoint Instead of Chat Completions in OmniRoute

> Learn how to use the OpenAI Responses API endpoint in OmniRoute for efficient input handling. Send input arrays instead of messages and leverage unified routing logic.

- Repository: [Diego Rodrigues de Sa e Souza/OmniRoute](https://github.com/diegosouzapw/OmniRoute)
- Tags: how-to-guide
- Published: 2026-08-01

---

**OmniRoute exposes the OpenAI Responses API at `POST /v1/responses`, allowing you to send `input[]` arrays instead of `messages[]` while reusing the same unified chat handler and routing logic that powers Chat Completions.**

The OmniRoute project (diegosouzapw/OmniRoute) implements the Responses API as a first-class alternative to the legacy Chat Completions interface. By routing requests to `/v1/responses` rather than `/v1/chat/completions`, you can leverage the modern `input[]` payload structure while maintaining full compatibility with OmniRoute’s provider-agnostic translation layer, Codex CLI integration, and unified streaming infrastructure.

## Architecture of the Responses API Route

### Route Definition and Entry Point

The Responses API surface is defined in [`src/app/api/v1/responses/route.ts`](https://github.com/diegosouzapw/OmniRoute/blob/main/src/app/api/v1/responses/route.ts). Unlike legacy routes that directly invoke provider-specific logic, this endpoint acts as a thin orchestration layer that prepares the request before delegating to the shared chat pipeline.

The route handler performs three critical operations before forwarding execution:

- **Injection guarding**: Parses and validates the JSON body via `withInjectionGuard` to prevent malformed payloads from reaching upstream providers.
- **Model resolution**: Invokes `withCodexPreferredModel` to determine if the requested model ID should be rewritten to the Codex namespace.
- **Transport negotiation**: Inspects the `Accept` header to decide between SSE streaming (`text/event-stream`) and standard JSON responses.

When the model resolves to a Codex provider, the route applies `resolveResponsesApiModel` from [`src/app/api/internal/codex-responses-ws/modelResolution.ts`](https://github.com/diegosouzapw/OmniRoute/blob/main/src/app/api/internal/codex-responses-ws/modelResolution.ts) to rewrite bare model IDs (e.g., `gpt-5.5`) to their Codex-prefixed equivalents (`codex-gpt-5.5`). This ensures the Codex CLI’s fallback paths function correctly without client-side configuration changes.

### Unified Chat Handler Integration

After preprocessing, the route invokes `handleChat` from [`src/sse/handlers/chat.ts`](https://github.com/diegosouzapw/OmniRoute/blob/main/src/sse/handlers/chat.ts). This unified handler auto-detects the request format—whether OpenAI Chat Completions, Anthropic Messages, Gemini, or **Responses**—and executes the appropriate translator.

Inside `handleChat`, the logic branches based on `apiFormat === "responses"`. When detected, the handler routes the payload through the OpenAI Responses translator (e.g., [`src/lib/providers/xai/translators/openai-responses.ts`](https://github.com/diegosouzapw/OmniRoute/blob/main/src/lib/providers/xai/translators/openai-responses.ts) for xAI targets) before executing the provider-specific request. The output is translated back to the Responses schema for the return journey, ensuring format consistency regardless of which upstream provider fulfills the request.

## Streaming and Keep-Alive Mechanisms

### Early Keep-Alive for SSE Streams

For clients that request streaming via `Accept: text/event-stream`, OmniRoute injects `withEarlyStreamKeepalive` from [`src/open-sse/utils/earlyStreamKeepalive.ts`](https://github.com/diegosouzapw/OmniRoute/blob/main/src/open-sse/utils/earlyStreamKeepalive.ts). This wrapper emits periodic keep-alive frames until the upstream provider produces its first token, preventing aggressive intermediate proxies or CLI clients from terminating connections during cold-start latency.

The keep-alive logic is particularly important for the Codex CLI integration, where the `codex-responses-ws` internal API expects persistent connections while waiting for model resolution and provider handshakes to complete.

## How to Migrate from Chat Completions to Responses

The primary difference between the two APIs is the payload structure: **Chat Completions** uses a `messages[]` array, while the **Responses API** uses an `input[]` array with an identical schema shape. OmniRoute handles this translation internally, but your client requests must conform to the Responses specification to hit the correct route.

### cURL Example (SSE Streaming)

```bash
curl -N -X POST \
  -H "Accept: text/event-stream" \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer $OMNIRoute_API_KEY" \
  -d '{
    "model": "gpt-5.5",
    "input": [{"role": "user", "content": "Explain quantum tunneling"}],
    "max_output_tokens": 256
  }' \
  https://your-omniroute-instance.com/v1/responses

```

### Node.js Example (JSON Response)

```javascript
const response = await fetch("https://your-omniroute-instance.com/v1/responses", {
  method: "POST",
  headers: {
    "Content-Type": "application/json",
    "Authorization": `Bearer ${process.env.OMNIRoute_API_KEY}`,
    "Accept": "application/json", // Omit for SSE
  },
  body: JSON.stringify({
    model: "gpt-5.5",
    input: [{ role: "user", content: "Explain quantum tunneling" }],
    max_output_tokens: 256,
  }),
});

const data = await response.json();
console.log(data);

```

### Python Example

```python
import os
import requests

url = "https://your-omniroute-instance.com/v1/responses"
headers = {
    "Authorization": f"Bearer {os.getenv('OMNIRoute_API_KEY')}",
    "Content-Type": "application/json",
}
payload = {
    "model": "gpt-5.5",
    "input": [{"role": "user", "content": "Explain quantum tunneling"}],
    "max_output_tokens": 256,
}

r = requests.post(url, json=payload, headers=headers)
print(r.json())

```

## Summary

- **Route Location**: The Responses API is implemented in [`src/app/api/v1/responses/route.ts`](https://github.com/diegosouzapw/OmniRoute/blob/main/src/app/api/v1/responses/route.ts) as a `POST` endpoint.
- **Payload Structure**: Use `input[]` instead of `messages[]`; OmniRoute translates this automatically to upstream provider formats.
- **Model Rewriting**: Bare model IDs are automatically rewritten to Codex-prefixed variants via [`src/app/api/internal/codex-responses-ws/modelResolution.ts`](https://github.com/diegosouzapw/OmniRoute/blob/main/src/app/api/internal/codex-responses-ws/modelResolution.ts) when applicable.
- **Streaming Support**: SSE is supported via the `Accept: text/event-stream` header, with `withEarlyStreamKeepalive` preventing premature connection drops.
- **Unified Handler**: All requests flow through [`src/sse/handlers/chat.ts`](https://github.com/diegosouzapw/OmniRoute/blob/main/src/sse/handlers/chat.ts), ensuring consistent behavior across Chat Completions and Responses APIs.

## Frequently Asked Questions

### What is the difference between the Responses API and Chat Completions in OmniRoute?

The Responses API uses an `input[]` payload structure and exposes the endpoint at `/v1/responses`, whereas Chat Completions uses `messages[]` at `/v1/chat/completions`. Functionally, both are handled by the same `handleChat` core in [`src/sse/handlers/chat.ts`](https://github.com/diegosouzapw/OmniRoute/blob/main/src/sse/handlers/chat.ts), but the Responses API provides a modernized interface that aligns with OpenAI’s latest specification while maintaining OmniRoute’s provider-agnostic routing.

### How does OmniRoute handle model resolution for the Responses API?

When a request arrives at the Responses endpoint, `withCodexPreferredModel` invokes `resolveResponsesApiModel` from [`src/app/api/internal/codex-responses-ws/modelResolution.ts`](https://github.com/diegosouzapw/OmniRoute/blob/main/src/app/api/internal/codex-responses-ws/modelResolution.ts). If the model maps to a Codex provider, the logic rewrites the bare model ID (e.g., `gpt-5.5`) to include the `codex-` prefix before forwarding the request to the unified handler. This happens transparently without requiring client-side changes.

### Can I use SSE streaming with the Responses API endpoint?

Yes. Set the `Accept` header to `text/event-stream` when calling `/v1/responses`. The route automatically wraps the request with `withEarlyStreamKeepalive` from [`src/open-sse/utils/earlyStreamKeepalive.ts`](https://github.com/diegosouzapw/OmniRoute/blob/main/src/open-sse/utils/earlyStreamKeepalive.ts), which emits periodic keep-alive frames until the upstream provider generates its first token. This prevents timeouts during provider cold-start or model resolution delays.

### Does the Responses API support all providers available in OmniRoute?

Yes. Because the Responses API routes through the unified `handleChat` handler, it inherits support for all configured providers including OpenAI, Anthropic, Gemini, and xAI. The handler detects the `apiFormat` as `"responses"` and invokes the appropriate translator (such as [`src/lib/providers/xai/translators/openai-responses.ts`](https://github.com/diegosouzapw/OmniRoute/blob/main/src/lib/providers/xai/translators/openai-responses.ts)) to convert the payload to the provider-specific schema before execution.