Getting Started
ThetaDataDx connects directly to ThetaData's servers — nothing to install and babysit locally. Pick a language, install, save your credentials, and make a request.
1. Install
# Cargo.toml
[dependencies]
thetadatadx-rs = "0.2.0"The market-data client is async; call it from your application's async runtime.
2. Authenticate
Pass your API key directly to the client and you are one line from a live connection. Generate a key from your ThetaData user portal, hand it to the client, and you have a connected client ready to make requests.
// API key inline, production by default.
let client = thetadatadx::Client::builder()
.api_key("your_api_key")
.connect()
.await?;The same one-step construction takes the key from the environment or a .env file, takes an email and password instead, and selects the staging cluster. Email and password is also supported; it is shown alongside the api-key forms below.
// Source the key from THETADATA_API_KEY, or from a .env file.
let client = thetadatadx::Client::builder().api_key_from_env().connect().await?;
let client = thetadatadx::Client::builder().api_key_from_dotenv(".env").connect().await?;
// Email and password inline, staging environment.
let client = thetadatadx::Client::builder()
.email_password("you@example.com", "your-password")
.stage()
.connect()
.await?;Credential sources
The client resolves any of the credential sources below. They are the building blocks behind the one-step construction above: an API key supplied inline, from the environment, or from a .env file; or an email and password supplied from a file, inline, or at a custom path. Each one also produces a standalone Credentials value you can hold and pass to the lower-level connect when you want full control over hosts and tuning (see "Full control" at the end of this section).
API key
Generate an API key from your ThetaData user portal, then supply it one of three ways.
1. Pass it directly. Hand the key straight to the api-key constructor.
let creds = thetadatadx::Credentials::api_key("your_api_key");2. Environment variable. Set THETADATA_API_KEY and let the SDK read it. from_env_or_file reads the variable when it is set and falls back to a creds.txt file otherwise, so the same code works in both setups.
export THETADATA_API_KEY="your_api_key"let creds = thetadatadx::Credentials::from_env_or_file("creds.txt")?;3. .env file. Keep the key in a .env file (one KEY=VALUE per line) and point the SDK at it.
THETADATA_API_KEY="your_api_key"let creds = thetadatadx::Credentials::from_dotenv(".env")?;Email and password
Supply your account email and password one of three ways.
1. Credentials file. Create a creds.txt in your working directory: your ThetaData account email on line 1, password on line 2.
you@example.com
your-passwordlet creds = thetadatadx::Credentials::from_file("creds.txt")?;2. Pass them directly. Hand the email and password straight to the constructor.
let creds = thetadatadx::Credentials::new("you@example.com", "your-password");3. Custom file path. Point from_file at any path, not just creds.txt in the working directory.
let creds = thetadatadx::Credentials::from_file("/path/to/creds.txt")?;No subscription yet? Create an account at thetadata.net — several endpoints work on the free tier (look for the Free badge on reference pages).
Full control
The one-step construction at the top of this section is a convenience over the typed path: build a Credentials and a Config yourself and pass both to the lower-level connect. Reach for this when you need to override hosts, timeouts, or other tuning knobs on the Config.
let creds = thetadatadx::Credentials::from_file("creds.txt")?;
let client = thetadatadx::Client::connect(&creds, thetadatadx::DirectConfig::production()).await?;3. First request
use thetadatadx::Client;
async fn run() -> Result<(), thetadatadx::Error> {
// Pass your API key directly. Add .stage() before .connect() for staging.
let client = Client::builder().api_key("your_api_key").connect().await?;
let rows = client.market_data().stock_history_eod("AAPL", "20250303", "20250306").await?;
for t in &rows {
println!("{}: open={} close={} volume={}", t.date, t.open, t.close, t.volume);
}
Ok(())
}Every endpoint follows this shape. Browse the API Reference — each page carries the signature and a runnable sample in all five surfaces.
Good to knows
- Dates are
YYYYMMDDstrings in the SDKs ("20250303"); the HTTP server also accepts ISOYYYY-MM-DD. Timestamps come back as milliseconds since midnight Eastern Time — see Symbology & Contract Identity. - Connect once, reuse the client. One client multiplexes any number of market-data requests and an optional streaming session; per-request connections waste the authentication round trip.
- Markets closed? Connect with
Config.dev()/DirectConfig::dev()to stream a replayed market-data session, and prefer market-data endpoints over snapshots on weekends. - Targeting staging or dev? The market-data and streaming environments are selected independently. Pick the market-data staging cluster with
DirectConfig::production().with_market_data_environment(MarketDataEnvironment::Stage)(or theConfig.stage()/DirectConfig::stage()preset), theTHETADATA_MARKET_DATA_TYPE=STAGEenvironment variable, or a.envfile. Pick the streaming dev-replay cluster withwith_streaming_environment(StreamingEnvironment::Dev)(or thedev()preset) orTHETADATA_STREAMING_TYPE=DEV. The market-data environment also sets the authentication marker; the streaming environment does not. All paths work with either credential type, and one.envfile can holdTHETADATA_API_KEY,THETADATA_MARKET_DATA_TYPE, andTHETADATA_STREAMING_TYPEtogether. See Configuration.