Expand description
A low-level Rust interface for interacting with OpenAI’s API.
This crate provides a simple, efficient, and low-level way to interact with OpenAI’s API, supporting both streaming and non-streaming responses. It leverages Rust’s powerful type system for safety and performance, while exposing the full flexibility of the API.
§Features
- Chat Completions: Full support for OpenAI’s chat completion and completion API, including both streaming and non-streaming responses, and multimodal user messages (text / image / audio / file content parts).
- Responses: Create model responses with the Responses API (string or item-based input, function tools, built-in web search, streaming events), retrieve and delete stored responses. Tested against DeepSeek and Qwen.
- Models: List, retrieve and delete models.
- Embeddings: Create embedding vectors from text input.
- Moderations: Classify whether text and/or image input is potentially harmful (untested).
- Images: Generate, edit, and create variations of images (untested).
- Audio: Text-to-speech, transcription, and translation endpoints (untested).
- Files: Support for the OpenAI file API (upload, list, retrieve, delete, download content).
- Streaming and Non-streaming: Support for both streaming and non-streaming responses.
- Strong Typing: Complete type definitions for all API requests and responses, utilizing Rust’s powerful type system.
- Configurable HTTP Client: Every request method takes a
reqwest::Client, so proxies, timeouts and connection pooling are under your control. Seerest::default_clientfor a sensible default, andrest::install_crypto_providerto pick the TLS backend. - Error Handling: Comprehensive error handling with detailed error types defined in
the
errorsmodule. Failed requests carry the API’s error message, type and code. - Async/Await: Built with async/await support.
- Musl Support: Designed to work with musl libc out-of-the-box; TLS is pure Rust, so no OpenSSL or C toolchain is needed.
- Multiple Provider Support: Expected to work with OpenAI, DeepSeek, Qwen, and other compatible API providers.
§Cargo Features
Fields that are proprietary to a single provider are opt-in via cargo
features. Cross-vendor de-facto standards — such as reasoning_content
(streamed by DeepSeek, Qwen3, ollama, vLLM and OpenRouter alike) and
reasoning_effort — are always available:
-
reasoning(default): cross-vendor reasoning fields —reasoning_contenton assistant messages (request and response), streamed deltas, and logprobs, plus its accumulation inchat::create::accumulator::ChatCompletionAccumulator. -
deepseek: enables DeepSeek’s proprietary fields — the Beta chat prefix completion fields (prefix, andreasoning_contentas the prefix-completion CoT input), thethinkinganduser_idrequest parameters, and theprompt_cache_hit_tokens/prompt_cache_miss_tokensusage statistics. Impliesreasoning. See api-docs.deepseek.com. -
qwen: Enables Qwen’s proprietary fields — the chat request parametersenable_thinking,thinking_budgetandtop_k, the Responses API input partinput_file, the built-in tools (web_extractor,code_interpreter,web_search_image,image_search,file_search,mcp), the corresponding output items and streaming events, and thex_details/x_toolsusage statistics. Impliesreasoning. See the Qwen OpenAI-compatible Chat API docs and the Qwen Responses API docs. -
azure: deprecated no-op. Streamingdelta.annotationsanddelta.audioare now always available (the non-streaming message fields were never gated). The empty feature remains defined so existing manifests keep compiling.
There is one feature unrelated to request fields:
ferritls: Adds the pure-Rustferritls-rustlsTLS crypto backend and therest::install_crypto_providerhelper that installs it. Off by default, so the crate never dictates your crypto backend; when you leave it off, install arustls::crypto::CryptoProvideryourself before building any client. See “TLS Crypto Provider”.
§Implemented APIs
- Chat Completions (create / retrieve / update / delete)
- Responses (create / retrieve / delete)
- Completions
- Models (list / retrieve / delete)
- Embeddings
- Moderations (untested)
- Images (generate / edit / variation, untested)
- Audio (speech / transcriptions / translations, untested)
- Files (create / list / retrieve / delete / download content)
§TLS Crypto Provider
HTTP is done by reqwest, depended on with its rustls-no-provider
feature: the rustls stack is compiled without a crypto backend, which
keeps the pure-Rust build (no C or asm toolchain needed) and leaves the
backend choice to the application. Consequently, exactly one
rustls::crypto::CryptoProvider must be installed as the process default
before any reqwest::Client is built — including the one returned by
rest::default_client. If none is installed, reqwest panics at client
construction time.
This crate never installs a provider on your behalf. The optional
ferritls cargo feature adds the pure-Rust ferritls-rustls backend
together with rest::install_crypto_provider, so you can delegate that
one decision to the crate:
[dependencies]
openai-interface = { version = "0.12", features = ["ferritls"] }// Choose the backend once, before building any client:
openai_interface::rest::install_crypto_provider()
.expect("a rustls crypto provider was already installed");To use a different backend (ring, aws-lc-rs, or a hand-picked
rustls::crypto::CryptoProvider), leave the feature off and install it
yourself — first install wins, so whichever provider is in place when the
first client is built is the one everything in the process uses:
// In the application crate, with `rustls = "0.23"` (feature `ring` or
// `aws-lc-rs`) as one of its own dependencies:
rustls::crypto::ring::default_provider()
.install_default()
.expect("a rustls crypto provider was already installed");§When nothing needs to be installed
Cargo features are additive across the dependency tree, so if your project
depends on reqwest itself with a crypto backend compiled in — its default
default-tls, or rustls explicitly — reqwest falls back to the
aws-lc-rs provider it ships with, and no install step is needed at all.
Enabling native-tls instead routes TLS through the system stack, so the
rustls path is never taken.
[dependencies]
reqwest = "0.13" # default features: `default-tls` -> `rustls`
openai-interface = "0.12" # no provider of its ownThe catch is that the backend is then decided by feature unification rather
than by you, and an unrelated dependency change can move it. To pin the
choice, enable the ferritls feature or install a provider yourself.
§Examples
§Non-streaming Chat Completion
This example demonstrates how to make a non-streaming request to the chat completion API.
use openai_interface::chat::create::request::{Message, RequestBody};
use openai_interface::chat::create::response::no_streaming::ChatCompletion;
use openai_interface::rest::{RequestOptions, default_client, post::PostNoStream};
const DEEPSEEK_CHAT_URL: &'static str = "https://api.deepseek.com";
const DEEPSEEK_MODEL: &'static str = "deepseek-v4-flash";
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
// Needs the `ferritls` cargo feature; leave it out if you install
// your own rustls crypto provider. See the "TLS Crypto Provider"
// section above.
openai_interface::rest::install_crypto_provider().ok();
let request = RequestBody {
messages: vec![
Message::system("You are a helpful assistant."),
Message::user("Hello, how are you?"),
],
model: DEEPSEEK_MODEL.to_string(),
stream: Some(false),
..Default::default()
};
// Send the request
let chat_completion: ChatCompletion = request
.get_response(&default_client(), DEEPSEEK_CHAT_URL, &RequestOptions::bearer("YOUR_API_KEY"))
.await?;
let text = chat_completion.choices[0]
.message
.content
.as_deref()
.unwrap();
println!("{:?}", text);
Ok(())
}§Streaming Chat Completion
This example demonstrates how to handle streaming responses from the API. As with the non-streaming example, all API parameters can be adjusted directly through the request struct.
use openai_interface::chat::create::request::{Message, RequestBody};
use openai_interface::chat::create::response::streaming::ChatCompletionChunk;
use openai_interface::rest::{RequestOptions, default_client, post::PostStream};
use futures_util::StreamExt;
const DEEPSEEK_CHAT_URL: &'static str = "https://api.deepseek.com";
const DEEPSEEK_MODEL: &'static str = "deepseek-v4-flash";
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let request = RequestBody {
messages: vec![
Message::system("You are a helpful assistant."),
Message::user("Who are you?"),
],
model: DEEPSEEK_MODEL.to_string(),
stream: Some(true),
..Default::default()
};
// Send the request
let mut response_stream = request
.get_stream_response(&default_client(), DEEPSEEK_CHAT_URL, &RequestOptions::bearer("YOUR_API_KEY"))
.await?;
let mut message = String::new();
while let Some(chunk_result) = response_stream.next().await {
let chunk: ChatCompletionChunk = chunk_result?;
if let Some(content) = chunk.choices[0].delta.content.as_deref() {
println!("content chunk: {}", content);
message.push_str(content);
}
}
println!("complete message: {}", message);
Ok(())
}§Musl Build
This crate is designed to work with musl libc, making it suitable for
lightweight deployments in containerized environments. TLS is provided by
rustls with a pure-Rust crypto backend, so OpenSSL does not need to be
built from source. See rest::install_crypto_provider for how the
backend is selected at runtime.
To build for musl:
rustup target add x86_64-unknown-linux-musl
cargo build --target x86_64-unknown-linux-muslRe-exports§
Modules§
- audio
- Turn audio into text or text into audio.
- batches
- The Batches API: run async batch processing jobs over collections of
requests via
/batches. - chat
- Chat Completions API Module
- completions
- Given a prompt, the model will return one or more predicted completions,
and can also return the probabilities of alternative tokens at each position.
Compared to the
chatAPI, this one does not provide the ability to have multiple rounds of conversation. This API is getting deprecated in favor of thechatAPI. - containers
- The Containers API: manage container objects via
/containers. - conversations
- The Conversations API: manage conversation state via
/conversations. - embeddings
- Get a vector representation of a given input that can be easily consumed by machine learning models and algorithms.
- errors
- evals
- The Evals API: manage evaluation runs via
/evals. - files
- File management module for OpenAI API integration.
- fine_
tuning - The Fine-tuning API: manage fine-tuning jobs via
/fine_tuning. - images
- Given a prompt and/or an input image, the model will generate a new image.
- models
- List and describe the various models available in the API.
- moderations
- Given text and/or image inputs, classifies if those inputs are potentially harmful.
- pagination
- Cursor pagination helpers shared by list endpoints.
- realtime
- The Realtime API (HTTP part): create ephemeral client sessions via
/realtime. - responses
- The Responses API: create model responses and retrieve stored ones.
- rest
- REST API client module for OpenAI interface
- uploads
- The Uploads API: upload large files in multiple parts via
/uploads. - vector_
stores - The Vector Stores API: manage vector stores via
/vector_stores.