# How CCX Messages, Chat, Responses, Gemini, and Images Channels Differ: Protocol & Implementation Guide

> Understand CCX channel differences: Messages, Chat, Responses, Gemini, and Images. Explore distinct API protocols, authentication, and Go handler implementations for seamless integration.

- Repository: [Benedict King/ccx](https://github.com/BenedictKing/ccx)
- Tags: protocol-implementation-guide
- Published: 2026-05-29

---

**In CCX, the five channels differ primarily by their upstream protocols: Messages uses Anthropic's Claude Messages API, Chat uses OpenAI's Chat Completions, Responses uses OpenAI's legacy Completions endpoint, Gemini uses Google's Gemini API, and Images uses OpenAI's Image generation/editing endpoints—each requiring distinct authentication headers, request bodies, and response parsers as implemented in their dedicated Go handler files.**

CCX (Cross‑Channel eXchange) is an open‑source proxy that unifies large language model APIs under a common routing layer. Understanding the specific protocol differences between the **Messages, Chat, Responses, Gemini, and Images channels** is critical for configuring upstream providers and troubleshooting integration errors. This guide examines the implementation details from the [BenedictKing/ccx](https://github.com/BenedictKing/ccx) repository, including exact handler file paths and runnable request examples.

## Messages Channel: Anthropic Claude Protocol

The **Messages** channel implements the Anthropic Messages API for Claude models. Unlike standard OpenAI‑compatible endpoints, this channel requires the `anthropic-version` header and uses Claude's native message structure.

Key implementation details in [`backend-go/internal/handlers/messages/channels.go`](https://github.com/BenedictKing/ccx/blob/main/backend-go/internal/handlers/messages/channels.go):
- **Endpoint**: `POST /v1/messages`
- **Required Headers**: `Authorization: Bearer <key>` and `anthropic-version: 2023-06-01`
- **Request Body**: Uses a `messages` array with `role` and `content` fields, but follows Claude's formatting conventions
- **Response Structure**: Returns `type: "message"` with `role` and `content` arrays, distinct from OpenAI's `choices` wrapper

```bash
curl -X POST http://localhost:8080/v1/messages \
  -H "Authorization: Bearer $CLAUDE_API_KEY" \
  -H "Content-Type: application/json" \
  -H "anthropic-version: 2023-06-01" \
  -d '{
        "model":"claude-3-5-sonnet-20240620",
        "messages":[
          {"role":"user","content":"Explain quantum tunneling in one sentence."}
        ],
        "max_tokens":256
      }'

```

## Chat Channel: OpenAI Chat Completions

The **Chat** channel handles OpenAI's standard Chat Completions protocol, which has become the industry default for conversational AI. This is the most commonly used channel for modern GPT models.

Implementation resides in [`backend-go/internal/handlers/chat/channels.go`](https://github.com/BenedictKing/ccx/blob/main/backend-go/internal/handlers/chat/channels.go):
- **Endpoint**: `POST /v1/chat/completions`
- **Authentication**: Standard `Authorization: Bearer <key>`
- **Request Body**: JSON with `messages` array containing objects with `role` (`system`, `user`, `assistant`) and `content`
- **Response Format**: Returns `choices[0].message` structure
- **Streaming**: Supports `stream=true` for Server‑Sent Events (SSE)

```bash
curl -X POST http://localhost:8080/v1/chat/completions \
  -H "Authorization: Bearer $OPENAI_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
        "model":"gpt-4o-mini",
        "messages":[
          {"role":"system","content":"You are a helpful assistant."},
          {"role":"user","content":"Write a haiku about spring."}
        ],
        "temperature":0.7
      }'

```

## Responses Channel: OpenAI Legacy Completions

The **Responses** channel corresponds to OpenAI's legacy Completions API (not Chat). This protocol differs significantly from the Chat channel by using raw prompt strings instead of structured message arrays.

Found in [`backend-go/internal/handlers/responses/channels.go`](https://github.com/BenedictKing/ccx/blob/main/backend-go/internal/handlers/responses/channels.go):
- **Endpoint**: `POST /v1/completions`
- **Request Body**: Uses `prompt` field (string or array of strings) rather than `messages`
- **Response Format**: Returns `choices[0].text` without `role` fields, providing only the generated text completion
- **Use Case**: Text completion workflows that predate conversational formats

```bash
curl -X POST http://localhost:8080/v1/completions \
  -H "Authorization: Bearer $OPENAI_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
        "model":"gpt-4o-mini",
        "prompt":"Summarize the plot of \"Pride and Prejudice\" in 30 words.",
        "max_tokens":150
      }'

```

## Gemini Channel: Google Gemini API

The **Gemini** channel provides a bridge to Google's Gemini models via the `v1beta` API. This channel handles protocol translation between Google's native format and OpenAI‑compatible responses.

Implementation in [`backend-go/internal/handlers/gemini/channels.go`](https://github.com/BenedictKing/ccx/blob/main/backend-go/internal/handlers/gemini/channels.go):
- **Endpoint**: `POST /v1beta/models/{model}:generateContent`
- **Authentication**: Uses `x-goog-api-key` header instead of Bearer tokens
- **Model Listing**: Queries `/v1beta/models` and converts the response to OpenAI‑compatible `object: "list"` JSON format
- **Request Structure**: Uses Gemini's `contents` array with `parts` objects containing text

```bash
curl -X POST http://localhost:8080/v1beta/models/gemini-1.5-pro:generateContent \
  -H "x-goog-api-key: $GEMINI_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
        "contents":[{"role":"user","parts":[{"text":"What is the capital of Canada?"}]}],
        "generationConfig":{"temperature":0.5}
      }'

```

To retrieve models through CCX's unified interface:

```bash
curl -X POST http://localhost:8080/gemini/channels/0/models \
  -H "Content-Type: application/json" \
  -d '{"key":"'"$GEMINI_API_KEY"'"}'

```

## Images Channel: OpenAI Image Operations

The **Images** channel supports OpenAI's DALL‑E style image generation, editing, and variations. This channel has strict service type requirements and handles multipart form data for image uploads.

Located in [`backend-go/internal/handlers/images/channels.go`](https://github.com/BenedictKing/ccx/blob/main/backend-go/internal/handlers/images/channels.go):
- **Service Type Restriction**: Only accepts upstream configurations with `serviceType: "openai"`
- **Endpoints**: `/v1/images/generations`, `/v1/images/edits`, `/v1/images/variations`
- **Content Types**: JSON for generations, `multipart/form-data` for edits and variations
- **Authentication**: Standard OpenAI Bearer token only

**Image Generation** (JSON):

```bash
curl -X POST http://localhost:8080/v1/images/generations \
  -H "Authorization: Bearer $OPENAI_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
        "prompt":"A futuristic cityscape at night, cyberpunk style",
        "n":1,
        "size":"1024x1024"
      }'

```

**Image Editing** (multipart/form-data):

```bash
curl -X POST http://localhost:8080/v1/images/edits \
  -H "Authorization: Bearer $OPENAI_API_KEY" \
  -F "image=@original.png" \
  -F "mask=@mask.png" \
  -F 'prompt=Add a flying car' \
  -F "n=1"

```

## Authentication & Header Differences

Each channel enforces distinct authentication patterns:

- **Messages**: Requires `Authorization: Bearer <key>` **and** `anthropic-version: 2023-06-01`
- **Chat, Responses, Images**: Standard `Authorization: Bearer <key>` (OpenAI‑compatible)
- **Gemini**: Uses `x-goog-api-key: <key>` (Google‑specific header)

The [`backend-go/internal/config/config.go`](https://github.com/BenedictKing/ccx/blob/main/backend-go/internal/config/config.go) file defines the `UpstreamConfig` structure that stores these authentication credentials, while [`backend-go/internal/scheduler/channel_scheduler.go`](https://github.com/BenedictKing/ccx/blob/main/backend-go/internal/scheduler/channel_scheduler.go) manages channel‑specific routing and failover logic based on these upstream types.

## Request Structure Comparison

The five channels accept fundamentally different request payloads:

1. **Messages & Chat**: Both use `messages` arrays, but Messages requires Claude‑specific formatting and versioning
2. **Responses**: Uses legacy `prompt` strings instead of structured conversations
3. **Gemini**: Implements Google's `contents` array with nested `parts` objects
4. **Images**: Uses either JSON parameters (generations) or multipart form uploads (edits/variations)

Response parsing also varies: Messages returns Claude's native format, Chat returns `choices[0].message`, Responses returns `choices[0].text`, and Gemini responses are proxied with format conversion for model listings.

## Summary

- **Messages** ([`backend-go/internal/handlers/messages/channels.go`](https://github.com/BenedictKing/ccx/blob/main/backend-go/internal/handlers/messages/channels.go)): Anthropic Claude protocol requiring `anthropic-version` headers and native message structures
- **Chat** ([`backend-go/internal/handlers/chat/channels.go`](https://github.com/BenedictKing/ccx/blob/main/backend-go/internal/handlers/chat/channels.go)): Standard OpenAI Chat Completions with `messages` arrays and streaming support
- **Responses** ([`backend-go/internal/handlers/responses/channels.go`](https://github.com/BenedictKing/ccx/blob/main/backend-go/internal/handlers/responses/channels.go)): OpenAI legacy Completions using `prompt` strings and returning plain text
- **Gemini** ([`backend-go/internal/handlers/gemini/channels.go`](https://github.com/BenedictKing/ccx/blob/main/backend-go/internal/handlers/gemini/channels.go)): Google Gemini API with `x-goog-api-key` authentication and `v1beta` endpoints, includes OpenAI‑compatible model list conversion
- **Images** ([`backend-go/internal/handlers/images/channels.go`](https://github.com/BenedictKing/ccx/blob/main/backend-go/internal/handlers/images/channels.go)): OpenAI Image API restricted to `serviceType: "openai"`, supporting both JSON and multipart form data

## Frequently Asked Questions

### Which CCX channel should I use for Claude 3.5 Sonnet?

Use the **Messages** channel. According to [`backend-go/internal/handlers/messages/channels.go`](https://github.com/BenedictKing/ccx/blob/main/backend-go/internal/handlers/messages/channels.go), this channel implements the Anthropic Messages API and is the only route that properly handles Claude's `anthropic-version` header requirements and message‑based conversation format.

### Why does the Gemini channel require a different authentication header?

The **Gemini** channel communicates directly with Google's API infrastructure, which uses `x-goog-api-key` instead of the Bearer token scheme standardized by OpenAI. The handler in [`backend-go/internal/handlers/gemini/channels.go`](https://github.com/BenedictKing/ccx/blob/main/backend-go/internal/handlers/gemini/channels.go) manages this translation, forwarding requests to Google's `v1beta` endpoints while optionally converting responses to OpenAI‑compatible formats for upstream model listings.

### Can I use non‑OpenAI providers with the Images channel?

No. The **Images** channel explicitly requires `serviceType: "openai"` in the upstream configuration. As implemented in [`backend-go/internal/handlers/images/channels.go`](https://github.com/BenedictKing/ccx/blob/main/backend-go/internal/handlers/images/channels.go), this restriction ensures that only OpenAI‑compatible image endpoints (supporting generations, edits, and variations) are routed through this channel.

### What is the difference between the Chat and Responses channels?

**Chat** uses the modern OpenAI Chat Completions protocol with structured `messages` arrays containing `role` and `content` fields, returning assistant messages in `choices[0].message`. **Responses** uses the legacy Completions API, accepting a raw `prompt` string and returning generated text in `choices[0].text` without role metadata. Choose Chat for conversational agents and Responses for single‑turn text completion tasks.