openrouter-rs
Library Listed
A type-safe OpenRouter Rust SDK
- Downloads
- 8,599
- Dependents
- 3
- Stars
- 98
- Forks
- 24
- Contributors
- 10
- Commits
- 408
- Latest release
- 0.24.0 ·
About
Type-safe, async Rust SDK for the OpenRouter API.
docs.rs | examples | crate | docs map | openrouter-cli | contributing | changelog
openrouter-rs is a community-maintained Rust SDK for OpenRouter, with typed requests, streaming, tool calling, and access to OpenRouter's model, usage, and management APIs. A companion CLI is available for terminal and automation workflows.
Installation
[dependencies]
openrouter-rs = "0.24.0"
tokio = { version = "1", features = ["full"] }
Requires Rust 1.93+ and Tokio 1.x. To try it in a new project:
cargo new openrouter-quickstart
cd openrouter-quickstart
Add the dependencies above to Cargo.toml, then set your API key:
export OPENROUTER_API_KEY="your-openrouter-api-key"
Quick Start
Save this as src/main.rs and run cargo run:
Read the full README
use openrouter_rs::{
OpenRouterClient,
api::chat::{ChatCompletionRequest, Message},
types::Role,
};
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let client = OpenRouterClient::builder()
.api_key(std::env::var("OPENROUTER_API_KEY")?)
.build()?;
let request = ChatCompletionRequest::builder()
.model(std::env::var("OPENROUTER_MODEL").unwrap_or_else(|_| "openai/gpt-4o-mini".into()))
.messages(vec![Message::new(
Role::User,
"Explain Rust ownership in plain English.",
)])
.max_tokens(256)
.build()?;
let response = client.chat().create(&request).await?;
let choice = response.choices.first().ok_or("OpenRouter returned no choices")?;
println!("{}", choice.content().unwrap_or(""));
Ok(())
}
Chat response messages and raw streaming deltas preserve reasoning_content and reasoning_text; Message::try_from replays these fields on follow-up requests. Read completion-token breakdowns through usage.completion_tokens_details. Choice::reasoning() and the stream adapters still emit only the canonical reasoning field; inspect raw deltas for provider-specific fields.
Chat responses accept nullable upstream costs and numeric or string choice error codes. Use error.code.as_ref().and_then(|code| code.as_i64()) for numeric handling, and preserve None for unreported costs. See the chat decoding migration for the changed field types.
Use choice.finish_reason().map(|reason| reason.as_str()) to read the finish reason wire name, including unknown provider values preserved by FinishReason::Other.
The SDK keeps setup intentionally narrow: configure runtime values on OpenRouterClient::builder(), then choose the final model on each request builder. File/profile config resolution belongs in the companion CLI or in your application layer, not in the SDK core.
Set OPENROUTER_MODEL to use another model ID available to your account. A successful request prints the model's reply. A missing key fails locally; for API authentication, credit, or model-availability errors, check your OpenRouter account and the returned error before retrying. API calls may consume credits.
Choose a Workflow
These commands run from a checkout of this repository with OPENROUTER_API_KEY set:
| Goal | Run | Guide |
|---|---|---|
| Stream a chat response | cargo run --example stream_chat_completion | Streaming example |
| Execute typed tools against fixed demo fixtures in a bounded agent loop | cargo run --example typed_tool_agent | Typed tool agent |
| Inspect credits and manage API keys | cargo run --example get_credits | CLI usage recipes and key management |
Management-governed endpoints require OPENROUTER_MANAGEMENT_KEY; ordinary chat and credits requests use OPENROUTER_API_KEY. For a minimal HTTP server, see the Axum chat gateway.
Why openrouter-rs
- Domain-oriented clients:
chat(),responses(),messages(),rerank(),audio().speech(),audio().transcriptions(),images(),videos(),files(),models(),batches(),vault(),decisions(),management(), and opt-inlegacy() - Typed request/response models with builder-style ergonomics
- Tokio-native
reqwest + rustlstransport by default, or the host'swasi:httponwasm32-wasip2with thewasip3feature - Streaming support for chat, responses, messages, and image generation, including a unified stream abstraction
- Typed tools, manual JSON-schema tools, OpenRouter server tools, and multimodal chat content
- Typed chat usage metadata for token counts, OpenRouter cost, provider cost breakdowns, and BYOK status
- Opt-in OpenRouter response metadata for chat, Responses API, and Anthropic-compatible Messages requests
- Discovery, rankings and benchmark datasets, task classifications, rerank, audio speech/transcription, image generation, video generation, provider-backed files, embeddings, API-key management, preset creation/readback/versioning, analytics, BYOK provider credentials, observability destinations, workspace management, SCIM group mappings, organization members/settings, external-user registrations, guardrails, activity, credits, and generation metadata/content coverage
- A companion CLI for profile resolution, discovery, management, and billing/usage workflows
Accepted endpoint coverage and live-test status are recorded separately in the endpoint matrix. See the changelog for release details and migration guide when upgrading, including the 0.19 speech input change.
0.20 transport migration: The SDK now uses reqwest 0.13, including the reqwest::Client accepted by .http_client(...). Default native TLS uses platform certificate verification and AWS-LC; Linux deployments need an up-to-date OS CA bundle. See the transport migration guide for custom-client, trust-store, and Tokio feature changes.
Legacy text completions are opt-in:
[dependencies]
openrouter-rs = { version = "0.24.0", features = ["legacy-completions"] }
HTTP backends and WASI
Requests go through one of two backends, chosen by cargo feature:
| Feature | Default | Backend |
|---|---|---|
reqwest | yes | reqwest 0.13 with rustls; needs a Tokio runtime; enables .http_client(...) |
wasip3 | no | the host's wasi:http/client (WASI 0.3) on wasm32-wasip2; no effect on other targets |
For a WASI component, disable the default reqwest backend and enable wasip3:
[dependencies]
openrouter-rs = { version = "0.24.0", default-features = false, features = ["wasip3"] }
The client API is the same on both backends, including streaming. When both features are on a WASI target, the default client uses wasi:http. The embedding host controls TLS, networking, redirects and timeouts; configure those policies in the host rather than assuming reqwest settings apply.
See tests/fixtures/wasip3-smoke/src/lib.rs for a runnable WASI 0.3 command component. just test-wasip3 runs it against a loopback mock server using Wasmtime 50.0.0 (wasmtime on PATH, or set WASMTIME). It checks authentication, query encoding, multipart upload, binary download, API/body errors, incremental SSE and stream cancellation without an OpenRouter account. Install the compilation target with rustup target add wasm32-wasip2.
API Surface
The canonical public surface is domain-oriented, and each endpoint family has exactly one entry path. The api::<module>::<function>(base_url, api_key, …) helpers and the flat OpenRouterClient methods were removed in 0.23.0 because they could not honor the configured client; see the 0.23 migration notes.
| Domain | Canonical methods | Primary endpoints | Auth note |
|---|---|---|---|
chat() | create, stream, stream_unified | /chat/completions | API key |
responses() | create, stream, stream_unified | /responses | API key |
messages() | create, stream, stream_unified | /messages | API key |
rerank() | create | /rerank | API key |
audio().speech() | create | /audio/speech (legacy /tts fallback) | API key |
audio().transcriptions() | create | /audio/transcriptions | API key |
images() | create, stream, list_models, list_model_endpoints | /images* | API key |
videos() | create, list_models, get_generation, get_content | /videos* | API key |
files() | list, upload, get_metadata, download_content, delete | /files* | API key |
files() | list_container_files, get_container_file, download_container_file, promote_container_file | /containers/*/files* | API key |
models() | list, list_filtered, list_by_category, list_by_parameters, get, list_endpoints, list_providers, list_user_models, list_for_user_with_params, get_model_count, get_rankings_daily, get_rankings_daily_filtered, get_app_rankings, get_session_cost, get_task_classifications, get_benchmarks, list_zdr_endpoints, create_embedding, list_embedding_models | /model*, /models*, /providers, /datasets/*, /classifications/task, /benchmarks, /endpoints/zdr, /embeddings* | API key |
management() | create_api_key, create_api_key_in_workspace, create_api_key_with_options, list_api_keys, list_api_keys_in_workspace, list_presets, get_preset, list_preset_versions, get_preset_version, create_chat_completion_preset, create_response_preset, create_message_preset, get_analytics_meta, query_analytics, list_byok_keys, create_byok_key, get_byok_key, update_byok_key, delete_byok_key, list_observability_destinations, create_observability_destination, get_observability_destination, update_observability_destination, delete_observability_destination, create_auth_code, create_api_key_from_auth_code, list_guardrails, list_guardrails_in_workspace, create_guardrail, list_organization_members, get_organization_settings, update_organization_settings, list_external_users, create_external_user, get_external_user, update_external_user, delete_external_user, list_private_providers, create_private_provider, get_private_provider, update_private_provider, delete_private_provider, list_workspaces, create_workspace, get_workspace, update_workspace, delete_workspace, list_workspace_budgets, get_workspace_budget, upsert_workspace_budget, delete_workspace_budget, list_workspace_members, add_workspace_members, remove_workspace_members, get_activity, get_activity_with_params, get_credits, create_coinbase_charge, get_generation, get_generation_content, submit_generation_feedback | /keys*, /presets*, /analytics*, /byok*, /observability/destinations*, /auth/keys*, /guardrails*, /organization/*, /external-users*, /private-providers*, /workspaces*, /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 |
batches() | list, create, get, delete | /batches* | API key |
vault() | list, list_for_intern, list_connections_for_intern, store, store_for_intern, delete, delete_for_intern, copy_to_intern | /vault* | API key |
decisions() | create, create_system_one | /api/alpha/decisions, /systemone | API key |
management() | get_oauth_jwks, exchange_oauth_token | /oauth/jwks, /oauth/token | Public signing keys; token exchange authenticates with the workload JWT |
management() | list_scim_groups, list_scim_group_mappings, create_scim_group_mapping, get_scim_group_mapping, update_scim_group_mapping, delete_scim_group_mapping, create_scim_sync_job, get_scim_sync_job | /scim/groups, /scim/group-mappings*, /scim/sync-jobs* | Management key |
legacy() | completions().create | /completions | legacy-completions feature + API key |
Vault reads follow the same domain-client style:
// Connections (GitHub, Slack, MCP servers, ...) available to one intern.
for connection in client
.vault()
.list_connections_for_intern("intern-id")
.await?
.data
{
println!("{}", connection.key);
}
At runtime, the builder/client exposes the values the SDK directly consumes:
base_urlapi_keymanagement_keyhttp_refererx_titleapp_categorieshttp_client(featurereqwest)
Chat, Responses API, and Anthropic-compatible Messages request builders also expose experimental_metadata(OpenRouterExperimentalMetadata::Enabled) for OpenRouter's opt-in routing metadata response header.
Common Workflows
openrouter-rs is not just a thin /chat/completions wrapper. The repo currently covers:
- chat completions, responses, and Anthropic-compatible messages
- rerank, audio speech generation, audio transcription, image generation, and video generation polling/content retrieval
- unified streaming across chat, responses, and messages
- manual tools, typed tools backed by
schemars, and OpenRouter server tools such asopenrouter:web_searchandopenrouter:datetime - multimodal chat content, including image, audio, video, and file parts
- model discovery, provider discovery, app rankings, task classifications, unified benchmarks, embeddings, and ZDR endpoints
- typed generation metadata, model voice/benchmark/link metadata, workspace I/O logging controls, video callback URL support, and file upload/download workflows
- explicit chat prompt-cache breakpoints and static predictions, image provider routing controls, conditional model pricing, and image-only video generation requests
- assistant-message model annotations, transcription speaker labels, Anthropic compaction/dynamic-tool blocks, and round-tripped BYOK controls for guardrail/workspace budgets
- management-key workflows for keys, workspace-scoped keys, preset reads/writes, analytics, BYOK provider credentials, observability destinations, auth codes, organization members, workspaces, workspace budgets, workspace member listing/mutation, guardrails, guardrail content filters, workspace-scoped guardrails, and activity, plus API-key-authenticated credits and generation metadata/content endpoints
For deeper examples, prefer the runnable examples in examples/ over long README snippets.
Server Tools
OpenRouter server tools use the same ServerTool type across chat completions, Responses API, Anthropic-compatible Messages, and preset creation request bodies:
use openrouter_rs::{
api::chat::{ChatCompletionRequest, Message},
types::{Role, ServerTool},
};
use serde_json::json;
let request = ChatCompletionRequest::builder()
.model("openai/gpt-5")
.messages(vec![Message::new(Role::User, "Find current OpenRouter docs.")])
.server_tool(ServerTool::web_search_with_parameters(json!({
"max_results": 3
})))
.force_server_tool("openrouter:web_search")
.build()?;
Examples
The repo includes runnable examples for the highest-value workflows:
Application Patterns
| Example | Focus |
|---|---|
examples/axum_chat_gateway.rs | Local Axum gateway with JSON and SSE chat, bounded requests, usage forwarding, and disconnect handling |
examples/typed_tool_agent.rs | Practical typed-tool agent loop with explicit tool dispatch |
examples/domain_chat_completion.rs | Canonical chat() request with the domain-oriented client |
examples/custom_http_client.rs | Inject a custom reqwest::Client (proxies, timeouts, middleware) |
Tokio Streaming
| Example | Focus |
|---|---|
examples/stream_chat_completion.rs | Stream chat deltas into a Tokio task/stdout |
examples/stream_chat_with_tools.rs | Tool-aware streaming aggregation plus a second round after execution |
examples/stream_response.rs | responses() streaming |
examples/stream_messages.rs | messages() streaming |
API Surface Demos
| Example | Focus |
|---|---|
examples/basic_tool_calling.rs | Manual tool-calling loop |
examples/typed_tool_calling.rs | Typed tools with generated schema |
examples/create_response.rs | responses() create |
examples/create_message.rs | messages() create |
examples/create_rerank.rs | rerank().create(...) |
examples/create_speech.rs | audio().speech().create(...) |
examples/create_transcription.rs | audio().transcriptions().create(...) |
examples/create_image_generation.rs | images().create(...) |
examples/create_video_generation.rs | videos().create(...) |
examples/create_embedding.rs | models().create_embedding(...) |
examples/domain_batches.rs | batches().create(...) |
examples/domain_vault.rs | vault().list_connections_for_intern(...) |
examples/domain_decisions.rs | decisions().create(...) |
examples/domain_management_api_keys.rs | API-key management via management() |
examples/list_byok_keys.rs | management().list_byok_keys(...) |
examples/list_observability_destinations.rs | management().list_observability_destinations(...) |
examples/list_organization_members.rs | Organization members/settings and external-user registration listing |
examples/list_workspaces.rs | management().list_workspaces(...) |
examples/exchange_code_for_api_key.rs | PKCE/auth-code flow |
examples/send_completion_request.rs | Legacy completions (legacy-completions required) |
Typical local usage:
export OPENROUTER_API_KEY=sk-or-v1-...
cargo run --example axum_chat_gateway
cargo run --example domain_chat_completion
cargo run --example stream_chat_completion
cargo run --example typed_tool_agent
cargo run --example typed_tool_calling
cargo run --example create_response
cargo run --example create_message
cargo run --example create_rerank
cargo run --example create_speech
cargo run --example create_transcription
cargo run --example create_image_generation
cargo run --example create_embedding
cargo run --example list_byok_keys
cargo run --example list_observability_destinations
cargo run --example custom_http_client
For shell and CI automation recipes built around the companion CLI, see docs/operations/cli-automation-workflows.md.
Continuing a chat after tool calls
Retain the response message before appending tool results so signed/encrypted reasoning
and other modeled assistant metadata survive the next client.chat().create(...) call:
if let Some(message) = choice.message() {
messages.push(openrouter_rs::api::chat::Message::try_from(message)?);
}
// Then append Message::tool_response(...) for each tool call.
Choice::message() returns None for streaming and legacy text choices. The conversion
preserves modeled response fields and rejects missing/unsupported roles; response content
parts retain the SDK's existing text normalization. See examples/typed_tool_agent.rs.
ReasoningDetail::summary and content() expose reasoning.summary blocks.
For streaming tool loops, examples/stream_chat_with_tools.rs collects text/reasoning
and retains reasoning-detail objects in arrival order before sending tool results.
Prompt-cache usage is available through response.usage → prompt_tokens_details →
cached_tokens / cache_write_tokens. These are optional provider-reported counts;
missing data is not evidence of a cache miss. The same usage type is used for streaming.
CLI Companion
This workspace also contains crates/openrouter-cli, a companion CLI for profile resolution, discovery, management, and usage/billing workflows.
Examples:
cargo run -p openrouter-cli -- --help
cargo run -p openrouter-cli -- profile show
cargo run -p openrouter-cli -- models list --category programming
cargo run -p openrouter-cli -- keys list --include-disabled
cargo run -p openrouter-cli -- workspaces list --limit 20
cargo run -p openrouter-cli -- usage activity --date 2026-03-01
See crates/openrouter-cli/README.md for the full command surface and config/auth precedence rules.
For copy-paste shell/CI recipes, see docs/operations/cli-automation-workflows.md.
Project Status
- Community-maintained third-party SDK; not affiliated with OpenRouter
- Canonical docs and examples prefer the domain clients over older flat helpers
- Accepted endpoint coverage is tracked against the current OpenAPI snapshot, and the current baseline is reviewed, with
140 / 154operations implemented at the SDK surface and 14 newer operations deferred - Live integration coverage and gaps are published in
docs/operations/official-endpoint-test-matrix.md - Migration guidance for the
0.9.x -> 0.10.0public-model future-proofing release, the0.8.x -> 0.9.0audio speech release, the0.7.x -> 0.8.0transport/error-surface release, and the archived0.5.x -> 0.6.xnaming guide lives inMIGRATION.md - Legacy
POST /completionssupport remains available behind thelegacy-completionsfeature
🔁 0.10 Public Model Migration
Full migration guide: MIGRATION.md
- High-churn public SDK request, response, metadata, usage, pricing, discovery, streaming, and upstream taxonomy types are
#[non_exhaustive] - Replace affected struct literals with builders, constructors, helpers, or serde deserialization
- Add wildcard arms when matching affected public enums outside the crate
- Use constructors such as
ResponseUsage::new(...),ToolCall::new(...),FunctionCall::new(...), andJsonSchemaConfig::new(...)for small helper/test fixtures - This source-level break lands in
0.10.0
🔁 0.9 Audio Speech Migration
client.tts().create(...)->client.audio().speech().create(...)api::tts::TtsRequest->api::audio::SpeechRequestapi::tts::TtsResponseFormat->api::audio::SpeechResponseFormatapi::ttsremains as a deprecated compatibility module, but new examples and docs useapi::audio- Newly added and high-churn public request/response structs use builder construction and may be marked
#[non_exhaustive]; prefer request builders over struct literals
🔁 0.8 Transport/Error Migration
Full migration guide: MIGRATION.md
OpenRouterError::HttpRequest(surf::Error)->OpenRouterError::HttpRequest(HttpRequestError)ApiErrorContext.status: surf::StatusCode->ApiErrorContext.status: http::StatusCodeopenrouter_rs::utils::{with_bearer_auth, with_request_metadata, with_client_request_headers, handle_error}-> caller-owned transport helpers or direct use of the canonical domain clients- No API migration is required if you only use
OpenRouterClientpluschat(),responses(),messages(),rerank(),audio(),images(),videos(),files(),models(),management(), andlegacy()
🔁 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 removed the transitional aliases above; use the canonical method names shown here.
Development
Prefer the just recipes so local work stays aligned with CI:
just quality
just quality-ci
just test-live-contract
OPENROUTER_MANAGEMENT_KEY=... just test-live-contract-management
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.
Docs Map
Start with docs/README.md for grouped navigation across root docs, docs/, specs/, and subsystem READMEs.
Users And Setup
MIGRATION.mdfor upgrade guidance across breaking SDK changescrates/openrouter-cli/README.mdfor CLI behavior, examples, and auth/config precedenceCHANGELOG.mdfor release-by-release history
Contributors And Project Policies
CONTRIBUTING.mdfor contributor workflow and review expectationsdocs/policies/maintenance-policy.mdfor release, MSRV, and breaking-change policydocs/policies/compatibility-update-policy.mdfor upstream compatibility reporting cadence, templates, and update rulesSECURITY.mdfor vulnerability reportingSUPPORT.mdfor support boundaries and issue-reporting guidance
Design And Roadmap
docs/design/generated-core-architecture.mdfor the generated-core plus idiomatic-wrapper design baselinedocs/design/http-transport-migration.mdfor the historical design baseline behind the completedreqwest + rustlstransport migration
Operations, Validation, And Distribution
docs/operations/official-endpoint-test-matrix.mdfor endpoint-by-endpoint implementation and test statusdocs/operations/openapi-drift-reporting.mdfor weekly upstream-spec drift detection and baseline refresh workflowdocs/operations/cli-automation-workflows.mdfor JSON-first shell and CI recipes built aroundopenrouter-clitests/integration/README.mdfor live test pools and env switchesdocs/community/awesome-openrouter/README.mdfor the Awesome OpenRouter submission kit and directory-safe assets
📈 Release History
Unreleased
Version 0.24.0 (Latest)
- Accepted the November 3 OpenAPI snapshot:
Model/UserModelexposeendpoints, ZDR endpoints exposesafety_retention, and Responses requests can opt into OpenAI access programs.POST /api/alpha/extractionsstays deferred. - Breaking: private providers dropped
data_policyupstream, soPrivateProviderDataPolicyand thedata_policyfields are removed. See the 0.24 migration notes. - The endpoint matrix now matches the shipped surface again, and
test_real_tool_callruns in the live workflow instead of being skipped everywhere.
Version 0.23.0
- Breaking: One entry path per endpoint family: the 162
api::*endpoint functions and 109 flatOpenRouterClientmethods are gone, so every call honours the configured client. See the 0.23 migration notes. - Breaking: Transport failures carry
HttpRequestErrorKind, the request URL, andretry_after; streaming has one event model (UnifiedStreamEvent) whose terminal event carries assembledtool_callsand typedusage. - Breaking: Upstream drift accepted in the same release:
client.interns()is removed,/end-users*became/external-users*, andmanagement()gained/private-providers*. - Reasoning setters keep the request valid:
reasoning_effortandreasoning_max_tokensare mutually exclusive, as the API requires. - Accepted drift fills gaps that were silently dropped: guardrail harness flag, prompt-cache breakpoint
ttl,GET /models/userclientfilter, and vault routing metadata.
Version 0.22.0
- Preserve
reasoning_content/reasoning_textacross chat responses, raw deltas and request replay; expose completion-token details. - Decode choices by shape with useful errors, accept omitted tool-call types, and preserve structured API errors with string codes.
- Breaking: Choice error codes are now
Option<ErrorCode>and upstream chat cost fields areOption<f64>. See the migration guide.
Version 0.21.1
- Expose
FinishReason::as_strto read wire names directly, including unknown provider finish reasons.
Version 0.21.0
- Added opt-in WASI 0.3 HTTP transport for
wasm32-wasip2, including streaming andSendfutures, plusFrom<HttpRequestError> for OpenRouterError. - Breaking: Raised the SDK and workspace CLI MSRV to Rust 1.93. Consumers using
default-features = falsemust explicitly enablereqwestorwasip3; see the 0.21 migration notes. - Preserved native reqwest charset/BOM decoding and added real-host WASI coverage for multipart, binary responses, errors, incremental SSE and cancellation.
Version 0.20.0
- Breaking: Upgraded the HTTP transport to
reqwest 0.13;.http_client(...)now accepts only areqwest 0.13client. Default native TLS uses platform certificate verification and AWS-LC, and the SDK's direct Tokio features narrowed toio-util. See the 0.20 migration notes. - Added intern icon and vault connection reads, plus the October 20 schema surface: Batch callback/expiry/provider metadata, endpoint service tiers and diarization, guardrail safety-retention controls with clear builders, observability cost-allocation broadcasting, video signed URLs, image privacy controls, and Responses
stop. - Accepted the October 20 OpenAPI snapshot (
140 / 153operations implemented; 13 deferred), forwarded vault attribution headers, and added adoption-metrics plus Axum streaming coverage.
Version 0.19.0
- Added Intern daemon signing with an OIDC session carrying
vault:read, BYOK declared regions, key budgets/last-used timestamps, expired-key filters, workspace moves and video expiration. - Added speech turn input/instructions, portable deferred-tool controls across Chat/Messages/Responses, chat function deferral and Messages tool-search result blocks.
- Breaking:
SpeechRequest::input(including the TTS alias) now usesSpeechInputfor text or turns. Existing text builder calls work unchanged; direct field access needs the 0.19 migration notes. - Added explicit key-limit clearing and preserved existing PATCH clear operations through JSON round trips. Corrected the legacy reasoning test and accepted the October 13 OpenAPI snapshot (
138 / 151implemented; 13 deferred).
Version 0.18.0
- Added prompt-cache usage details and assistant-message replay helpers that preserve modeled metadata, including reasoning summaries, signed/encrypted reasoning, and null content. Updated non-streaming and streaming tool-agent examples to retain context.
- Added end-user registration management and organization settings, plus Batch fallback, audio provider, and activity cache-token fields. Preserved generic server-tool request types.
- Accepted the October 6 OpenAPI review with
136 / 149operations implemented and 13 explicitly deferred. Absent reasoning text/data fields now serialize as omitted rather than null.
Version 0.17.0
- Added asynchronous Batch APIs, Intern invocation/daemon access, shared provider options, audio URL/image references, transcription metadata, and SCIM filters.
- Hardened credential response errors, forwarded Batch/Intern/SCIM attribution headers, and rejected empty audio URLs.
- Deprecated daemon-access and Coinbase charge aliases with documented replacements; retained compatibility entry points. Accepted the September 30 OpenAPI review with
129 / 142operations implemented and 13 explicitly deferred.
Version 0.16.0
- Added typed Intern lifecycle and streaming chat, workspace/intern vault secrets, and Decisions/System One domain clients, with runnable examples.
- Accepted the 2026-09-23 OpenAPI drift across all
122 / 122operations, including current API-key, BYOK, audio, embedding, image, message, rerank, video, workspace, generation, and model-endpoint schemas.
Version 0.15.0
Added container files, workload OAuth token exchange/signing keys, SCIM sync jobs, regional management controls, and expanded message/model fields. Accepted the 2026-09-08 OpenAPI review with
105 / 105tracked operations.Added session-cost datasets, single-interval workspace budgets, activity workspace filters, benchmark search filters, speech voice cloning, observability generation broadcast flags, and stored generation content errors.
Breaking:
ByokKey::workspace_idis now optional, anddelete_workspace(...)takes an optionalconfirm_default_workspace_deletionargument.Accepted the 2026-08-17 OpenAPI drift review and restored tracked endpoint coverage to
97 / 97.
Version 0.14.0
- Tool-aware chat streaming now preserves provider-supplied tool-call indices without inventing missing values, and
FinishReason::Otherkeeps unknown provider finish reasons forward-compatible. - Added SCIM group and group-role mapping management plus provider-aware Files API support.
- Accepted the 2026-08-03 OpenAPI drift review and restored tracked endpoint coverage to
95 / 95.
Version 0.13.0
- Added explicit prompt-cache controls, static predicted output, image provider routing, conditional pricing overrides, cache-creation usage details, and guardrail
flagactions. - Added assistant-message model annotations, BYOK-aware guardrail/workspace budgets, workspace default guardrail IDs, transcription speaker labels, and Anthropic compaction/dynamic-tool blocks.
- Enabled image-only video requests and kept the accepted OpenAPI snapshot at
89 / 89through the 2026-07-28 review. - Breaking: workspace budget upserts now return
UpsertWorkspaceBudgetResponse; read the budget from.data. - Breaking: direct construction or matching of
ContentPart::Textmust account forprompt_cache_breakpoint; prefer the provided constructors or..patterns.
Version 0.12.0
- Added OpenRouter server-tool request helpers for chat completions, Responses API, Anthropic-compatible Messages, and preset creation request bodies.
- Added management-key SDK support for generation feedback and workspace member listing.
- Added model/rankings filters, analytics classifier controls, verbose transcription fields, XAI ZDR policy, routed service tiers, server-tool reasoning details, and image text chunks.
- Accepted OpenAPI drift through 2026-07-14 and restored tracked endpoint coverage to
89 / 89.
Version 0.11.1
- Accepted OpenRouter's new
maxreasoning effort and preserved future provider-defined effort strings in model metadata, keeping/modelsdeserialization and CLI model listing forward-compatible with upstream taxonomy additions. - Hardened scheduled live Responses checks so transient runtime statuses stay service warnings while completed empty outputs, SDK deserialization failures, and non-retryable API errors remain hard failures.
Version 0.11.0
- Added typed SDK coverage for image generation, files, analytics, app rankings, task classifications, unified benchmarks, singular model lookup, rankings-daily, preset listing/readback/versioning, workspace budgets, and expanded model filters.
- Added automatic prompt caching request support through top-level
cache_controlbuilders for chat completions and Responses API requests. - Refreshed multimodal and metadata schemas, including rerank image-only document echoes, nullable model/generation metadata, Responses debug options, and Anthropic Messages system-role helpers.
- Accepted OpenAPI drift through the 2026-06-29 review and restored the tracked endpoint snapshot to
87 / 87.
Version 0.10.0
- Marked high-churn public SDK request, response, metadata, usage, pricing, discovery, streaming, and upstream taxonomy types as
#[non_exhaustive]; use builders, constructors, helpers, serde deserialization, or wildcard enum arms when migrating from0.9.x. - Added typed SDK coverage for audio transcriptions, BYOK provider credentials, observability destinations, multimodal embedding media parts, experimental response metadata, and model/generation metadata refreshes.
- Added
OpenRouterClientBuilder::http_client(...)for injecting a customreqwest::Clientwhile preserving the default transport when omitted. - Accepted OpenAPI drift through the 2026-05-19 review and restored the tracked endpoint snapshot to
62 / 62, while preserving OpenRouter metadata on normalized API errors and Anthropic Messages stream stop events.
Version 0.9.0
- Added the canonical
audio().speech()SDK surface for official/audio/speech, with deprecatedtts()compatibility aliases. - Expanded workspace, workspace-scoped keys/guardrails, workspace I/O logging, generation content/metadata, and video callback coverage while keeping the endpoint snapshot at
51 / 51. - Marked high-churn public types as builder-first/future-proof and documented the
0.8.x -> 0.9.0migration path.
Version 0.8.1
- Added typed
POST /ttssupport with the canonicaltts()client surface and a runnable example. - Added live smoke coverage for
POST /rerankandGET /organization/members, and restored the repo snapshot to43 / 43accepted OpenAPI endpoints. - Added
openrouter-cli organization members listand aligned the CLI/docs surface with the latest management coverage.
Version 0.8.0
- Completed the SDK transport migration to
reqwest + rustlsand removed the legacysurf/curldependency chain. - Made the public HTTP error surface backend-neutral and documented the
0.7.x -> 0.8.0breaking changes. - Expanded the repo snapshot with rerank, video, and organization-member coverage plus refreshed examples and CLI automation docs.
Version 0.7.0
- Removed the SDK-level config surface and kept file/profile config out of the core crate.
- Standardized the canonical domain-oriented client docs around the
0.7.xAPI surface. - Improved error normalization for
HTTP 200payloads that actually contain API error bodies.
Contributing
See CONTRIBUTING.md for the full contributor workflow.
At a minimum, if you change public API surface, examples, or docs:
- 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
Related policies:
License
MIT. See LICENSE.
Compatibility
- Runs on
- GPU support unknown
What shows it
- no dependency or feature matches a backend row
- Native code
- None found
- No native code found
- Python bindings
- No Python binding crate found
- License
- MIT
Compare with similar projects
Order: strongest tier first, then most downloads, then name, with unmeasured values last. A library counts downloads over 30 days. An app counts binary downloads per release. An app with none counts its crate downloads over 30 days. ML Rust runs this catalogue, so its closest project always gets a row.
| Project | Downloads | Dependents | Stars | Latest release | Runs on (GPU) | Native code | License |
|---|---|---|---|---|---|---|---|
|
A type-safe OpenRouter Rust SDK |
8,599 downloads over 30 days | 3 | 98 | 0.24.0 | GPU support unknown | No native code found | MIT |
|
aisdk Listed
An open-source Rust library for building AI-powered applications, inspired by the Vercel AI SDK. It provides a robust, type-safe, and easy-to-use interface for interacting with various Large Language Models (LLMs). |
36,877 downloads over 30 days | 4 | 263 | 0.6.1 | GPU support unknown | No native code found | MIT |
|
liter-llm Listed
Universal LLM API client — 174 providers, streaming, tool calling. Rust-powered, type-safe, compiled. |
13,151 downloads over 30 days | 8 | 264 | 2.7.0 | GPU support unknown | Binds native code: libmimalloc-sys (feature mimalloc), tikv-jemalloc-sys (feature jemalloc) | MIT |
|
gemini-client Listed
A Rust SDK for the Google Gemini API |
2,207 downloads over 30 days | 2 | 13 | 0.10.0 | GPU support unknown | No native code found | MIT |
|
anthropic-sdk-rs Listed
An unofficial Rust SDK for Anthropic's Claude AI API |
2,116 downloads over 30 days | 4 | 18 | 0.2.27 | GPU support unknown | No native code found | MIT |
|
Anthropic Rust SDK. |
1,949 downloads over 30 days | 6 | Not measured | 0.0.8 | GPU support unknown | No native code found | MIT |
|
An open protocol that gives AI agents a secure, sandboxed place to run code and use tools — with lean context usage. AXP works alongside MCP |
Not measured | Not applicable | 3 | Not measured | Not measured | Not measured | Apache-2.0 |
Why ListedNo archive, New or Featured rule places it, so it is Listed.
What it lacks for Featured
- It has 3 active dependents and 2 new dependents in 365 days. Featured needs 11 active dependents or 9 new dependents in 365 days. The repository route reads 98 stars, 24 forks and 10 contributors. It needs 4,539 stars, 434 forks and 79 contributors together.
What else the check found
- The last activity is on 3 Nov 2026, 6 days ago. The rules expect an update within 365 days. Dormancy rule
Exact rules: Listed, Featured library. The check on applied thresholds version 9.
Every rule outcome, as the check records it
expected-interval: version 0.24.0 base 140, raised to the 365-day floor: E = 365 daysdormancy: last activity 2026-11-03, 6 days ago, E = 365: activefeatured: not featured: active_users 3 < 11 and new_adopters 2 < 9 and repository route stars 98 (needs 4539), forks 24 (needs 434), contributors 10 (needs 79)listed: listed: no archive, new or featured rule applies
Crates2 crates
- openrouter-rs Primary
- openrouter-cli
Measurements and sources
Each signal row shows the raw value, its source and the fetch date. The Sources list gathers every distinct source on this page. Movement needs more history.
Sources6 sources
- Description: the crates.io description
- crates.io database dump, fetched
- RustSec advisory database, fetched
- GitHub repository, fetched
- crates.io package, fetched
- GitHub contributors, fetched
Adoption3 active dependents, 2 new dependents in 365 days1 not measured
| Signal | Value | Source | Fetched | Counts |
|---|---|---|---|---|
| Active dependents | 3 | crates.io database dump | Yes | |
| New dependents (365 days) | 2 | crates.io database dump | Yes | |
| Peak active dependents | 3 | crates.io database dump | Yes | |
| Active dependents as a share of the peak | 1 | crates.io database dump | Yes | |
| Binary downloads per release | Not measured | Yes |
MaintenanceLatest human commit: 6 days ago3 not measured
| Signal | Value | Source | Fetched | Counts |
|---|---|---|---|---|
| Latest human commit | 2026-11-03 | GitHub repository | Yes | |
| Latest release | 2026-11-03 | crates.io database dump | Yes | |
| First release | 2025-07-29 | crates.io database dump | Yes | |
| Latest version | 0.24.0 | crates.io database dump | Yes | |
| Days the oldest outside issue waits for a reply | 0 | GitHub repository | Yes | |
| Maintainer replies over 365 days | 57 | GitHub repository | Yes | |
| Repository archived | false | GitHub repository | Yes | |
| Repository gone | false | GitHub repository | Yes | |
| Release commit or manifest in the repo | true | crates.io package | Yes | |
| Published docs | true | crates.io database dump | Yes | |
| Latest release fails cargo check | Not measured | Yes | ||
| Build check date | Not measured | Yes | ||
| Build check toolchain | Not measured | Yes |
SecurityUnpatched vulnerabilities: none
| Signal | Value | Source | Fetched | Counts |
|---|---|---|---|---|
| Unpatched vulnerabilities past the grace window | none | RustSec advisory database | Yes | |
| RustSec unmaintained advisory | none | RustSec advisory database | Yes | |
| Deprecation notice | none | crates.io database dump | Yes | |
| Deprecated requirement | none | crates.io database dump | Yes |
Distribution29 releases, 8,599 downloads over 30 days5 not measured
| Signal | Value | Source | Fetched | Counts |
|---|---|---|---|---|
| Releases | 29 | crates.io database dump | Yes | |
| Downloads over 30 days | 8599 | crates.io database dump | Yes | |
| Binary downloads over the last 3 releases | Not measured | Yes | ||
| Homebrew installs on request over 365 days | Not measured | Yes | ||
| Repology repository families | Not measured | Yes | ||
| Docker pull growth over 90 days | Not measured | Yes | ||
| Docker pulls at the growth baseline | Not measured | Yes | ||
| Every version a prerelease | false | crates.io database dump | Yes | |
| Every version 0.0.x | false | crates.io database dump | Yes | |
| Every version yanked | false | crates.io database dump | Yes | |
| Crate deleted from crates.io | false | crates.io database dump | Yes |
Repository98 stars, 24 forks, 10 contributors, 408 commits. Stars alone never qualify a project.
| Signal | Value | Source | Fetched | Counts |
|---|---|---|---|---|
| GitHub stars | 98 | GitHub repository | Yes — one part of the repository route | |
| GitHub forks | 24 | GitHub repository | Yes — one part of the repository route | |
| Contributors with a GitHub account | 10 | GitHub contributors | Yes — one part of the repository route | |
| Commits on the default branch | 408 | GitHub repository | No | |
| Repository's main crate left out of the entry | none | crates.io database dump | Yes |
Facts that never count
| Signal | Value | Source | Fetched | Counts |
|---|---|---|---|---|
| License | MIT | crates.io database dump | No | |
| Runs on, from listed crates and their direct dependencies | GPU support unknown | crates.io database dump | No | |
| What shows each backend | no dependency or feature matches a backend row | crates.io database dump | No | |
| Native code, from listed crates and their dependencies | No native code found | crates.io database dump | No | |
| Python bindings, from direct dependencies of listed crates | No Python binding crate found | crates.io database dump | No | |
| Crates that depend on a listed crate directly | 3 | crates.io database dump | No |
Corrections and review history
No correction applies to this entry.
Judgments
A judgment enters only through an approved issue and a merged pull request.
No judgment applies to this entry.