Skip to main content

Overview

GoModel accepts the Anthropic Messages API request dialect at POST /v1/messages, in addition to its OpenAI-compatible API. Clients and SDKs that speak the Anthropic format can point at GoModel unchanged. The request is translated to GoModel’s canonical chat type at ingress and runs through the same pipeline as /v1/chat/completions — so virtual models, workflow policy, budgets, failover, the response cache, usage/cost tracking, and audit logging all apply. Because every provider implements chat completion, an Anthropic-format request can be routed to any configured provider (OpenAI, Gemini, Bedrock, and others), not only Anthropic. This differs from the passthrough API: /p/anthropic/v1/messages forwards bytes verbatim to the Anthropic upstream only, while the managed /v1/messages endpoint routes anywhere and is fully managed.

Native forwarding to Anthropic

When a /v1/messages request resolves to an Anthropic provider, GoModel skips the translation round-trip and forwards the original request body verbatim (rewriting only the model field when an alias resolved to a different name), then relays the provider-native response or SSE stream unchanged. This preserves everything the canonical translation cannot — cache_control breakpoints, thinking-block signatures, anthropic-beta headers — which coding agents like Claude Code depend on. Rate limits, budgets, audit logging, and usage tracking still apply, for both streaming and non-streaming responses. Native forwarding is automatic. Requests fall back to the translated pipeline when a feature that operates on the canonical request is in play: guardrails request patching, the response cache, or failover routing. Requests resolving to any non-Anthropic provider always translate.

Supported endpoints

Message Batches

/v1/messages/batches shares the gateway’s native-batch pipeline with the OpenAI-compatible /v1/batches route — the two are dialect views of the same resource. Batch IDs are interchangeable across the two dialects (msgbatch_<uuid> here, batch_<uuid> there). All requests in one batch must resolve to a single provider; per-item custom_id values are required and must be unique. Providers whose batch API is file-based (OpenAI-compatible) receive inline requests as an automatically uploaded JSONL input file. request_counts maps the provider’s aggregate counts: while a batch runs, unfinished requests are reported as processing; once it ends, any remainder is attributed by the batch outcome (canceled, expired, or errored).

Authentication

Both credential styles work, so the official Anthropic SDKs are drop-in:
  • Authorization: Bearer <key> — GoModel’s primary scheme.
  • x-api-key: <key> — the Anthropic-native header, accepted as a fallback when no Authorization header is present.

Example

The response uses the Anthropic Messages shape (type: "message", content blocks, stop_reason, usage). Errors use the Anthropic error envelope ({"type": "error", "error": {...}}). max_tokens is required, as in the Anthropic API. Streaming responses emit the Anthropic SSE event sequence (message_start, content_block_start/content_block_delta/content_block_stop, message_delta, message_stop).

Cost tracking and audit logs

/v1/messages requests are tracked and audited exactly like the OpenAI-compatible routes. Cost is computed from the actual provider that served the request, and usage is recorded under the /v1/messages endpoint so it can be filtered in the dashboard.

Limitations

These limitations apply to the translated pipeline — requests routed to a non-Anthropic provider, or to Anthropic with guardrails, response cache, or failover engaged. Requests natively forwarded to Anthropic are preserved byte-for-byte apart from the model value when an alias resolved to a different name, and none of the below applies. /v1/messages translates through GoModel’s canonical chat type. Anthropic-specific features that have no canonical equivalent are not preserved end to end:
  • cache_control is preserved on the request, system/content blocks, custom tools, and tool-use/tool-result history when routed to Anthropic.
  • {"role": "system"} messages inside messages keep their position and cache_control breakpoints when routed to a Claude 4.8+/5-family model (Claude Code appends system reminders this way, and its prompt caching depends on them staying in place). On older Claude models, which reject the role, their text is hoisted into the top-level system prompt instead.
  • Extended-thinking signatures and thinking blocks on input messages are dropped.
  • Server/built-in tools (web search, code execution, …) are rejected with a clear 400; only custom tools (type absent or "custom") translate.
  • top_k is dropped — it has no portable OpenAI-compatible equivalent, and OpenAI-family providers reject unknown request fields. temperature and top_p are forwarded.
  • document and other non-text/image content blocks are rejected with a clear 400 error rather than silently dropped.
  • stop_sequences are honored on every provider. Providers that report the matched sequence natively (Anthropic) get the full contract back: stop_reason: "stop_sequence" plus the stop_sequence value. OpenAI-family providers conflate stop-parameter hits with natural stops in finish_reason, so completions there report stop_reason: "end_turn" (output is still truncated correctly).
  • count_tokens returns a provider-agnostic heuristic estimate (≈ characters / 4), not a tokenizer-exact count. Use it for budgeting and UX sizing, not hard context-limit decisions. The same estimate seeds usage.input_tokens in the streaming message_start event; the authoritative counts arrive in the final message_delta event, which SDK accumulators prefer.
For byte-exact Anthropic fidelity beyond the supported cache controls, use the /p/anthropic/v1/messages passthrough route instead. See ADR-0007 for the design rationale and tradeoffs.
Last modified on August 22, 2026