# openai-api-rs ticks fourteen endpoints, ships no tests, and compiles proxy support in

> dongri/openai-api-rs is an unofficial single-crate Rust client for the OpenAI API with first-class OpenRouter support. Its documentation is short and its manifest is precise: one TLS switch governs both the HTTP and WebSocket transports, proxy support is enabled unconditionally, and the twenty-one runnable files in the repository are all examples with no test suite behind them.

**dongri/openai-api-rs** — OpenAI API client library for Rust (unofficial)

- Repository: https://github.com/dongri/openai-api-rs
- Website: https://docs.rs/openai-api-rs
- Stars: 486 · Forks: 94
- Language: Rust
- License: MIT
- Published: 2026-09-14 · Updated: 2026-09-14 · Language: en
- Canonical page: https://hysenlabs.com/projects/dongri-openai-api-rs

## The example consumes the client on its second line of output

The documented send step does something worth noticing. After the request returns and the first choice is printed, the example iterates over the client's headers:

```rust
let result = client.chat_completion(req)?;
println!("Content: {:?}", result.choices[0].message.content);

for (key, value) in client.headers.unwrap().iter() {
    println!("{}: {:?}", key, value);
}
```

Unwrapping that field takes ownership of it, so the client is partially moved by the end of the snippet and cannot be used for a second request afterwards. It works as a one-shot example and stops being usable as soon as you want to print the headers, which is the opposite of what the surrounding text implies about a client you configured once and reuse.

The line above it has the same shape of hazard in a milder form. Indexing the first choice directly means an empty choices array panics rather than returning an error, so a request that the service accepts but answers with nothing takes the process down instead of surfacing a value you can inspect.

## Fourteen endpoints are ticked and five of them have no example

The supported-API list is fourteen rows with every box checked: completions, chat, edits, images, embeddings, audio, files, fine-tuning, moderations, function calling, assistants, batch, realtime and responses. A list where everything is checked carries no information, so the useful comparison is against what the repository actually contains.

The examples directory holds twenty-one programs. They cover chat completion in both blocking and streaming form, plain completions, embeddings, vision, the four audio paths for speech, transcription and translation, batch, assistants, function calling in two variants, the responses API in blocking and streaming form, model listing, and a realtime directory. Three of the files plus a data directory target OpenRouter specifically, one of them for listing models there and one for a reasoning-style request.

Cross the two lists and five ticked endpoints have no example at all: edits, images, files, fine-tuning and moderations. So the checklist describes the intended surface, the examples describe the demonstrated surface, and the two are not the same shape. For a client library that difference matters, because an endpoint with no example is also an endpoint whose request and response types nobody has exercised in this tree.

## One TLS switch governs both the HTTP client and the WebSocket client

The manifest declares two transport feature sets and makes them all-or-nothing across both of the crate's transports. The default feature selects the native TLS backend, and it does so by enabling it on the HTTP client and on the WebSocket client in the same list. An alternative feature selects the Rustls backend, again for both at once.

That design is tidy for the common case, where a project wants one TLS story everywhere, and restrictive for the cases where it does not. A project that has standardised on Rustls for outbound HTTP but needs a WebSocket client configured differently cannot express it here; it takes both or changes neither. The websocket dependency exists because the realtime API is a socket protocol, which is why the two features are declared together in the first place.

The HTTP dependency itself is configured with its defaults switched off and its features selected one by one, which is the careful way to do it. The list includes proxy support, which is the one entry that is not obviously needed by an API client and is not something a consumer would think to check.

## Two documented ways to change the base URL, and they appear in different sections

There are two mechanisms for pointing the client somewhere other than the default, and the documentation introduces them separately without reconciling them. One is a builder method that takes an endpoint URL directly, and it is what the OpenRouter example uses. The other is an environment variable holding the base address, marked optional, with an example value pointing at the public API host.

Both end up in the same place, so the choice is about precedence rather than capability, and precedence is exactly what is left unstated. Whether a value in the environment overrides a builder call, or is only consulted when the builder was left alone, is not written down anywhere in the visible documentation. A reader who sets both gets whichever the library prefers, and they will find out by observing the request rather than by reading.

