gopenrouter is a Go client for the OpenRouter API.
It combines the complete generated interface from OpenRouter's official Go SDK
with an ergonomic, go-openai-style compatibility interface.
Use one client for both surfaces:
- the generated namespaces expose the complete typed OpenRouter API, including inference, Batch, Containers, Interns, Private Endpoints, Vault, SCIM, System One, the tool catalog, Decisions, analytics, BYOK, guardrails, workspaces, and API-key management;
- the compatibility methods provide a compact interface for chat completions, streaming, Anthropic Messages, Responses, embeddings, model discovery, generation metadata, credits, OAuth, and management operations.
- Go 1.25.10 or newer
- an OpenRouter API key for authenticated operations; public model discovery can be used without one
The generated surface uses official Go SDK v0.9.11, pinned in
go.mod. Generated types follow that SDK's versioning and release
notes.
go get github.com/iamwavecut/gopenrouter@mainpackage main
import (
"context"
"fmt"
"log"
"os"
"github.com/iamwavecut/gopenrouter"
)
func main() {
client := gopenrouter.NewClient(os.Getenv("OPENROUTER_API_KEY"))
response, err := client.CreateChatCompletion(
context.Background(),
gopenrouter.ChatCompletionRequest{
Model: "openai/gpt-5-nano",
Messages: []gopenrouter.ChatCompletionMessage{
{
Role: gopenrouter.RoleUser,
Content: "Explain why the sky is blue in one sentence.",
},
},
},
)
if err != nil {
log.Fatal(err)
}
fmt.Println(response.Choices[0].Message.Content)
}Client embeds OpenRouter's generated Go client. Its namespaces and exact
request, response, union, multipart, pagination, binary, error, and event-stream
types are available directly:
client := gopenrouter.NewClient(os.Getenv("OPENROUTER_API_KEY"))
models, err := client.Models.List(ctx, nil)
files, err := client.Files.List(ctx, nil)
responses, err := client.Responses.Send(ctx, request, nil)Generated model types live under
github.com/OpenRouterTeam/go-sdk/models. The client currently exposes these
top-level namespaces:
Analytics, Alpha, APIKeys, Batch, Benchmarks, Beta, BYOK,
Chat, Classifications, Containers, Credits, Datasets, Embeddings,
Endpoints, Files, Generations, Guardrails, Images, Interns,
Models, OAuth, Observability, Organization, Presets,
PrivateEndpoints, Providers, Rerank, Responses, Scim, STT,
SystemOne, Tools, TTS, Vault, VideoGeneration, and Workspaces.
Byok, Stt, and Tts remain aliases for BYOK, STT, and TTS.
Beta.Responses remains available; the current upstream SDK no longer exposes
Beta.Analytics, so use Analytics directly.
client.Batch.List(ctx, nil) supports cursor pagination without modifying
the caller's query and stops when has_more is false. An operation timeout
applies to each page; the caller's context can bound the entire traversal.
Other Batch methods use the official types unchanged. The unwrapped generated
Batch client is available at client.OpenRouter.Batch.
client.Alpha.Decisions.Create shares the configured base URL. Per-operation
operations.WithServerURL takes precedence. The original generated Decisions
client is available at client.OpenRouter.Alpha.Decisions.
The root methods retain the library's concise, go-openai-inspired API:
response, err := client.CreateChatCompletion(ctx, request)
stream, err := client.CreateChatCompletionStream(ctx, request)
embedding, err := client.CreateEmbeddings(ctx, embeddingRequest)
anthropic, err := client.CreateAnthropicMessage(ctx, anthropicRequest)
responses, err := client.CreateResponse(ctx, responsesRequest)
generation, err := client.GetGeneration(ctx, generationID)The catalog, embeddings, responses, anthropic, oauth, management,
and shared packages provide the same compatibility contracts in focused
namespaces.
The compatibility surface also covers POST /messages and the deprecated
POST /credits/coinbase operation, which are present in OpenRouter's public
OpenAPI contract but intentionally omitted from the generated official client.
Server tools use top-level Parameters; function tools in Chat use
Function.Parameters. Function-tool codecs retain explicit nullable fields;
Responses function tools encode required parameters: null when no schema is
supplied. Responses output items and Anthropic content blocks retain opaque
fields when replayed, including asynchronous/subagent context, tool inputs,
thinking signatures, and citations. Typed field edits take precedence.
Custom compatibility decoders use json.Number for unstructured numeric
values in tool schemas, tracing extensions, and Raw/Extra payloads. This
preserves large integers and decimal precision. Callers that asserted
float64 for these values must use json.Number.Int64 or Float64 instead;
typed numeric fields keep their existing types. Use keyed struct literals:
compatibility structs gain fields, and embeddings.Value also tracks decoded
encoding internally.
Guardrail creation and patches keep omission distinct from explicit false
and null. Use ExtraBody to clear a nullable policy or set a zero budget
without changing existing pointer and slice field types:
guardrail, err := client.UpdateGuardrail(ctx, guardrailID,
gopenrouter.GuardrailUpdateRequest{
ExtraBody: map[string]any{
"allowed_models": nil,
"enforce_zdr_openai": nil,
},
})config := gopenrouter.DefaultConfig(os.Getenv("OPENROUTER_API_KEY"))
config.HTTPClient = &http.Client{Timeout: 2 * time.Minute}
config.SiteURL = "https://example.com"
config.SiteName = "Example application"
config.SiteCategories = []string{"productivity", "developer-tools"}
client := gopenrouter.NewClientWithConfig(config)The configuration is shared by both client surfaces and controls:
- bearer authentication;
- the base URL and HTTP client;
HTTP-Referer,X-Title, andX-OpenRouter-Title;X-OpenRouter-Categories.
An empty base URL uses https://openrouter.ai/api/v1; a nil HTTP client uses
http.Client. Trailing slashes are normalized. A custom base URL applies to
generated operations as well as compatibility methods. Decisions uses
/api/alpha/decisions on the configured host, preserving any proxy prefix
before /api/v1. Endpoint availability still depends on the selected region
and account. Explicit per-operation server URLs and attribution headers take
precedence over configuration, including intentionally empty headers.
- provider routing, fallback model lists, provider preferences, ZDR and region selection, and provider-specific options;
- BYOK model, user, and API-key restrictions;
- service tiers, routing metadata, workspace accounting, and alignment rules and results;
- reasoning controls and reasoning details;
- prompt caching and cache-control directives;
- structured outputs, strict and deferred tools, asynchronous Responses tools, server tools, and plugins;
- text, image, audio, file, embedding, rerank, and video payloads;
- cost and native-token accounting;
- inline Batch submission and results, container files, and code-interpreter events;
- typed synchronous and streaming errors;
- Chat SSE, Responses semantic events, and Anthropic event streams.
Runnable programs are available in examples/:
- inference: Chat, streaming Chat, Responses, Anthropic Messages, and embeddings;
- asynchronous inference: Batch submission, using
OPENROUTER_API_KEYand a batch-capableOPENROUTER_BATCH_MODEL; - multimodal: vision, file attachments, and PDF parsing;
- generation controls: reasoning, structured output, logprobs, prompt caching, provider extras, and tool calling;
- utilities: model discovery, generation metadata, and credit status.
The default suite uses local HTTP servers and contract fixtures; it does not call the live OpenRouter API. Tests cover the generated method surface and compatibility JSON, HTTP, pagination, and streaming behavior:
go test ./...
go test -race ./...
go vet ./...An optional live check exercises public model discovery without an API key:
GOPENROUTER_LIVE_TEST=1 go test . -run TestLivePublicCatalog -count=1 -vThe compatibility interface is inspired by go-openai. The complete generated surface is provided by OpenRouter's official Go SDK.