OpenRouter Rust SDK
Type-safe, async Rust bindings for the OpenRouter API.
openrouter-rs is built around the canonical 0.6.x domain-oriented client surface:
client.chat()forPOST /chat/completionsclient.responses()forPOST /responsesclient.messages()for Anthropic-compatiblePOST /messagesclient.models()for model discovery and embeddingsclient.management()for auth-code, API-key, guardrail, activity, and account-management flowsclient.legacy()forPOST /completionswhenlegacy-completionsis explicitly enabled
The crate ships typed request/response models, builder-based ergonomics, streaming support, typed tools, multimodal chat content, and complete endpoint coverage for the current repository snapshot. The implementation map and live-test status live in docs/official-endpoint-test-matrix.md.
Installation
[]
= "0.6.1"
= { = "1", = ["full"] }
Legacy text completions are opt-in:
[]
= { = "0.6.1", = ["legacy-completions"] }
= { = "1", = ["full"] }
Quick Start
use ;
async
Design Overview
The main design change in 0.6.x is that public documentation and examples treat the domain clients as the canonical surface. Flat OpenRouterClient::* helpers still exist in places, but they are not the recommended path for new code.
| Domain | Canonical methods | Primary endpoints | Auth note |
|---|---|---|---|
chat() |
create, stream, stream_tool_aware, stream_unified |
/chat/completions |
API key |
responses() |
create, stream, stream_unified |
/responses |
API key |
messages() |
create, stream, stream_unified |
/messages |
API key |
models() |
list, list_by_category, list_by_parameters, list_endpoints, list_providers, list_user_models, get_model_count, list_zdr_endpoints, create_embedding, list_embedding_models |
/models*, /providers, /endpoints/zdr, /embeddings* |
API key |
management() |
create_api_key, list_api_keys, create_auth_code, create_api_key_from_auth_code, list_guardrails, get_activity, get_credits, create_coinbase_charge, get_generation |
/keys*, /auth/keys*, /guardrails*, /activity, /credits*, /generation, /key |
Governed endpoints require a management key; billing/session endpoints still use the normal API key because that is how OpenRouter authenticates them |
legacy() |
completions().create |
/completions |
legacy-completions feature + API key |
The client builder currently exposes:
base_urlapi_keymanagement_keyhttp_refererx_titleconfig
At runtime you can also call set_api_key, clear_api_key, set_management_key, and clear_management_key.
Core Workflows
Streaming
The SDK exposes three useful streaming layers:
- Raw endpoint streams:
chat().stream(...)responses().stream(...)messages().stream(...)
- Tool-aware chat aggregation:
chat().stream_tool_aware(...)
- A unified event model across chat, responses, and messages:
chat().stream_unified(...)responses().stream_unified(...)messages().stream_unified(...)
use StreamExt;
use UnifiedStreamEvent;
let mut stream = client.chat.stream_unified.await?;
while let Some = stream.next.await
Tool Calling And Typed Tools
Manual tool schemas and typed tools are both first-class:
types::Toolfor explicit JSON-schema tool definitionstypes::typed_tool::{TypedTool, TypedToolParams}for Rust-typed tools backed byschemars
use ;
use JsonSchema;
use ;
let request = builder
.model
.messages
.
.build?;
Multimodal Chat Content
api::chat::ContentPart now covers text, image URLs, audio input, video input, and file payloads.
use ContentPart;
let request = builder
.model
.messages
.build?;
Responses, Messages, And Embeddings
The current repo has dedicated typed surfaces for the non-chat APIs as well:
use ;
use json;
let responses_request = builder
.model
.input
.build?;
let _responses = client.responses.create.await?;
let messages_request = builder
.model
.max_tokens
.messages
.build?;
let _message = client.messages.create.await?;
let embedding_request = builder
.model
.input
.build?;
let _embedding = client.models.create_embedding.await?;
Discovery And Management
Discovery and governance endpoints are intentionally separated:
use ;
let programming_models = client
.models
.list_by_category
.await?;
let providers = client.models.list_providers.await?;
let zdr_endpoints = client.models.list_zdr_endpoints.await?;
let keys = client
.management
.list_api_keys
.await?;
let guardrail = client
.management
.create_guardrail
.await?;
Management-key reminders:
/activityrequires.management_key(...)/keys*requires.management_key(...)/auth/keys*requires.management_key(...)/guardrails*requires.management_key(...)
API-key reminders:
/credits/credits/coinbase/generation/key
Those endpoints are grouped under management() for discoverability, but the underlying upstream auth model is still API-key based.
Configuration And Model Presets
OpenRouterConfig loads built-in presets from src/config/default_config.toml and resolves preset:* model references into concrete IDs.
use OpenRouterConfig;
let config = default;
println!;
println!;
Built-in presets:
programmingreasoningfree
Legacy Completions
Legacy POST /completions support is isolated behind the legacy-completions feature and the explicit legacy namespace.
use ;
let request = builder
.model
.prompt
.build?;
let response = client.legacy.completions.create.await?;
For new applications, prefer chat() or responses().
🔁 0.6 Naming/Pagination Migration
Full migration guide: MIGRATION.md
models().count()->models().get_model_count()models().list_for_user()->models().list_user_models()management().exchange_code_for_api_key(...)->management().create_api_key_from_auth_code(...)management().list_guardrails(offset, limit)->management().list_guardrails(Some(PaginationOptions::with_offset_and_limit(offset, limit)))client.list_api_keys(offset, include_disabled)->management().list_api_keys(Some(PaginationOptions::with_offset(offset)), include_disabled)
0.6.0 removes the transitional aliases above; use the canonical method names shown in the mapping list.
Migration validation commands for contributors:
Examples
The repo includes runnable examples for the canonical flows:
| Example | Focus |
|---|---|
examples/domain_chat_completion.rs |
Canonical chat() usage |
examples/basic_tool_calling.rs |
Manual tool-calling loop |
examples/typed_tool_calling.rs |
Typed tools with generated schema |
examples/chat_with_reasoning.rs |
Reasoning controls |
examples/stream_chat_completion.rs |
Raw chat streaming |
examples/stream_chat_with_tools.rs |
ToolAwareStream |
examples/create_response.rs |
responses() create |
examples/stream_response.rs |
responses() streaming |
examples/create_message.rs |
messages() create |
examples/stream_messages.rs |
messages() streaming |
examples/create_embedding.rs |
models().create_embedding(...) |
examples/domain_management_api_keys.rs |
API-key management via management() |
examples/exchange_code_for_api_key.rs |
PKCE/auth-code flow |
examples/send_completion_request.rs |
Legacy completions (legacy-completions required) |
Local commands:
CLI Companion
This workspace also contains crates/openrouter-cli, a companion CLI for profile resolution, discovery, management, and usage/billing workflows.
Useful entrypoints:
CLI auth/config precedence is deterministic:
- Flags:
--api-key,--management-key,--base-url - Environment:
OPENROUTER_API_KEY,OPENROUTER_MANAGEMENT_KEY,OPENROUTER_BASE_URL - Profile config values from
profiles.toml - Default
base_url
See crates/openrouter-cli/README.md for the full command surface.
Testing And Quality
Prefer the just recipes so local work stays aligned with CI:
OPENROUTER_MANAGEMENT_KEY=...
Focused commands:
just test-unitjust test-libjust test-docjust test-integration-subsetsjust test-clijust check-migration-docsjust test-migration-smokejust test-integration
Environment and model-pool details live in tests/integration/README.md. A starter env file lives at .env.example.
Repo Docs
- MIGRATION.md for
0.5.x -> 0.6.0 - docs/official-endpoint-test-matrix.md for endpoint-by-endpoint implementation/test status
- tests/integration/README.md for live test pools and env switches
- crates/openrouter-cli/README.md for CLI behavior and examples
- CHANGELOG.md for release-by-release changes
Contributing
When you change API surface or examples:
- update the relevant README/docs in the same change
- run
just quality - run
just quality-ciif you touched migration docs, CLI behavior, or CI-aligned release/test flows
Requirements
- Rust
1.85+ - Tokio
1.x - An
OPENROUTER_API_KEYfor API-backed examples and live tests - An
OPENROUTER_MANAGEMENT_KEYfor management-governed examples/tests
📈 Release History
Version 0.6.1 (Latest)
- Fixed
ToolBuilderfield loss when setters are called in different orders. - Preserved combined model filters and model resolution ordering, and propagated default headers to chat streaming requests.
- Hardened SSE frame parsing, normalized response parsing errors across endpoints, and aligned release validation around
justplus live contract checks.
Version 0.6.0
- Removed
0.5.xcompatibility aliases, madelegacy-completionsopt-in, and standardized the canonical domain-client documentation aroundchat(),responses(),messages(),models(), andmanagement().
Version 0.5.2
- Added
/messages, discovery/activity, guardrails, auth-code flows, unified streaming, CLI foundation, and the0.5.x -> 0.6.0migration bridge.
See CHANGELOG.md for the full history.
License
MIT. See LICENSE.
Disclaimer
This is a third-party SDK and is not affiliated with OpenRouter.