The key handling is cleaner by comparison, and worth praising. Both clients are built from an environment variable read in the example, the documentation recommends an environment variable rather than a literal in source, and the two supported hosts are shown as two separate variables rather than one that has to be overloaded.

## Twenty-one example programs and no test suite

The repository has two source directories and one example directory, plus the manifest, the license and the workflow configuration. There is no test directory, and the manifest declares no development dependencies.

Twenty-one example files, two of which are directories, is the entire executable surface of the crate. That is a defensible choice for a thin client where the interesting behaviour lives in someone else's service, and examples are genuinely more useful than tests for showing how a request is shaped. It is also the reason you cannot tell from the repository whether a change broke anything: nothing asserts that a request is built correctly, only that a program that builds one compiles.

The distribution of those examples is informative in its own right. Streaming has two files, one blocking and one not, and the responses API has the same pair, which says the streaming paths were considered worth two demonstrations each. Vision, model listing and the three audio operations each get one. Whether the request and response types for the unticked endpoints are complete is not answerable from here.

## The install snippet names one exact version that moves every release

Installation is a two-line manifest entry, and the version in it is the current release number rather than a range:

```toml
[dependencies]
openai-api-rs = "10.0.1"
```

In Cargo that requirement means at least that version and below the next major, which is the sensible reading. The consequence is that the documentation has to be edited as part of every release, since a reader who copies it gets the floor at the time of writing rather than the newest release, and there is no note in the visible text saying the version is illustrative.

The release history shows why that matters here. The newest tag is a patch release on the tenth major line, preceded by the major release itself three weeks earlier and a patch on the ninth line four months before that. A major bump in a client library is a breaking-change signal, and anyone upgrading across it is relying on release notes rather than on anything in this repository, since the only release documentation the README points at is the platform's own API reference.

The last commit to the branch and the newest tag fall on the same day within seconds of each other, so the published crate and the branch tip agree today.

## Conclusion

Use it if you need one endpoint pointed at a non-default host, because overriding the base URL and swapping the key are both one line, and if a websocket transport for the realtime API is what you are after. Do not adopt it on the strength of the checklist, since every box is ticked regardless of whether an example or a test exists, and five of the ticked endpoints have neither. Before you commit, check three things: that the TLS backend you need is available for both transports rather than one, since the features cannot be mixed; whether the proxy support compiled into the HTTP client matters in your build; and what your own test story is, because the crate ships none of its own and the twenty-one example programs are the only executable code in the tree.

## FAQ

### What is openai-api-rs?

An unofficial Rust client library for the OpenAI API, at version 10.0.1, with its documentation hosted on docs.rs. It is a single crate whose only transports are one HTTP client and one WebSocket client, and it describes itself as unofficial in both the README title and the package manifest description.

### Which OpenAI endpoints does openai-api-rs claim to support?

Fourteen, all ticked: completions, chat, edits, images, embeddings, audio, files, fine-tuning, moderations, function calling, assistants, batch, realtime and responses. The examples directory covers a subset, with no example file for edits, images, files, fine-tuning or moderations.

### Can openai-api-rs talk to OpenRouter?

Yes, and it is treated as a first-class target rather than an afterthought: three example files and a data directory are dedicated to it, covering a chat request, listing available models and a reasoning-style request. The client is pointed at a different host through a builder method that takes the endpoint URL.

### How is the TLS backend configured in openai-api-rs?

Through a Cargo feature, and the choice covers both transports at once. The default feature selects the native backend for the HTTP client and the WebSocket client together, and an alternative feature selects the Rustls backend for both, so the two cannot be mixed.

### Does openai-api-rs ship tests?

No. There is no test directory in the repository and no development dependencies are declared. The runnable code consists of twenty-one example programs, two of which are directories, which makes the examples the only executable surface the crate provides.

## Sources

- [dongri/openai-api-rs on GitHub](https://github.com/dongri/openai-api-rs)
- [License: MIT](https://github.com/dongri/openai-api-rs/blob/main/LICENSE)
- [Project website](https://docs.rs/openai-api-rs)
- [README](https://github.com/dongri/openai-api-rs/blob/main/README.md)
- [Releases](https://github.com/dongri/openai-api-rs/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/dongri-openai-api-rs
