Rust crates.io async / tokio

Rust SDK

Fully async Rust client backed by reqwest and tokio. Typed Error enum, builder pattern, zero unsafe code.

install cargo
$ cargo add tcglookup

Key Features

Fully Async

Built on reqwest + tokio. Awaitable from any async runtime.

Typed Error Enum

Match on Error::PlanAccess, Error::RateLimit, etc.

Builder Pattern

Construct search params ergonomically with the builder API.

Zero Unsafe

No unsafe blocks anywhere in the codebase.

Auto-chunk Batches

Pass any number of IDs — SDK handles the chunking for you.

Rate Limit Access

client.rate_limit() after each request.

Quickstart

src/main.rs Rust
use tcglookup::{Client, SearchParams};

#[tokio::main]
async fn main() -> Result<(), tcglookup::Error> {
    let client = Client::new(
        std::env::var("TCG_API_KEY").unwrap()
    );

    // Search for cards
    let results = client
        .cards()
        .search(SearchParams::builder()
            .q("charizard")
            .game("pokemon")
            .limit(5)
            .build())
        .await?;

    println!("{}", results.data[0].name);

    // Check rate limit
    let rl = client.rate_limit();
    println!("{} / {}", rl.remaining, rl.limit);

    Ok(())
}

API Surface

client.cards().search(params) Search & batch
// Keyword search
let results = client.cards().search(
    SearchParams::builder().q("black lotus").game("mtg").build()
).await?;

// Batch by IDs — auto-chunks beyond 20
let ids = vec!["uuid1", "uuid2"];
let results = client.cards().search(
    SearchParams::builder().ids(ids).build()
).await?;
client.cards().get(id) Single card lookup
let card = client.cards().get("019535a1-d5d0-7c12-a3e8-b7f4c6d8e9a2").await?;
println!("{:?}", card.prices.raw.near_mint);
client.cards().history(id, params) Trader+ required
let history = client.cards().history(
    &card.id,
    HistoryParams::builder().period("30d").build()
).await?;
client.sets().list() / client.games().list() Browse sets and games
let sets = client.sets().list(SetParams::builder().game("pokemon").build()).await?;
let games = client.games().list(Default::default()).await?;

Error Handling

error-handling.rs
use tcglookup::Error;

match client.cards().get("some-id").await {
    Ok(card) => println!("{}", card.name),
    Err(Error::Authentication(msg)) => {
        eprintln!("Invalid API key: {}", msg);
    }
    Err(Error::PlanAccess(required)) => {
        eprintln!("Upgrade to {} required", required);
    }
    Err(Error::RateLimit { retry_after }) => {
        eprintln!("Rate limited. Retry in {}s", retry_after);
    }
    Err(Error::NotFound) => eprintln!("Card not found"),
    Err(e) => eprintln!("Other error: {}", e),
}

Rate Limit Headers

rate-limits.rs
client.cards().search(SearchParams::builder().q("pikachu").build()).await?;

let rl = client.rate_limit();
println!("{} / {} (resets {})", rl.remaining, rl.limit, rl.reset);

Start building with Rust

Get your free API key and query card prices in minutes.