Skip to main content

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, 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
│   └── 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.alerts and 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 RobinhoodError for easy catching. OOOK!
  • Discovery Engine — Analyst ratings, hedge fund activity, insider trading, short interest, earnings, similar instruments. DEEP RESEARCH!!
  • Price Alerts — Create and manage price and indicator alerts via API. NEVER MISS A MOVE!! YEAH!!

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 a single quote
quote = await client.stocks.get_quote("AAPL")

# Get quotes by instrument IDs with session bounds
quotes = await client.stocks.get_quotes_by_ids(["id1", "id2"], bounds="24_5")

# 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 - WHERE WE BEEN?! YEAH!!
bars = await client.stocks.get_historicals("AAPL", interval="day", span="month")

# 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")

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")

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 (with session bounds)
liljon stocks quote-by-ids <id1> <id2> --bounds 24_5

# Get fundamentals - DO YOUR HOMEWORK!! OOOK!
liljon stocks fundamentals AAPL

# Get fundamentals by instrument ID (session-aware)
liljon stocks fundamentals-by-id <instrument_id> --bounds 24_5

# Get 52-week fundamentals history
liljon stocks fundamentals-history <instrument_id1> <instrument_id2> --start-date 2025-01-01

# Get historical bars - YEAH!!
liljon stocks historicals AAPL --interval day --span month --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

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" to RobinhoodClient() 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

liljon-0.6.0.tar.gz (73.9 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

liljon-0.6.0-py3-none-any.whl (70.4 kB view details)

Uploaded Python 3

File details

Details for the file liljon-0.6.0.tar.gz.

File metadata

  • Download URL: liljon-0.6.0.tar.gz
  • Upload date:
  • Size: 73.9 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.10.4 {"installer":{"name":"uv","version":"0.10.4","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for liljon-0.6.0.tar.gz
Algorithm Hash digest
SHA256 dd15ab5f48a71f3bc804db496861ad68308a730882c40e553ec5fb10318692da
MD5 a5da3b87a4be581fb2a6fadbc1d9729d
BLAKE2b-256 7e9bb47c0b2beda1ec969d5c08e71255b74ba758cbdfbedfe4fdf564acfcb3f4

See more details on using hashes here.

File details

Details for the file liljon-0.6.0-py3-none-any.whl.

File metadata

  • Download URL: liljon-0.6.0-py3-none-any.whl
  • Upload date:
  • Size: 70.4 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.10.4 {"installer":{"name":"uv","version":"0.10.4","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for liljon-0.6.0-py3-none-any.whl
Algorithm Hash digest
SHA256 35ce4527649288140e18102c57f9414ca331dc9d7ff08dddef160b24fb99a95b
MD5 545416cb7e64c22ac4cdc63678f452fc
BLAKE2b-256 198381d3cf0097e09c5bace4f1b3f880862ded97f40331634d0d9648b146bad3

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page