API Reference

POST /v1/messages

Anthropic-compatible Messages API. Use the Anthropic SDK with our base URL — every Claude variant, plus the rest of the catalog.

FIG.
FIG. 00 · POST /V1/MESSAGESANTHROPIC-COMPATIBLE

The /v1/messages endpoint speaks the Anthropic Messages API natively. Point your Anthropic SDK at our base URL and ship — every Claude model works, and most non-Claude models work too via the compat layer. If you'd rather use a single TypeScript surface, the AI SDK's streamText covers the same models with the same shape.

FIG. 01MESSAGES WIRE
SCHEMATIC
Anthropic's named SSE events (`message_start`, `content_block_delta`, `message_stop`) flow through unchanged. Tool use, vision blocks, and extended thinking all land in their native shapes; Synapse Garden adds `providerOptions.gateway` for routing and caching on top.

Endpoint

POST https://synapse.garden/api/v1/messages

Authentication

Authorization: Bearer mg_live_xxxxxxxxxxxxxxxxxxxxxxxx

The Anthropic SDK uses x-api-key natively — we accept both. Use Authorization: Bearer for consistency with the rest of our docs.

Request body

{
  // ── REQUIRED ────────────────────────────────────────────────────────
  model: string,             // e.g. "anthropic/claude-opus-4.6"
  max_tokens: number,        // required by Anthropic — no default
  messages: Message[],

  // ── OPTIONAL ────────────────────────────────────────────────────────
  system?: string | SystemBlock[], // system prompt
  temperature?: number,      // 0–1; default 1
  top_p?: number,
  top_k?: number,
  stop_sequences?: string[],
  stream?: boolean,
  metadata?: { user_id?: string },

  // ── TOOLS ───────────────────────────────────────────────────────────
  tools?: ToolDefinition[],
  tool_choice?: { type: "auto" | "any" | "tool"; name?: string },

  // ── EXTENDED THINKING (reasoning) ───────────────────────────────────
  thinking?: { type: "enabled"; budget_tokens: number },

  // ── SYNAPSE GARDEN EXTENSIONS ──────────────────────────────────────────
  providerOptions?: {
    gateway?: {
      order?: string[],
      only?: string[],
      sort?: "cost" | "ttft" | "tps",
      models?: string[],
      caching?: "auto",
    },
    anthropic?: {
      thinkingBudget?: number, // dollars per request — alternative to `thinking.budget_tokens`
    },
  },
}

Message shape

type Message =
  | { role: "user"; content: string | ContentBlock[] }
  | { role: "assistant"; content: string | ContentBlock[] }

type ContentBlock =
  | { type: "text"; text: string; cache_control?: { type: "ephemeral"; ttl?: "5m" | "1h" } }
  | { type: "image"; source: ImageSource }
  | { type: "tool_use"; id: string; name: string; input: object }
  | { type: "tool_result"; tool_use_id: string; content: string | ContentBlock[] }

type ImageSource =
  | { type: "url"; url: string }
  | { type: "base64"; media_type: "image/jpeg" | "image/png" | "image/webp" | "image/gif"; data: string }

Tool definition

type ToolDefinition = {
  name: string
  description?: string
  input_schema: JsonSchema    // standard JSON Schema
  cache_control?: { type: "ephemeral" }  // optional — cache the tool definition
}

Response

Non-streaming

{
  "id": "msg_01ABCD...",
  "type": "message",
  "role": "assistant",
  "model": "anthropic/claude-opus-4.6",
  "content": [
    { "type": "text", "text": "The sky appears blue because..." }
  ],
  "stop_reason": "end_turn",
  "stop_sequence": null,
  "usage": {
    "input_tokens": 24,
    "output_tokens": 156,
    "cache_read_input_tokens": 0,
    "cache_creation_input_tokens": 0
  },
  "providerMetadata": {
    "gateway": {
      "generationId": "gen_01XYZ...",
      "resolvedProvider": "anthropic",
      "modelAttempts": [...]
    }
  }
}

