Skip to content

devesh-bytes1/newsdata-rust-client

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

1 Commit
 
 
 
 
 
 
 
 
 
 

Repository files navigation

newsdata-rust-client

An async Rust client for the newsdata.io news API.

Built on tokio and reqwest, it gives you strongly-typed responses, ergonomic query builders, and a reusable connection-pooled HTTP client. It is designed to run out of the box on the free newsdata.io plan.

Features

  • 🚀 Fully async (Tokio) with a pooled reqwest client under the hood
  • 🧱 Typed responses (NewsResponse, Article, Source, ...) via serde
  • 🔧 Fluent NewsQuery builder for q, country, language, category, and pagination
  • 🆓 Free-tier safe — paid-only fields are optional and paid-only errors degrade gracefully
  • 🛡️ Rich error handling for invalid keys (401), rate limits (429), and upgrade-required (403/422)
  • 🔌 Connection pooling example for high-throughput, concurrent usage

Installation

This repository is the crate. Clone it and use it as a path/git dependency, or copy it into your workspace:

[dependencies]
newsdata-client = { git = "https://github.com/your-account/newsdata-rust-client" }
tokio = { version = "1", features = ["full"] }

Requires Rust 1.75+.

Getting an API key

  1. Create a free account at https://newsdata.io.
  2. Copy your API key from the dashboard.
  3. Export it as an environment variable (the client never hardcodes it):
export NEWSDATA_API_KEY="pub_xxxxxxxxxxxxxxxxxxxxxxxx"

If NEWSDATA_API_KEY is unset, NewsDataClient::from_env() returns Error::MissingApiKey with a clear message instead of panicking.

Usage

use newsdata_client::{NewsDataClient, NewsQuery};

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let client = NewsDataClient::from_env()?;

    let query = NewsQuery::new()
        .query("technology")
        .language("en")
        .country("us");

    let page = client.latest_news(&query).await?;
    for article in &page.results {
        println!("{}", article.title);
    }

    // Pagination: pass the returned token back via `.page(...)`.
    if let Some(token) = page.next_page {
        let next = client.latest_news(&query.clone().page(token)).await?;
        println!("next page has {} articles", next.results.len());
    }

    Ok(())
}

Examples

Run any example with your key set:

NEWSDATA_API_KEY=your_key cargo run --example latest_news
NEWSDATA_API_KEY=your_key cargo run --example sources
NEWSDATA_API_KEY=your_key cargo run --example connection_pooling
  • latest_news — fetch and print the latest articles
  • sources — list available publishers for a country
  • connection_pooling — share one pooled client across many concurrent Tokio tasks

Connection pooling

reqwest::Client keeps an internal connection pool, so the fast path is to build it once and share it. NewsDataClient is cheap to clone and clones share the same pool. You can also bring your own tuned reqwest::Client:

use std::time::Duration;
use newsdata_client::NewsDataClient;

let http = reqwest::Client::builder()
    .pool_max_idle_per_host(16)
    .pool_idle_timeout(Duration::from_secs(90))
    .timeout(Duration::from_secs(30))
    .build()?;

let client = NewsDataClient::with_http_client(
    std::env::var("NEWSDATA_API_KEY")?,
    http,
);
# Ok::<(), Box<dyn std::error::Error>>(())

Error handling

All API calls return Result<_, newsdata_client::Error>:

Variant Meaning
MissingApiKey NEWSDATA_API_KEY not set
Unauthorized API key rejected (HTTP 401)
RateLimited Free-tier rate limit hit (HTTP 429) — back off and retry
PaidFeature(msg) Request needs a paid plan (HTTP 403/422 "upgrade" response)
Api { status, message } Any other API error
Http / Decode Transport or JSON decoding failure

Empty results are handled normally (you get an empty Vec, not an error).

Free tier vs. paid plan

This crate targets the free plan. The following are paid-only on newsdata.io and are intentionally treated as optional:

  • Sentiment analysisArticle::sentiment is Option and None on free.
  • AI enrichment fieldsai_tag, ai_region, ai_org are optional.
  • The /archive endpoint and long historical date ranges.
  • Advanced full-text query operators.

If you request a paid-only feature with a free key, the API responds with an "upgrade your plan" error, which this client surfaces as Error::PaidFeature so your app can skip it and keep working rather than crashing.

License

MIT

About

Async Rust crate for the newsdata.io news API, built on Tokio and reqwest with typed responses and connection pooling examples.

Topics

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages