tone3000
Async Rust client for the TONE3000 API (v1): browse and search
the community tone library, download .nam and IR files, and authenticate users with
OAuth 2.0 + PKCE.
Pairs with nam-rs, which runs the models this
crate downloads.
$ cargo add tone3000
$ cargo add tokio -F macros,rt-multi-thread # the snippets below are async
Read this first
Every endpoint requires an end-user OAuth login. There is no anonymous access.
Searching the public library needs a user access token exactly as much as reading that
user's favourites does. The publishable key (t3k_pub_…) is the OAuth client_id, not a
credential — a call without an access token fails with Error::Unauthenticated before it
reaches the network.
If your product can't put a user through a browser login, this API isn't usable.
Concepts
| Type | What it is |
|---|---|
Tone |
A capture project: one piece of gear, captured once, published with a title and licence. Not downloadable itself. |
Model |
One downloadable file belonging to a tone, at a given size and architecture. Six models is six variants of one capture, not six amps. |
Make |
The real-world gear captured, e.g. "Mesa Boogie Badlander". |
Size |
The CPU/quality trade-off (standard, lite, feather, nano, custom), not a byte count. |
A tone has many models; a model has a model_url you download. nam-rs parses those bytes
into a NamModel and loads it into a nam_rs::Model you can run audio through — so "model"
means something different in each crate. Fully qualify it in code using both.
Quick start
use ;
async
client.tones() is browse and search both — add .query("plexi") and it becomes a search.
Filters are optional and chain:
use ;
async
Authentication
Get a publishable key from TONE3000 Settings → API Keys and register your redirect URI there; localhost is allowed in development. This crate handles the token exchange, and your app owns the redirect, because a desktop loopback, a plugin host and a web callback are different problems.
use ;
async
Prompt::SelectTone, Prompt::LoadTone { tone_id } and Prompt::LoadModel { model_id }
hand the browsing to TONE3000's own UI instead, which saves building one.
examples/oauth_desktop.rs does this end to end with a real
loopback listener, in std only.
Refresh tokens rotate. Each refresh invalidates the previous one, so store every token you are handed or the session dies:
use Client;
Downloading
use ;
async
download_url and download_url_to take a model_url directly, for when you stored one
rather than a whole Model.
client.models(id) returns one architecture at a time — the API defaults to v1 and has no
"all" option. Client::models documents the loop that collects them all.
With nam-rs
cargo add nam-rs, then:
use ;
async
Examples
| Example | Shows | Needs |
|---|---|---|
oauth_desktop |
The PKCE flow with a loopback listener. Start here — it produces the token the others need | T3K_PUB_KEY |
search_and_download |
Browse, search, tone detail, models, download | both |
play_with_nam_rs |
Download a capture and run audio through it | both |
$ export T3K_PUB_KEY=t3k_pub_...
$ cargo run --example oauth_desktop # prints an access token
$ export T3K_ACCESS_TOKEN=...
$ cargo run --example search_and_download
Errors and limits
Error separates what you would branch on: Unauthenticated (no token set), Unauthorized
(401), Forbidden (403), RateLimited { retry_after }, Status { code, body }, and Http
for transport failures. Error::is_timeout() and Error::is_connect() answer the usual
retry questions without matching the variant out.
The API allows 100 requests per minute by default, and search is limited more tightly.
Honour retry_after.
Coverage
Implemented: tone search and browse, tone detail, created, favorited, model list and detail, model download, the user profile, the public user directory, and the OAuth token flows.
Not yet implemented, tracked as issues: /tones/trending and /tones/latest
(#9), /tones/downloaded
(#10), /makes and /tags
(#11), and the API's deprecation
headers (#12). GET /tones/download
is restricted to approved partners, so it is deliberately absent — download individual
models via model_url.
Compatibility
- MSRV 1.86, set by
url→idna_adapter→icu_*. An MSRV bump is a minor bump. - Async only, on
tokio. TLS viarustls, no OpenSSL.
Your integration must also follow TONE3000's
Design Requirements and Commercial Terms, and you should
check tone.license before redistributing a model.
Development
| Command | What it does | Credentials |
|---|---|---|
cargo test |
Unit + wiremock suites; live tests are #[ignore]d |
No |
make test-live |
Live contract and enum-vocabulary checks | Yes |
make test-oauth |
Interactive OAuth bootstrap; prints a refresh token | Yes, a browser |
make check-upstream |
Diffs upstream types.ts against a pinned SHA |
Needs gh |
make check-upstream also runs weekly in CI.
Licensed under MIT.