Streaming events

When stream: true, response is text/event-stream with named events:

event: message_start
data: {"type":"message_start","message":{...}}

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":"The"}}

event: content_block_delta
data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":" sky"}}



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":156}}

event: message_stop
data: {"type":"message_stop"}

For tool calls, content blocks of type tool_use carry input_json_delta events for the streaming JSON arguments.

Caching

Cache markers go on individual content blocks:

{
  role: "user",
  content: [
    {
      type: "text",
      text: largeCorpus,
      cache_control: { type: "ephemeral" }, // 5-min default
    },
    { type: "text", text: userQuestion },
  ],
}

For 1-hour cache:

cache_control: { type: "ephemeral", ttl: "1h" }

For hands-free, set providerOptions.gateway.caching: "auto" and we add the marker on the right boundary. See Caching.

Examples

curl — basic

curl https://synapse.garden/api/v1/messages \
  -H "Authorization: Bearer $MG_KEY" \
  -H "Content-Type: application/json" \
  -H "anthropic-version: 2023-06-01" \
  -d '{
    "model": "anthropic/claude-opus-4.6",
    "max_tokens": 1024,
    "messages": [{"role": "user", "content": "Why is the sky blue?"}]
  }'

curl — streaming

curl https://synapse.garden/api/v1/messages \
  -H "Authorization: Bearer $MG_KEY" \
  -H "Content-Type: application/json" \
  -H "anthropic-version: 2023-06-01" \
  -N \
  -d '{
    "model": "anthropic/claude-opus-4.6",
    "max_tokens": 1024,
    "stream": true,
    "messages": [{"role": "user", "content": "Tell me a story"}]
  }'

Anthropic SDK (TypeScript)

import Anthropic from "@anthropic-ai/sdk"

const client = new Anthropic({
  apiKey: process.env.MG_KEY,
  baseURL: "https://synapse.garden/api",
})

const message = await client.messages.create({
  model: "anthropic/claude-opus-4.6",
  max_tokens: 1024,
  messages: [{ role: "user", content: "Why is the sky blue?" }],
})

console.log(message.content[0].text)

Streaming via SDK

const stream = await client.messages.stream({
  model: "anthropic/claude-opus-4.6",
  max_tokens: 1024,
  messages: [{ role: "user", content: "Tell me a story" }],
})

for await (const event of stream) {
  if (event.type === "content_block_delta" && event.delta.type === "text_delta") {
    process.stdout.write(event.delta.text)
  }
}

Extended thinking

client.messages.create({
  model: "anthropic/claude-opus-4.6",
  max_tokens: 8192,
  thinking: { type: "enabled", budget_tokens: 5000 },
  messages: [{ role: "user", content: "Solve this proof: ..." }],
})

Or via gateway extension (cleaner — dollars instead of token estimate):

client.messages.create({
  model: "anthropic/claude-opus-4.6",
  max_tokens: 8192,
  // @ts-expect-error
  providerOptions: {
    anthropic: { thinkingBudget: 0.05 }, // $0.05 cap
  },
  messages: [...],
})

Auto-caching

client.messages.create({
  model: "anthropic/claude-sonnet-4.6",
  max_tokens: 1024,
  system: "You are a helpful assistant with this corpus...",
  messages: [{ role: "user", content: "..." }],
  // @ts-expect-error
  providerOptions: {
    gateway: { caching: "auto" },
  },
})

Cross-provider compat

Many non-Anthropic models work via this endpoint too — pass them with their creator/slug:

client.messages.create({
  model: "openai/gpt-5.4",        // OpenAI via Anthropic SDK
  max_tokens: 1024,
  messages: [...],
})

client.messages.create({
  model: "google/gemini-3.1-pro-preview", // Gemini via Anthropic SDK
  max_tokens: 1024,
  messages: [...],
})

The compat layer translates the request shape. Most features work; some provider-specific ones (e.g. extended thinking) only apply to native models.

Errors

Same error envelope as /v1/chat/completions. See Errors & retries.

See also