A Rust workspace for the Massive.com REST API: a reusable
massive-sdk library and a companion massive-cli
binary (CLI + TUI). Covers stocks, options, futures, crypto, forex, indices, economy,
alternative data, and third-party partners (Benzinga, ETF Global, TMX).
| Crate | Description | Docs |
|---|---|---|
massive-sdk |
The async REST API library | cargo doc --workspace --open |
massive-cli |
CLI + interactive TUI binary | — |
use massive_sdk::MassiveClient;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let client = MassiveClient::new(std::env::var("MASSIVE_API_KEY")?);
// Get a stock's aggregate bars for a date range
let bars = client
.stocks()
.aggregates("AAPL", 1, "day", "2025-01-01", "2025-12-31")
.await?;
for bar in bars.results.unwrap_or_default() {
println!("close={:?} volume={:?}", bar.close, bar.volume);
}
// Convert currency
let conv = client.forex().convert("EUR", "USD", Some(100.0), None).await?;
println!("100 EUR = {} USD", conv.converted);
// Get the most recent quote
let quote = client.stocks().last_quote("AAPL").await?;
if let Some(q) = quote.results {
println!("AAPL bid={:?} ask={:?}", q.bid_price, q.ask_price);
}
Ok(())
}By default, every asset class is enabled. To slim the build, disable the ones you don't use:
[dependencies]
massive-sdk = { version = "0.1", default-features = false, features = ["stocks", "crypto"] }Available features (all default-on):
| Feature | What it includes |
|---|---|
stocks |
client.stocks() — 37 endpoints |
options |
client.options() — 16 endpoints |
futures |
client.futures() — 9 endpoints |
crypto |
client.crypto() — 18 endpoints |
forex |
client.forex() — 16 endpoints |
indices |
client.indices() — 14 endpoints |
economy |
client.economic_indicators() — 4 endpoints |
full |
enables every asset feature above at once |
retry |
opt-in retry layer for HTTP 429 / 5xx (off by default) |
The alternative (Fable consumer spending) and partners (Benzinga, ETF Global, TMX) modules are always compiled in.
The companion binary massive-cli wraps the SDK with a CLI and an interactive TUI:
cargo install --git https://github.com/marcusjihansson/massive-rsTicker overview, aggregate bars, daily summaries, corporate actions (dividends, splits, IPOs, ticker events), ticker types, related tickers, fundamentals (balance sheets, cash flow, income statements, ratios, float, short interest, short volume), SEC filings (8-K, 10-K, Form 3, Form 4, 13-F, risk factors, risk categories), news, market operations (exchanges, market holidays, market status, condition codes), full market and ticker snapshots, top movers, unified snapshots, technical indicators (SMA, EMA, RSI, MACD), and tick-level trades & quotes.
Same patterns as stocks: ticker lookup, all-tickers list, aggregates, daily summaries, market operations, snapshots, technical indicators, and tick-level trades & quotes (or quotes-only for forex/indices). Crypto ticker format is X:BTCUSD; forex is C:EURUSD; indices is I:SPX.
Plus options-specific: all_contracts() (paged list of all options contracts), contract_snapshot(), chain() (option chain for an underlying).
Plus futures-specific: products(), contracts(), schedules(product_code), contract_snapshot().
Inflation (CPI, PCE, core), inflation expectations, labor market (unemployment, labor force participation, hourly earnings, job openings), treasury yields.
Fable Data European consumer spending: merchant_aggregates() and merchant_hierarchy().
Three sub-clients:
.benzinga()— analyst details, firm details, analyst insights, ratings, bulls/bears, consensus ratings, corporate guidance, earnings, news.etf_global()— analytics, constituents, fund flows, profiles, taxonomies.tmx()— corporate events
- Async / tokio — all I/O is
async fn; the crate is built onreqwestandtokio. - Errors — single
MassiveErrorenum with variants for HTTP, JSON, unauthorized, rate-limited, and a catch-allApiError { status, body }. Use?to propagate. - Pagination — paged list endpoints return
Vec<T>directly via aPager<P>internal helper that followsnext_urluntil exhausted. You don't have to manage cursors. - Query strings — built with a
Querybuilder.Query::new().add_opt("limit", limit).add_opt("ticker", ticker).build(). Empty /Nonevalues are skipped automatically. - Optional fields — most JSON fields are modeled as
Option<T>. Adding new fields to the API shouldn't break your build as long as you don't pin specific fields as required. - Feature isolation — assets behind feature flags so a downstream user can include just the ones they need.
- WebSocket streaming is not yet implemented. Only the REST API is covered. The Massive real-time WebSocket surface is planned for a future release; see ROADMAP.md for the intended design.
cargo testTests use wiremock to stand up a fake Massive server. No real API key is required for the test suite.
URL paths follow the Polygon.io convention. Massive is the rebrand of Polygon, so paths are mostly stable, but a few endpoints may have changed. Verify with the official docs and file an issue if you find a mismatch.
MIT