Async-first Robinhood API client library with typed Pydantic models, encrypted token caching, and full CLI
Project description
LIL JON
WHAT?! An Async Robinhood API Client Library?! YEAH!!
LilJon is a custom async-first Robinhood API client library that replaced the third-party robin_stocks package. OOOK! It's built from the ground up with httpx, Pydantic models, and Fernet-encrypted token caching. Every call is async. Every response is typed. Every token is ENCRYPTED. YEAH!!
WHAT'S IN THE BOX?!
src/liljon/
├── client.py # The main RobinhoodClient - THIS IS WHERE THE PARTY STARTS!!
├── cli.py # Full CLI tool for testing - COMMAND LINE CRUNK!!
├── __main__.py # Run it as a module, baby!
├── _http.py # httpx transport with auth headers - OOOK!
├── _endpoints.py # Pure URL templates, zero side effects - CLEAN!!
├── _pagination.py # Handles paginated API responses - WHAT?!
├── exceptions.py # Custom exception hierarchy - YEAH!!
├── auth/ # OAuth + MFA + token cache
│ ├── _flow.py # Two-step auth flow (login → 2FA → done!)
│ ├── _token_cache.py # Fernet-encrypted storage - SECURE!! OOOK!
│ ├── _device_token.py # Device token generation
│ └── models.py # TokenData, ChallengeInfo, LoginResult
├── api/ # API namespace modules
│ ├── stocks.py # Quotes, fundamentals, multi-symbol historicals, news, batch lookups
│ ├── options.py # Chains, instruments, market data, positions, strategies, P&L
│ ├── crypto.py # Pairs, quotes, holdings, orders
│ ├── futures.py # Contracts, quotes, accounts, orders, products, closes
│ ├── indexes.py # Index quotes, fundamentals, closes
│ ├── account.py # Positions, portfolio, watchlists, dividends, subscriptions, performance
│ ├── orders.py # Place, cancel, list stock orders, combo orders, fee calculator
│ ├── markets.py # Market hours, movers, categories
│ ├── screeners.py # Stock screeners and scans
│ ├── discovery.py # Analyst ratings, hedge funds, insiders, short interest, earnings, ETPs, news feeds
│ └── alerts.py # Price and indicator alerts (GET/POST/PATCH)
└── models/ # Pydantic response models for EVERYTHING
├── stocks.py # StockQuote, Fundamentals, HistoricalBar, NewsArticle, etc.
├── options.py # OptionChain, OptionInstrument, OptionMarketData, etc.
├── crypto.py # CryptoPair, CryptoQuote, CryptoHolding, etc.
├── futures.py # FuturesContract, FuturesQuote, FuturesOrder, etc.
├── indexes.py # IndexQuote, IndexFundamentals, etc.
├── account.py # Position, PortfolioProfile, LivePortfolio, UserProfile, etc.
├── orders.py # OrderResult
├── screeners.py # Screener, ScanResult, Indicator, etc.
├── discovery.py # AnalystRating, HedgeFundSummary, InsiderSummary, ShortInterest, etc.
├── alerts.py # AlertSettings, AlertSetting
└── common.py # PaginatedResponse, TimestampMixin
KEY FEATURES - TURN DOWN FOR WHAT?!
- Async HTTP — httpx-based transport with connection pooling. FAST!! OOOK!
- Pydantic Models — Every single API response is typed. No guessing. WHAT?! YEAH!!
- Fernet-Encrypted Token Cache — Your tokens are stored at
~/.tokens/liljon_tokens.enc, encrypted with a machine-derived key. AIN'T NOBODY STEALING YOUR TOKENS!! - Two-Step MFA — Supports SMS and email verification flows. SECURE!! OOOK!
- 13 Namespace APIs — Clean
client.stocks,client.options,client.crypto,client.discovery,client.alertsand more. ORGANIZED!! - Pagination — Automatic URL-based and cursor-based pagination. GETS ALL THE DATA!! YEAH!!
- Full CLI — Interactive testing tool with Rich tables and panels. PRETTY!! WHAT?!
- Exception Hierarchy — All errors inherit from
RobinhoodErrorfor easy catching. OOOK! - Discovery Engine — Analyst ratings, hedge fund activity, insider trading, short interest, earnings, similar instruments, and news feeds. DEEP RESEARCH!!
- Price Alerts — Create and manage price and indicator alerts via API. NEVER MISS A MOVE!! YEAH!!
- Multi-Symbol Batching — Fetch historicals for multiple symbols in a single request. EFFICIENT!! OOOK!
INSTALLATION - LET'S GET IT!! OOOK!
pip install liljon
Requires Python 3.12+. Dependencies: httpx, pydantic, cryptography, click, rich.
USING THE LIBRARY - LET'S GOOO!!
Basic Usage
from liljon import RobinhoodClient
# YEAH!! Create a client and get some quotes!
async with RobinhoodClient() as client:
await client.try_restore_session()
quotes = await client.stocks.get_quotes(["AAPL", "MSFT", "NVDA"])
for q in quotes:
print(f"{q.symbol}: ${q.last_trade_price}") # OOOK!
Authentication - WHAT?! YOU GOTTA LOG IN FIRST!!
from liljon import RobinhoodClient
async with RobinhoodClient() as client:
# Try cached session first - SKRRT SKRRT!
if await client.try_restore_session():
print("Already logged in! YEAH!!")
else:
# Phase 1: Send credentials
result = await client.login("your@email.com", "password")
# Phase 2: Handle 2FA if needed - WHAT?!
if result.status == "challenge_required":
code = input("Enter your verification code: ")
result = await client.submit_verification(code)
if result.status == "logged_in":
print(f"OOOK! Logged in as {result.username}!")
Stocks - GET THAT BREAD!!
# Get quotes - WHAT ARE THESE PRICES?!
quotes = await client.stocks.get_quotes(["AAPL", "TSLA"])
# Get quotes by instrument IDs
quotes = await client.stocks.get_quotes_by_ids(["id1", "id2"])
# Get latest prices - QUICK LOOK!! YEAH!!
prices = await client.stocks.get_latest_price(["AAPL", "TSLA"])
# Get fundamentals - DO YOUR DD!! OOOK!
fundamentals = await client.stocks.get_fundamentals("NVDA")
# Get fundamentals by instrument ID (session-aware)
fundamentals = await client.stocks.get_fundamentals_by_id(instrument_id, bounds="24_5")
# Get fundamentals history over time
history = await client.stocks.get_fundamentals_history(["id1", "id2"], start_date="2025-01-01")
# Get historicals - batches multiple symbols in one call! YEAH!!
bars = await client.stocks.get_historicals(["AAPL", "MSFT"], interval="day", span="month", bounds="regular")
# Returns dict keyed by symbol: {"AAPL": [...], "MSFT": [...]}
# Get batch historicals by instrument IDs
batch = await client.stocks.get_historicals_by_ids(["id1", "id2"], interval="5minute", span="day")
# Get news - WHAT'S HAPPENING?!
news = await client.stocks.get_news("TSLA")
# Get market-wide news (no symbol) - ALL THE NEWS!! OOOK!
news = await client.stocks.get_news()
# Resolve a symbol to its instrument
instrument = await client.stocks.get_instrument_by_symbol("AAPL")
# Get instrument by ID or URL
instrument = await client.stocks.get_instrument_by_id(instrument_id)
Options - OOOK! ADVANCED MOVES!!
# Get option chains
chains = await client.options.get_chains(instrument_id)
# Get specific instruments
instruments = await client.options.get_instruments(
chain_id=chains[0].id,
expiration_dates=["2026-03-20"],
option_type="call"
)
# Get market data for an option - WHAT'S IT WORTH?!
data = await client.options.get_market_data(instrument.id)
# Batch market data for multiple options - YEAH!!
batch = await client.options.get_market_data_batch(["opt_id1", "opt_id2"])
# Get aggregated positions grouped by strategy
positions = await client.options.get_aggregate_positions()
# Get option strategies
strategies = await client.options.get_strategies(["strategy_code"])
# Get strategy-level quotes with greeks
quotes = await client.options.get_strategy_quotes(ids=["opt_id1", "opt_id2"])
# Get chain collateral requirements - HOW MUCH MARGIN?! OOOK!
collateral = await client.options.get_chain_collateral(chain_id)
# Get option events (expirations, assignments, exercises)
events = await client.options.get_events()
# Get P&L chart data
pnl = await client.options.get_pnl_chart(legs="...", order_price="1.50", quantity="1")
# Get breakeven calculations
breakevens = await client.options.get_breakevens(strategy_code, average_cost="150.00")
Crypto - DIGITAL MONEY!! YEAH!!
# List crypto pairs - WHAT COINS WE GOT?!
pairs = await client.crypto.get_pairs()
# Get a quote
quote = await client.crypto.get_quote(pair_id)
# Get holdings - SHOW ME THE CRYPTO!! OOOK!
holdings = await client.crypto.get_holdings()
Account - WHERE'S MY MONEY AT?! WHAT?!
# Get positions - WHAT AM I HOLDING?!
positions = await client.account.get_positions()
# Get portfolio - THE BIG PICTURE!! YEAH!!
account_id = client.get_account_number()
portfolio = await client.account.get_portfolio(account_id)
# Get live portfolio with real-time values - LIVE DATA!! OOOK!
live = await client.account.get_live_portfolio(account_number)
# Get portfolio performance chart data
perf = await client.account.get_portfolio_performance(account_number, display_span="month")
# Get Phoenix unified account snapshot
phoenix = await client.account.get_phoenix_account()
# Get user profile
user = await client.account.get_user()
# Get active subscriptions (Gold, etc.)
subs = await client.account.get_subscriptions()
# Get watchlists with items - WHAT AM I WATCHING?! OOOK!
watchlists = await client.account.get_watchlists()
# Add/remove symbols from watchlists
await client.account.add_symbols_to_watchlist(["AAPL", "MSFT"], name="Main")
await client.account.remove_symbols_from_watchlist(["TSLA"], name="Main")
# Get dividends
dividends = await client.account.get_dividends()
# Get cash sweep interest rates
interest = await client.account.get_sweep_interest(account_number)
# Get historical activities (trades, dividends, transfers)
activities = await client.account.get_historical_activities()
# Get stock lending income
payments = await client.account.get_stock_loan_payments()
# Get buying power for a specific instrument
bp = await client.account.get_instrument_buying_power(account_number, instrument_id)
Orders - EXECUTE!! EXECUTE!!
# Place a stock order - LET'S GOOO!!
order = await client.orders.place_stock_order(
symbol="AAPL",
quantity=1,
side="buy",
order_type="market",
time_in_force="gfd",
)
# Convenience wrappers - QUICK AND EASY!! YEAH!!
await client.orders.buy_market("AAPL", 1)
await client.orders.buy_limit("AAPL", 1, price=150.00)
await client.orders.sell_market("AAPL", 1)
await client.orders.sell_stop_loss("AAPL", 1, stop_price=140.00)
# Cancel an order - NEVERMIND!! WHAT?!
await client.orders.cancel_stock_order(order_id)
# Get combo/multi-leg orders - COMPLEX TRADES!! OOOK!
combos = await client.orders.get_combo_orders(states="pending")
# Calculate fees before placing an order
fees = await client.orders.calculate_fees(
instrument_id=inst_id, quantity="10", price="150.00", side="buy"
)
Futures - OOOK! BIG BOY MOVES!!
# Get contracts by product ID
contracts = await client.futures.get_contracts(product_ids=["ES"])
# Get quote for a contract
quote = await client.futures.get_quote(contract_id)
# Batch quotes
quotes = await client.futures.get_quotes(["id1", "id2"])
# Get futures account
account = await client.futures.get_account()
# Get futures orders
orders = await client.futures.get_orders()
# Calculate realized P&L - AM I WINNING?! YEAH!!
pnl = await client.futures.calculate_pnl()
# Get product metadata (contract specs)
product = await client.futures.get_product(product_id)
# Get previous closes
closes = await client.futures.get_closes(["id1", "id2"])
# Get historical close range
closes = await client.futures.get_closes_range(contract_id, start="2025-01-01T00:00:00Z")
# Get futures user settings
settings = await client.futures.get_user_settings()
# Get P&L cost basis
pnl = await client.futures.get_pnl_cost_basis(account_id)
# Get aggregated positions
positions = await client.futures.get_aggregated_positions(account_id)
Indexes - TRACK THE MARKET!! YEAH!!
# Get index quotes (S&P 500, NASDAQ, etc.)
quotes = await client.indexes.get_values(ids="SPX,NDX")
# Get index fundamentals - THE FUNDAMENTALS!! WHAT?!
fundies = await client.indexes.get_fundamentals(ids="SPX")
Screeners - FIND THE GEMS!! OOOK!
# List available screeners
screeners = await client.screeners.get_screeners()
# Get presets - PRE-BUILT FILTERS!! YEAH!!
presets = await client.screeners.get_presets()
# Run a scan - SCAN THE MARKET!! WHAT?!
results = await client.screeners.scan(screener_id, filters=my_filters)
Discovery - DEEP RESEARCH!! WHAT?! YEAH!!
# Analyst ratings (buy/hold/sell, price targets)
ratings = await client.discovery.get_ratings(instrument_id)
ratings_batch = await client.discovery.get_ratings_batch(["id1", "id2"])
# Hedge fund activity - WHAT ARE THE BIG BOYS DOING?! OOOK!
summary = await client.discovery.get_hedgefund_summary(instrument_id)
transactions = await client.discovery.get_hedgefund_transactions(instrument_id)
# Insider trading - WHO'S BUYING THEIR OWN STOCK?! YEAH!!
insiders = await client.discovery.get_insider_summary(instrument_id)
insider_txns = await client.discovery.get_insider_transactions(instrument_id)
# Short interest - WHO'S BETTING AGAINST IT?! WHAT?!
short = await client.discovery.get_short_interest(instrument_id)
# Equity summary — daily net buy/sell flow
equity = await client.discovery.get_equity_summary(instrument_id)
# Earnings data
earnings = await client.discovery.get_earnings(instrument_id)
# Similar instruments - FIND MORE LIKE THIS!! OOOK!
similar = await client.discovery.get_similar(instrument_id)
# Market indices (S&P 500, Nasdaq, Dow, VIX, Russell)
indices = await client.discovery.get_market_indices(symbols=["SPX", "NDX", "DJX"])
# ETP (ETF/ETN) details — AUM, expense ratio, holdings
etp = await client.discovery.get_etp_details(instrument_id)
# NBBO (National Best Bid/Offer) summary
nbbo = await client.discovery.get_nbbo_summary(instrument_id)
# Chart time bounds
bounds = await client.discovery.get_chart_bounds()
# Unified search across stocks, crypto, futures - FIND ANYTHING!! YEAH!!
results = await client.discovery.search("AAPL")
# General market news feed from dora.robinhood.com - WHAT'S THE BUZZ?! OOOK!
feed = await client.discovery.get_feed()
# Instrument-specific news feed - WHAT'S THE WORD ON THIS ONE?! YEAH!!
feed = await client.discovery.get_instrument_feed(instrument_id)
Alerts - NEVER MISS A MOVE!! OOOK!
# Get all alerts for an instrument
alerts = await client.alerts.get_alerts(instrument_id)
# Create a price alert - TELL ME WHEN IT HITS!! YEAH!!
await client.alerts.create_alert(instrument_id, [
{"enabled": True, "price": "200.00", "setting_type": "price_above"}
])
# Update an alert - CHANGE THE TARGET!! WHAT?!
await client.alerts.update_alert(instrument_id, [
{"id": alert_id, "setting_type": "price_above", "enabled": False}
])
THE CLI - COMMAND LINE CRUNK!! OOOK!
Run the CLI with:
uv run python -m liljon [OPTIONS] COMMAND [ARGS]
Or if installed via pip:
liljon [OPTIONS] COMMAND [ARGS]
Global Options
| Option | Description |
|---|---|
--json |
Output raw JSON instead of Rich tables. YEAH!! |
Auth Commands - OOOK! GOTTA GET IN FIRST!!
# Check auth status - AM I IN?! WHAT?!
liljon auth status
# Interactive login (prompts for credentials + 2FA)
liljon auth login
# Logout and clear cached tokens - PEACE OUT!!
liljon auth logout
Stocks Commands - GET THAT MARKET DATA!!
# Get quotes for one or more symbols - WHAT'S THE PRICE?!
liljon stocks quote AAPL MSFT NVDA
# Quick latest price
liljon stocks price AAPL TSLA
# Get quotes by instrument IDs
liljon stocks quote-by-ids <id1> <id2>
# Get fundamentals - DO YOUR HOMEWORK!! OOOK!
liljon stocks fundamentals AAPL
# Get fundamentals by instrument ID
liljon stocks fundamentals-by-id <instrument_id>
# Get 52-week fundamentals history
liljon stocks fundamentals-history <instrument_id1> <instrument_id2> --start-date 2025-01-01
# Get historical bars (supports multiple symbols) - YEAH!!
liljon stocks historicals AAPL MSFT --interval day --span month --bounds regular --last 30
# Get instrument metadata
liljon stocks instrument AAPL
# Get news for a ticker
liljon stocks news TSLA --limit 20
# Get market-wide news (no symbol) - ALL THE NEWS!! OOOK!
liljon stocks news
Account Commands - SHOW ME THE MONEY!! WHAT?!
# View account info (buying power, cash, etc.)
liljon account info
# View portfolio - THE WHOLE THING!! YEAH!!
liljon account portfolio
# View positions
liljon account positions
# View dividends - PASSIVE INCOME!! OOOK!
liljon account dividends
# View all watchlists with symbols
liljon account watchlists
# Create a watchlist
liljon account watchlist-create "My List"
# Add symbols to a watchlist
liljon account watchlist-add AAPL MSFT --name "My First List"
# Remove symbols from a watchlist
liljon account watchlist-remove TSLA --name "My First List"
# View user profile
liljon account user
# View active subscriptions (Gold, etc.)
liljon account subscriptions
# View live portfolio with real-time values
liljon account live
# View portfolio performance chart data
liljon account performance --span month
# View cash sweep interest rates
liljon account sweep-interest
# View historical activities (trades, dividends, transfers)
liljon account activities
# View buying power for a specific instrument
liljon account buying-power <instrument_id>
Orders Commands - MAKE MOVES!! WHAT?!
# List recent orders
liljon orders list
# Get specific order - WHAT HAPPENED?!
liljon orders get <order_id>
# Place a market buy - LET'S GOOO!!
liljon orders buy AAPL 1 --type market --confirm
# Place a limit buy
liljon orders buy AAPL 1 --type limit --price 150.00 --confirm
# Place a stop-loss sell
liljon orders sell AAPL 1 --type stoploss --stop-price 140.00 --confirm
# Place a market sell - TAKE PROFITS!! YEAH!!
liljon orders sell AAPL 1 --type market --confirm
# Cancel an order - OOOK! CHANGED MY MIND!!
liljon orders cancel <order_id> --confirm
# View combo/multi-leg orders
liljon orders combo --states pending
# Calculate fees before placing an order
liljon orders fees <instrument_id> 10 150.00 buy
Options Commands - YEAH!! DERIVATIVES!!
# Get option chains for a symbol
liljon options chains AAPL
# Search option instruments
liljon options instruments <chain_id> --expiration 2026-03-20 --type call
# Get market data for an option (greeks, IV, prices)
liljon options market-data <option_id>
# Batch market data for multiple options
liljon options market-data-batch <option_id1> <option_id2>
# View option positions - WHAT AM I HOLDING?!
liljon options positions
# View aggregated positions by strategy
liljon options aggregate
# View option orders - WHAT DID I DO?! OOOK!
liljon options orders
# View option events (expirations, assignments, exercises)
liljon options events --chain-id <chain_id>
# Get option strategies
liljon options strategies <strategy_code1> <strategy_code2>
# Get strategy-level quotes
liljon options strategy-quotes <opt_id1> <opt_id2> --ratios 1,1 --types long,short
# Get P&L chart data
liljon options pnl-chart --legs "..." --order-price 1.50 --quantity 1
# Get breakeven calculations
liljon options breakevens <strategy_code> <average_cost>
Crypto Commands - DIGITAL ASSETS!! WHAT?!
# List available crypto pairs
liljon crypto pairs
# Get a crypto quote (by symbol, e.g. BTC)
liljon crypto quote BTC
# View crypto holdings - HOW MUCH CRYPTO?! YEAH!!
liljon crypto holdings
# Get crypto historicals
liljon crypto historicals BTC --interval hour --span week --last 48
Futures Commands - OOOK! THE FUTURE IS NOW!!
# List futures contracts by product ID
liljon futures contracts ES NQ
# Get a futures quote
liljon futures quote <contract_id>
# View futures account
liljon futures account
# View futures orders
liljon futures orders
# View futures P&L - AM I WINNING?! WHAT?!
liljon futures pnl
# Get product metadata (contract specs)
liljon futures product <product_id>
# Get previous close prices
liljon futures closes <contract_id1> <contract_id2>
# Get historical close range
liljon futures closes-range <contract_id> <start_datetime>
# View futures user settings
liljon futures settings
# Get P&L cost basis
liljon futures pnl-cost-basis <account_id> --contract-id <contract_id>
# Get aggregated positions
liljon futures aggregated-positions <account_id>
Indexes Commands - MARKET BENCHMARKS!! YEAH!!
# Get index quote
liljon indexes quote SPX
# Get index instrument info
liljon indexes instrument SPX
# Get index fundamentals - THE NUMBERS!! OOOK!
liljon indexes fundamentals SPX NDX
# Get previous closes
liljon indexes closes SPX
# Get index option chains
liljon indexes chains SPX
Markets Commands - WHAT TIME IS IT?!
# List all markets
liljon markets list
# Get market hours for a date - WHEN'S IT OPEN?! YEAH!!
liljon markets hours XNYS 2026-02-27
# Get S&P 500 movers - WHO'S MOVING?! OOOK!
liljon markets movers --direction up
# List discovery categories
liljon markets categories
# Get instruments in a category
liljon markets category <tag>
Screeners Commands - FIND THE WINNERS!! WHAT?!
# List all screeners
liljon screeners list
# Get preset screeners - EASY MODE!! YEAH!!
liljon screeners presets
# Get a specific screener
liljon screeners get <screener_id>
# List available indicators
liljon screeners indicators
# Run a screener scan - SCAN IT!! OOOK!
liljon screeners scan <screener_id>
# Run a custom query with filters
liljon screeners query -i pe_ratio=pe_ratio_more_than_5
liljon screeners query -i market_cap=mkt_cap_large_cap,mkt_cap_mega_cap --sort market_cap
liljon screeners query -i sector=Technology -i 1d_price_change=daily_price_is_up
Discovery Commands - DEEP RESEARCH!! YEAH!!
# Analyst ratings for an instrument
liljon discovery ratings <instrument_id>
# Batch analyst ratings
liljon discovery ratings-batch <id1> <id2>
# Hedge fund activity summary
liljon discovery hedgefunds <instrument_id>
# Detailed hedge fund transactions - WHO'S BUYING?! OOOK!
liljon discovery hedgefund-transactions <instrument_id>
# Insider trading summary
liljon discovery insiders <instrument_id>
# Detailed insider transactions
liljon discovery insider-transactions <instrument_id>
# Short interest data - WHAT?!
liljon discovery short-interest <instrument_id>
# Equity summary (daily buy/sell flow)
liljon discovery equity-summary <instrument_id>
# Earnings data
liljon discovery earnings <instrument_id>
# Similar instruments - FIND MORE!! YEAH!!
liljon discovery similar <instrument_id>
# Unified search across stocks, crypto, futures
liljon discovery search "apple"
# Market index summaries (S&P 500, Nasdaq, Dow, VIX, Russell)
liljon discovery market-indices --symbols SPX,NDX,DJX,VIX,RUT
# ETP (ETF/ETN) details — AUM, expense ratio, holdings
liljon discovery etp-details <instrument_id>
# NBBO summary - OOOK!
liljon discovery nbbo <instrument_id>
# Chart time bounds
liljon discovery chart-bounds
# General market news feed - WHAT'S THE BUZZ?! OOOK!
liljon discovery feed --limit 10
# News feed for a specific instrument - WHAT'S THE WORD?! YEAH!!
liljon discovery instrument-feed <instrument_id> --limit 10
Alerts Commands - SET IT AND FORGET IT!! OOOK!
# List all alerts for an instrument (accepts symbol or instrument ID)
liljon alerts list AAPL
# Create a price alert - TELL ME WHEN!! YEAH!!
liljon alerts create AAPL price_above --price 200.00
# Create an indicator alert
liljon alerts create AAPL rsi_above --interval 5m
# Update an alert (enable/disable, change price) - WHAT?!
liljon alerts update AAPL <alert_id> --disabled
liljon alerts update AAPL <alert_id> --price 250.00
EXCEPTION HIERARCHY - WHEN THINGS GO WRONG!! WHAT?!
All exceptions inherit from RobinhoodError so you can catch the whole family. OOOK!
RobinhoodError # Base exception - THE BOSS!!
├── AuthenticationError # Login/2FA/token refresh failed
│ ├── NotAuthenticatedError # No valid session (HTTP 401) - LOG IN!! WHAT?!
│ └── ChallengeRequiredError # Additional verification needed
├── APIError # Non-2xx HTTP response - OOOK!
│ └── RateLimitError # HTTP 429 - SLOW DOWN!! YEAH!!
├── InvalidSymbolError # Bad ticker symbol
├── OrderError # Order placement/cancellation failed
└── ValidationError # Client-side validation failure
Example Error Handling
from liljon import RobinhoodClient, RobinhoodError, NotAuthenticatedError, RateLimitError
async with RobinhoodClient() as client:
try:
quotes = await client.stocks.get_quotes(["AAPL"])
except NotAuthenticatedError:
print("You ain't logged in! WHAT?!")
except RateLimitError as e:
print(f"Slow down! Retry after {e.retry_after}s. OOOK!")
except RobinhoodError as e:
print(f"Something went wrong: {e}. YEAH... that's not good.")
TOKEN CACHE - KEEP YOUR SECRETS SAFE!! OOOK!
Tokens are stored encrypted at ~/.tokens/liljon_tokens.enc using Fernet symmetric encryption. WHAT?! YEAH, THAT'S RIGHT — ENCRYPTED!!
- Default key derivation: SHA-256 hash of
{hostname}:{username}:{platform}— machine-specific. OOOK! - Custom passphrase: Pass
passphrase="your_secret"toRobinhoodClient()for extra security. YEAH!! - Atomic writes: Uses write-then-rename to prevent corruption. SAFE!!
- Auto-refresh: Tokens near expiry are automatically refreshed on session restore. SMART!! WHAT?!
# Custom cache location - PUT IT WHERE YOU WANT!! OOOK!
client = RobinhoodClient(cache_path="/custom/path/tokens.enc")
# Custom passphrase - EXTRA SECURITY!! YEAH!!
client = RobinhoodClient(passphrase="TURN_DOWN_FOR_WHAT")
RUNNING TESTS - MAKE SURE IT WORKS!! YEAH!!
# Run all LilJon tests - TEST EVERYTHING!! OOOK!
uv run pytest tests/test_liljon/ -v
# Run a specific test file
uv run pytest tests/test_liljon/test_client.py -v
# Run with coverage - HOW MUCH WE COVERING?! WHAT?!
uv run pytest tests/test_liljon/ --cov=src/liljon -v
LilJon — TURN DOWN FOR WHAT?! Your async Robinhood API client that GETS. IT. DONE. OOOK!! YEAH!! WHAT?!
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file liljon-0.7.0.tar.gz.
File metadata
- Download URL: liljon-0.7.0.tar.gz
- Upload date:
- Size: 1.7 MB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
779299c6c7c95656d8682ae4b862faea4efe0efe9d57d64ab2461b8232c579eb
|
|
| MD5 |
9f877879fce5f7c496aaa0383834f464
|
|
| BLAKE2b-256 |
d7c2f72823423c51d016f22b6b7e355e6fa201aee333dc5a5a6ea602b5b579ea
|
File details
Details for the file liljon-0.7.0-py3-none-any.whl.
File metadata
- Download URL: liljon-0.7.0-py3-none-any.whl
- Upload date:
- Size: 84.0 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
61ffec033c35b82f706b6a51c7df6a523983eaaafabeb0fcd0f78b70fb62d266
|
|
| MD5 |
06e277b6005da8a9f91fa591117cae1b
|
|
| BLAKE2b-256 |
3998b042a8b104269158c43e0fdf39389bee2c985eaea03e9ecdeb381431671a
|