mirror of
https://github.com/tiennm99/claude-central-gateway.git
synced 2026-04-17 17:21:03 +00:00
- Project overview, system architecture, code standards - API reference with 15+ examples - Quick start guide with troubleshooting - Updated README with feature highlights and compatibility matrix
590 lines
12 KiB
Markdown
590 lines
12 KiB
Markdown
# API Reference
|
|
|
|
## Overview
|
|
|
|
Claude Central Gateway implements the Anthropic Messages API, making it a drop-in replacement for the official Anthropic API. All endpoints and request/response formats match the [Anthropic API specification](https://docs.anthropic.com/en/docs/about/api-overview).
|
|
|
|
## Endpoints
|
|
|
|
### POST /v1/messages
|
|
|
|
Create a message and get a response from the model.
|
|
|
|
#### Authentication
|
|
|
|
All requests to `/v1/messages` require authentication via the `x-api-key` header:
|
|
|
|
```bash
|
|
curl -X POST https://gateway.example.com/v1/messages \
|
|
-H "x-api-key: my-secret-token" \
|
|
-H "Content-Type: application/json" \
|
|
-d '{...}'
|
|
```
|
|
|
|
Alternatively, use `Authorization: Bearer` header:
|
|
|
|
```bash
|
|
curl -X POST https://gateway.example.com/v1/messages \
|
|
-H "Authorization: Bearer my-secret-token" \
|
|
-H "Content-Type: application/json" \
|
|
-d '{...}'
|
|
```
|
|
|
|
#### Request Body
|
|
|
|
```json
|
|
{
|
|
"model": "claude-sonnet-4-20250514",
|
|
"messages": [
|
|
{
|
|
"role": "user",
|
|
"content": [
|
|
{
|
|
"type": "text",
|
|
"text": "Hello, how are you?"
|
|
}
|
|
]
|
|
}
|
|
],
|
|
"max_tokens": 1024,
|
|
"stream": false,
|
|
"temperature": 0.7,
|
|
"top_p": 1.0,
|
|
"stop_sequences": null,
|
|
"system": "You are a helpful assistant.",
|
|
"tools": null,
|
|
"tool_choice": null
|
|
}
|
|
```
|
|
|
|
##### Request Parameters
|
|
|
|
| Parameter | Type | Required | Description |
|
|
|-----------|------|----------|-------------|
|
|
| `model` | string | Yes | Model identifier (e.g., `claude-sonnet-4-20250514`). Gateway maps to OpenAI model via `MODEL_MAP` env var. |
|
|
| `messages` | array | Yes | Array of message objects with conversation history. |
|
|
| `max_tokens` | integer | Yes | Maximum tokens to generate (1-4096 typical). |
|
|
| `stream` | boolean | No | If `true`, stream response as Server-Sent Events. Default: `false`. |
|
|
| `temperature` | number | No | Sampling temperature (0.0-1.0). Higher = more random. Default: `1.0`. |
|
|
| `top_p` | number | No | Nucleus sampling parameter (0.0-1.0). Default: `1.0`. |
|
|
| `stop_sequences` | array | No | Array of strings; generation stops when any is encountered. Max 5 sequences. |
|
|
| `system` | string or array | No | System prompt. String or array of text blocks. |
|
|
| `tools` | array | No | Array of tool definitions the model can call. |
|
|
| `tool_choice` | object | No | Constraints on which tool to use. |
|
|
|
|
##### Message Object
|
|
|
|
```json
|
|
{
|
|
"role": "user",
|
|
"content": [
|
|
{
|
|
"type": "text",
|
|
"text": "What is 2 + 2?"
|
|
},
|
|
{
|
|
"type": "image",
|
|
"source": {
|
|
"type": "base64",
|
|
"media_type": "image/jpeg",
|
|
"data": "base64-encoded-image-data"
|
|
}
|
|
},
|
|
{
|
|
"type": "tool_result",
|
|
"tool_use_id": "tool_call_123",
|
|
"content": "Result from tool execution",
|
|
"is_error": false
|
|
}
|
|
]
|
|
}
|
|
```
|
|
|
|
###### Message Content Types
|
|
|
|
**text**
|
|
```json
|
|
{
|
|
"type": "text",
|
|
"text": "String content"
|
|
}
|
|
```
|
|
|
|
**image** (user messages only)
|
|
```json
|
|
{
|
|
"type": "image",
|
|
"source": {
|
|
"type": "base64",
|
|
"media_type": "image/jpeg",
|
|
"data": "base64-encoded-image"
|
|
}
|
|
}
|
|
```
|
|
|
|
Or from URL:
|
|
```json
|
|
{
|
|
"type": "image",
|
|
"source": {
|
|
"type": "url",
|
|
"url": "https://example.com/image.jpg"
|
|
}
|
|
}
|
|
```
|
|
|
|
**tool_use** (assistant messages only, in responses)
|
|
```json
|
|
{
|
|
"type": "tool_use",
|
|
"id": "call_123",
|
|
"name": "search",
|
|
"input": {
|
|
"query": "capital of France"
|
|
}
|
|
}
|
|
```
|
|
|
|
**tool_result** (user messages only, after tool_use)
|
|
```json
|
|
{
|
|
"type": "tool_result",
|
|
"tool_use_id": "call_123",
|
|
"content": "The capital of France is Paris.",
|
|
"is_error": false
|
|
}
|
|
```
|
|
|
|
##### Tool Definition
|
|
|
|
```json
|
|
{
|
|
"name": "search",
|
|
"description": "Search the web for information",
|
|
"input_schema": {
|
|
"type": "object",
|
|
"properties": {
|
|
"query": {
|
|
"type": "string",
|
|
"description": "Search query"
|
|
}
|
|
},
|
|
"required": ["query"]
|
|
}
|
|
}
|
|
```
|
|
|
|
##### Tool Choice
|
|
|
|
Control which tool the model uses.
|
|
|
|
Auto (default):
|
|
```json
|
|
{
|
|
"type": "auto"
|
|
}
|
|
```
|
|
|
|
Model must use a tool:
|
|
```json
|
|
{
|
|
"type": "any"
|
|
}
|
|
```
|
|
|
|
Model cannot use tools:
|
|
```json
|
|
{
|
|
"type": "none"
|
|
}
|
|
```
|
|
|
|
Model must use specific tool:
|
|
```json
|
|
{
|
|
"type": "tool",
|
|
"name": "search"
|
|
}
|
|
```
|
|
|
|
#### Response (Non-Streaming)
|
|
|
|
```json
|
|
{
|
|
"id": "msg_1234567890abcdef",
|
|
"type": "message",
|
|
"role": "assistant",
|
|
"content": [
|
|
{
|
|
"type": "text",
|
|
"text": "2 + 2 = 4"
|
|
}
|
|
],
|
|
"model": "claude-sonnet-4-20250514",
|
|
"stop_reason": "end_turn",
|
|
"usage": {
|
|
"input_tokens": 10,
|
|
"output_tokens": 5
|
|
}
|
|
}
|
|
```
|
|
|
|
##### Response Parameters
|
|
|
|
| Parameter | Type | Description |
|
|
|-----------|------|-------------|
|
|
| `id` | string | Unique message identifier. |
|
|
| `type` | string | Always `"message"`. |
|
|
| `role` | string | Always `"assistant"`. |
|
|
| `content` | array | Array of content blocks (text or tool_use). |
|
|
| `model` | string | Model identifier that processed the request. |
|
|
| `stop_reason` | string | Reason generation stopped (see Stop Reasons). |
|
|
| `usage` | object | Token usage: `input_tokens`, `output_tokens`. |
|
|
|
|
#### Response (Streaming)
|
|
|
|
Stream responses as Server-Sent Events when `stream: true`:
|
|
|
|
```
|
|
event: message_start
|
|
data: {"type":"message_start","message":{"id":"msg_...","type":"message","role":"assistant","content":[],"model":"claude-sonnet-4-20250514","stop_reason":null,"usage":{"input_tokens":0,"output_tokens":0}}}
|
|
|
|
event: content_block_start
|
|
data: {"type":"content_block_start","index":0,"content_block":{"type":"text","text":""}}
|
|
|
|
event: content_block_delta
|
|
data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":" How"}}
|
|
|
|
event: content_block_delta
|
|
data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":" are"}}
|
|
|
|
event: content_block_stop
|
|
data: {"type":"content_block_stop","index":0}
|
|
|
|
event: message_delta
|
|
data: {"type":"message_delta","delta":{"stop_reason":"end_turn"},"usage":{"output_tokens":5}}
|
|
|
|
event: message_stop
|
|
data: {"type":"message_stop"}
|
|
```
|
|
|
|
###### Stream Event Types
|
|
|
|
**message_start**
|
|
First event, contains message envelope.
|
|
|
|
**content_block_start**
|
|
New content block begins (text or tool_use).
|
|
- `index`: Position in content array.
|
|
- `content_block`: Block metadata.
|
|
|
|
**content_block_delta**
|
|
Incremental update to current block.
|
|
- Text blocks: `delta.type: "text_delta"`, `delta.text: string`
|
|
- Tool blocks: `delta.type: "input_json_delta"`, `delta.partial_json: string`
|
|
|
|
**content_block_stop**
|
|
Current block complete.
|
|
|
|
**message_delta**
|
|
Final message metadata.
|
|
- `delta.stop_reason`: Reason generation stopped.
|
|
- `usage.output_tokens`: Total output tokens.
|
|
|
|
**message_stop**
|
|
Stream ended.
|
|
|
|
#### Stop Reasons
|
|
|
|
| Stop Reason | Meaning |
|
|
|------------|---------|
|
|
| `end_turn` | Model completed generation naturally. |
|
|
| `max_tokens` | Hit `max_tokens` limit. |
|
|
| `stop_sequence` | Generation hit user-specified `stop_sequences`. |
|
|
| `tool_use` | Model selected a tool to call. |
|
|
|
|
#### Error Responses
|
|
|
|
**401 Unauthorized** (invalid token)
|
|
```json
|
|
{
|
|
"type": "error",
|
|
"error": {
|
|
"type": "authentication_error",
|
|
"message": "Unauthorized"
|
|
}
|
|
}
|
|
```
|
|
|
|
**400 Bad Request** (malformed request)
|
|
```json
|
|
{
|
|
"type": "error",
|
|
"error": {
|
|
"type": "invalid_request_error",
|
|
"message": "Bad Request"
|
|
}
|
|
}
|
|
```
|
|
|
|
**500 Internal Server Error** (server misconfiguration or API error)
|
|
```json
|
|
{
|
|
"type": "error",
|
|
"error": {
|
|
"type": "api_error",
|
|
"message": "Internal server error"
|
|
}
|
|
}
|
|
```
|
|
|
|
## Health Check Endpoint
|
|
|
|
### GET /
|
|
|
|
Returns gateway status (no authentication required).
|
|
|
|
```bash
|
|
curl https://gateway.example.com/
|
|
```
|
|
|
|
Response:
|
|
```json
|
|
{
|
|
"status": "ok",
|
|
"name": "Claude Central Gateway"
|
|
}
|
|
```
|
|
|
|
## Configuration
|
|
|
|
Gateway behavior controlled via environment variables:
|
|
|
|
| Variable | Required | Description | Example |
|
|
|----------|----------|-------------|---------|
|
|
| `GATEWAY_TOKEN` | Yes | Shared token for authentication. | `sk-gatewaytoken123...` |
|
|
| `OPENAI_API_KEY` | Yes | OpenAI API key for authentication. | `sk-proj-...` |
|
|
| `MODEL_MAP` | No | Comma-separated model name mappings. | `claude-sonnet-4-20250514:gpt-4o,claude-opus:gpt-4-turbo` |
|
|
|
|
## Usage Examples
|
|
|
|
### Simple Text Request
|
|
|
|
```bash
|
|
curl -X POST https://gateway.example.com/v1/messages \
|
|
-H "x-api-key: my-secret-token" \
|
|
-H "Content-Type: application/json" \
|
|
-d '{
|
|
"model": "claude-sonnet-4-20250514",
|
|
"max_tokens": 256,
|
|
"messages": [
|
|
{"role": "user", "content": "Say hello!"}
|
|
]
|
|
}'
|
|
```
|
|
|
|
### Streaming Response
|
|
|
|
```bash
|
|
curl -X POST https://gateway.example.com/v1/messages \
|
|
-H "x-api-key: my-secret-token" \
|
|
-H "Content-Type: application/json" \
|
|
-d '{
|
|
"model": "claude-sonnet-4-20250514",
|
|
"max_tokens": 256,
|
|
"stream": true,
|
|
"messages": [
|
|
{"role": "user", "content": "Count to 5"}
|
|
]
|
|
}' \
|
|
-N
|
|
```
|
|
|
|
### Tool Use Workflow
|
|
|
|
**Request with tools:**
|
|
```json
|
|
{
|
|
"model": "claude-sonnet-4-20250514",
|
|
"max_tokens": 256,
|
|
"tools": [
|
|
{
|
|
"name": "search",
|
|
"description": "Search the web",
|
|
"input_schema": {
|
|
"type": "object",
|
|
"properties": {
|
|
"query": {"type": "string"}
|
|
},
|
|
"required": ["query"]
|
|
}
|
|
}
|
|
],
|
|
"messages": [
|
|
{"role": "user", "content": "What is the capital of France?"}
|
|
]
|
|
}
|
|
```
|
|
|
|
**Response with tool_use:**
|
|
```json
|
|
{
|
|
"id": "msg_...",
|
|
"type": "message",
|
|
"role": "assistant",
|
|
"content": [
|
|
{
|
|
"type": "tool_use",
|
|
"id": "call_123",
|
|
"name": "search",
|
|
"input": {"query": "capital of France"}
|
|
}
|
|
],
|
|
"stop_reason": "tool_use",
|
|
"usage": {"input_tokens": 50, "output_tokens": 25}
|
|
}
|
|
```
|
|
|
|
**Follow-up request with tool result:**
|
|
```json
|
|
{
|
|
"model": "claude-sonnet-4-20250514",
|
|
"max_tokens": 256,
|
|
"messages": [
|
|
{"role": "user", "content": "What is the capital of France?"},
|
|
{
|
|
"role": "assistant",
|
|
"content": [
|
|
{
|
|
"type": "tool_use",
|
|
"id": "call_123",
|
|
"name": "search",
|
|
"input": {"query": "capital of France"}
|
|
}
|
|
]
|
|
},
|
|
{
|
|
"role": "user",
|
|
"content": [
|
|
{
|
|
"type": "tool_result",
|
|
"tool_use_id": "call_123",
|
|
"content": "Paris is the capital of France"
|
|
}
|
|
]
|
|
}
|
|
]
|
|
}
|
|
```
|
|
|
|
**Final response:**
|
|
```json
|
|
{
|
|
"id": "msg_...",
|
|
"type": "message",
|
|
"role": "assistant",
|
|
"content": [
|
|
{
|
|
"type": "text",
|
|
"text": "Paris is the capital of France."
|
|
}
|
|
],
|
|
"stop_reason": "end_turn",
|
|
"usage": {"input_tokens": 100, "output_tokens": 15}
|
|
}
|
|
```
|
|
|
|
### Image Request
|
|
|
|
```json
|
|
{
|
|
"model": "claude-sonnet-4-20250514",
|
|
"max_tokens": 256,
|
|
"messages": [
|
|
{
|
|
"role": "user",
|
|
"content": [
|
|
{
|
|
"type": "image",
|
|
"source": {
|
|
"type": "base64",
|
|
"media_type": "image/jpeg",
|
|
"data": "iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNk+M9QDwADhgGAWjR9awAAAABJRU5ErkJggg=="
|
|
}
|
|
},
|
|
{
|
|
"type": "text",
|
|
"text": "Describe this image"
|
|
}
|
|
]
|
|
}
|
|
]
|
|
}
|
|
```
|
|
|
|
### Using Claude SDK (Recommended)
|
|
|
|
Set environment variables:
|
|
```bash
|
|
export ANTHROPIC_BASE_URL=https://gateway.example.com
|
|
export ANTHROPIC_AUTH_TOKEN=my-secret-token
|
|
```
|
|
|
|
Then use normally:
|
|
```javascript
|
|
import Anthropic from "@anthropic-ai/sdk";
|
|
|
|
const client = new Anthropic({
|
|
baseURL: process.env.ANTHROPIC_BASE_URL,
|
|
apiKey: process.env.ANTHROPIC_AUTH_TOKEN,
|
|
});
|
|
|
|
const message = await client.messages.create({
|
|
model: "claude-sonnet-4-20250514",
|
|
max_tokens: 256,
|
|
messages: [
|
|
{ role: "user", content: "Say hello!" }
|
|
],
|
|
});
|
|
|
|
console.log(message.content[0].text);
|
|
```
|
|
|
|
## Limitations & Compatibility
|
|
|
|
### Fully Supported
|
|
- Text messages
|
|
- Image content (base64 and URLs)
|
|
- Tool definitions and tool use/tool result round-trips
|
|
- System messages (string or array)
|
|
- Streaming responses with proper SSE format
|
|
- Stop sequences
|
|
- Temperature, top_p, max_tokens
|
|
- Usage token counts
|
|
|
|
### Unsupported (Filtered Out)
|
|
- Thinking blocks (Claude 3.7+)
|
|
- Cache control directives
|
|
- Multi-modal tool inputs (tools receive text input only)
|
|
- Vision-specific model parameters
|
|
|
|
### Behavioral Differences from Anthropic API
|
|
- Single shared token (no per-user auth)
|
|
- No rate limiting (implement on your end if needed)
|
|
- No request logging/audit trail
|
|
- Error messages may differ (OpenAI error format converted)
|
|
- Latency slightly higher due to proxying
|
|
|
|
## Rate Limiting Notes
|
|
|
|
Gateway itself has no rate limits. Limits come from:
|
|
1. **OpenAI API quota**: Based on your API tier
|
|
2. **Network throughput**: Hono/platform limits
|
|
3. **Token count**: OpenAI pricing
|
|
|
|
Recommendations:
|
|
- Implement client-side rate limiting
|
|
- Monitor token usage via `usage` field in responses
|
|
- Set aggressive `max_tokens` limits if cost is concern
|
|
- Use smaller models in `MODEL_MAP` for cost reduction
|