Documentation

Robinhood CLI

robinhood-pp-cli

Install

npx -y @mvanhorn/printing-press-library install robinhood

Installs the CLI binary and the agent skill for Claude Code, Codex, Cursor, Gemini CLI, Copilot, and more. Add --cli-only or --skill-only for one half. Requires Node.

Documentation

This is a CLI + MCP for the whole of Robinhood, not just crypto. It covers the brokerage surface — multiple accounts (individual + retirement), positions, equity and options orders, option chains, portfolio performance over YTD/1-week/1-month/1-year/5-year/all-time windows, ACH transfers (deposits and withdrawals), dividends, watchlists, and recurring investments (resume/pause/edit) — across api.robinhood.com and the bonfire gateway, captured live and risk-labeled. True full-account coverage: identify, navigate, and modify across every account. Brokerage auth uses an OAuth bearer (ROBINHOOD_BROKERAGE_TOKEN); reads run live while all write commands are read-only by default, staying in dry-run "test mode" behind the ROBINHOOD_PP_ALLOW_WRITES=1 gate plus --live-write.

The official Robinhood Crypto Trading API below is the easy documented subset (it has its own public spec and key/signature auth), included alongside the brokerage map.

Welcome to Robinhood Crypto Trading API documentation for traders and developers! The Crypto API lets you view crypto market data, access your account information, and place crypto orders programmatically.

To get started, head to your crypto account settings on web classic to create credentials. There are two versions of the Crypto Trading API, giving you the option to place crypto orders with fee tiers (v2) or without fee tiers (v1). All read-only API actions are available on both versions. For more information about API version differences, fee tiers, and answers to common questions, visit our Help Center. You can also view the Fee Schedule for the latest rates.

The Robinhood Crypto Trading API is available to customers in the United States only. Use of the Robinhood Crypto Trading API is subject to the Robinhood Crypto Customer Agreement as well as all other terms and disclosures made available on Robinhood Crypto's about page.

To get started with the Robinhood Crypto Trading API, you need to create a key, signature, and headers. Authenticated requests must include all three x-api-key, x-signature, and x-timestamp HTTP headers.

Creating an API key

Head to your crypto account settings on web classic to create credentials. After creating credentials, you will receive the API key associated with the credential. You can modify, disable, and delete credentials you created at any time.

Your API key will be used as the x-api-key header you will need to pass during authentication when calling our API endpoints. Additionally, you will need the public key generated in the Creating a key pair section to create your API credentials.

Creating a key pair

Below are example scripts on how to generate the public and private key pair. You'll need the public key for creating an API credential and the private key for authenticating requests. Remember to never share your private key with anyone. Robinhood will never ask you to share it with us.

We highly recommend saving your private and public keys in an encrypted format to ensure the highest level of security. Encrypting your keys will protect them from unauthorized access or theft. Avoid saving them in plain text or any easily accessible location. Instead, consider using strong encryption algorithms or tools specifically designed for key storage. Remember to choose a strong passphrase for encryption and store it separately from your keys. By taking these precautions, you can significantly reduce the risk of compromising your keys and safeguard your sensitive information.

Python

Note that you'll need to have pynacl installed to run the Python script. You can install them with the following pip command in your terminal.

pip install pynacl
import nacl.signing
import base64

# Generate an Ed25519 keypair
private_key = nacl.signing.SigningKey.generate()
public_key = private_key.verify_key

# Convert keys to base64 strings
private_key_base64 = base64.b64encode(private_key.encode()).decode()
public_key_base64 = base64.b64encode(public_key.encode()).decode()

# Print the keys in base64 format
print("Private Key (Base64):")
print(private_key_base64)

print("Public Key (Base64):")
print(public_key_base64)

Headers and Signature

Developing your own application to place trades with your Robinhood account is quick and simple. Once you've finished authentication, start here with the code you'll need to access the API and make supported API calls. These are essentially the building blocks of code for each API call, which you can easily build on based on your preferred strategies.

  1. Create a script file
mkdir robinhood-api-trading && cd robinhood-api-trading
touch robinhood_api_trading.py
touch robinhood_api_trading_v2.py
  1. Install PyNaCl library
pip install pynacl
  1. To use v1 endpoints, copy the script below into the newly created robinhood_api_trading.py file. Make sure to add your API key and secret key into the API_KEY and BASE64_PRIVATE_KEY variables.
import base64
import datetime
import json
from typing import Any, Dict, Optional
import uuid
import requests
from nacl.signing import SigningKey

API_KEY = "ADD YOUR API KEY HERE"
BASE64_PRIVATE_KEY = "ADD YOUR PRIVATE KEY HERE"

class CryptoAPITrading:
    def __init__(self):
        self.api_key = API_KEY
        private_key_seed = base64.b64decode(BASE64_PRIVATE_KEY)
        self.private_key = SigningKey(private_key_seed)
        self.base_url = "https://trading.robinhood.com"

    @staticmethod
    def _get_current_timestamp() -> int:
        return int(datetime.datetime.now(tz=datetime.timezone.utc).timestamp())

    @staticmethod
    def get_query_params(key: str, *args: Optional[str]) -> str:
        if not args:
            return ""

        params = []
        for arg in args:
            params.append(f"{key}={arg}")

        return "?" + "&".join(params)

    def make_api_request(self, method: str, path: str, body: str = "") -> Any:
        timestamp = self._get_current_timestamp()
        headers = self.get_authorization_header(method, path, body, timestamp)
        url = self.base_url + path

        try:
            response = {}
            if method == "GET":
                response = requests.get(url, headers=headers, timeout=10)
            elif method == "POST":
                response = requests.post(url, headers=headers, json=json.loads(body), timeout=10)
            return response.json()
        except requests.RequestException as e:
            print(f"Error making API request: {e}")
            return None

    def get_authorization_header(
            self, method: str, path: str, body: str, timestamp: int
    ) -> Dict[str, str]:
        message_to_sign = f"{self.api_key}{timestamp}{path}{method}{body}"
        signed = self.private_key.sign(message_to_sign.encode("utf-8"))

        return {
            "x-api-key": self.api_key,
            "x-signature": base64.b64encode(signed.signature).decode("utf-8"),
            "x-timestamp": str(timestamp),
        }

    def get_account(self) -> Any:
        path = "/api/v1/crypto/trading/accounts/"
        return self.make_api_request("GET", path)

    # The symbols argument must be formatted in trading pairs, e.g "BTC-USD", "ETH-USD". If no symbols are provided,
    # all supported symbols will be returned
    def get_trading_pairs(self, *symbols: Optional[str]) -> Any:
        query_params = self.get_query_params("symbol", *symbols)
        path = f"/api/v1/crypto/trading/trading_pairs/{query_params}"
        return self.make_api_request("GET", path)

    # The asset_codes argument must be formatted as the short form name for a crypto, e.g "BTC", "ETH". If no asset
    # codes are provided, all crypto holdings will be returned
    def get_holdings(self, *asset_codes: Optional[str]) -> Any:
        query_params = self.get_query_params("asset_code", *asset_codes)
        path = f"/api/v1/crypto/trading/holdings/{query_params}"
        return self.make_api_request("GET", path)

    # The symbols argument must be formatted in trading pairs, e.g "BTC-USD", "ETH-USD". If no symbols are provided,
    # the best bid and ask for all supported symbols will be returned
    def get_best_bid_ask(self, *symbols: Optional[str]) -> Any:
        query_params = self.get_query_params("symbol", *symbols)
        path = f"/api/v1/crypto/marketdata/best_bid_ask/{query_params}"
        return self.make_api_request("GET", path)

    # The symbol argument must be formatted in a trading pair, e.g "BTC-USD", "ETH-USD"
    # The side argument must be "bid", "ask", or "both".
    # Multiple quantities can be specified in the quantity argument, e.g. "0.1,1,1.999".
    def get_estimated_price(self, symbol: str, side: str, quantity: str) -> Any:
        path = f"/api/v1/crypto/marketdata/estimated_price/?symbol={symbol}&side={side}&quantity={quantity}"
        return self.make_api_request("GET", path)

    def place_order(
            self,
            client_order_id: str,
            side: str,
            order_type: str,
            symbol: str,
            order_config: Dict[str, str],
    ) -> Any:
        body = {
            "client_order_id": client_order_id,
            "side": side,
            "type": order_type,
            "symbol": symbol,
            f"{order_type}_order_config": order_config,
        }
        path = "/api/v1/crypto/trading/orders/"
        return self.make_api_request("POST", path, json.dumps(body))

    def cancel_order(self, order_id: str) -> Any:
        path = f"/api/v1/crypto/trading/orders/{order_id}/cancel/"
        return self.make_api_request("POST", path)

    def get_order(self, order_id: str) -> Any:
        path = f"/api/v1/crypto/trading/orders/{order_id}/"
        return self.make_api_request("GET", path)

    def get_orders(self) -> Any:
        path = "/api/v1/crypto/trading/orders/"
        return self.make_api_request("GET", path)

def main():
    api_trading_client = CryptoAPITrading()
    print(api_trading_client.get_account())

    """
    BUILD YOUR TRADING STRATEGY HERE

    order = api_trading_client.place_order(
          str(uuid.uuid4()),
          "buy",
          "market",
          "BTC-USD",
          {"asset_quantity": "0.0001"}
    )
    """

if __name__ == "__main__":
    main()
  1. To use v2 endpoints, copy the script below into the newly created robinhood_api_trading_v2.py file. Make sure to add your API key and secret key into the API_KEY and BASE64_PRIVATE_KEY variables.
import base64
import datetime
import json
from typing import Any, Dict, Optional
import uuid
import requests
from nacl.signing import SigningKey

API_KEY = "ADD YOUR API KEY HERE"
BASE64_PRIVATE_KEY = "ADD YOUR PRIVATE KEY HERE"

class CryptoAPITradingV2:
    def __init__(self):
        self.api_key = API_KEY
        private_key_seed = base64.b64decode(BASE64_PRIVATE_KEY)
        self.private_key = SigningKey(private_key_seed)
        self.base_url = "https://trading.robinhood.com"

    @staticmethod
    def _get_current_timestamp() -> int:
        return int(datetime.datetime.now(tz=datetime.timezone.utc).timestamp())

    @staticmethod
    def get_query_params(params_dict: Dict[str, Any]) -> str:
        """
        Build query parameter string from a dictionary.
        - Single values: {"key1": "value1", "key2": "value2"}
        - Multiple values for same key: {"symbol": ["BTC-USD", "ETH-USD"]}
        """
        if not params_dict:
            return ""
        
        params = []
        for key, value in params_dict.items():
            if value is None:
                continue
            if isinstance(value, list):
                # Handle multiple values for the same key
                for v in value:
                    params.append(f"{key}={v}")
            else:
                params.append(f"{key}={value}")
        
        return "?" + "&".join(params) if params else ""

    def make_api_request(self, method: str, path: str, body: str = "") -> Any:
        timestamp = self._get_current_timestamp()
        headers = self.get_authorization_header(method, path, body, timestamp)
        url = self.base_url + path

        try:
            response = {}
            if method == "GET":
                response = requests.get(url, headers=headers, timeout=10)
            elif method == "POST":
                response = requests.post(url, headers=headers, json=json.loads(body) if body else None, timeout=10)

            # Check for non-success status codes
            if response.status_code >= 400:
                print(f"HTTP Error {response.status_code}: {response.reason}")
                try:
                    return response.json()
                except json.JSONDecodeError:
                    return {"error": response.text or response.reason, "status_code": response.status_code}

            return response.json()
        except requests.RequestException as e:
            print(f"Error making API request: {e}")
            return None

    def get_authorization_header(
            self, method: str, path: str, body: str, timestamp: int
    ) -> Dict[str, str]:
        message_to_sign = f"{self.api_key}{timestamp}{path}{method}{body}"
        signed = self.private_key.sign(message_to_sign.encode("utf-8"))

        return {
            "x-api-key": self.api_key,
            "x-signature": base64.b64encode(signed.signature).decode("utf-8"),
            "x-timestamp": str(timestamp),
        }

    def get_accounts(self) -> Any:
        path = "/api/v2/crypto/trading/accounts/"
        return self.make_api_request("GET", path)

    # The symbols argument must be formatted in trading pairs, e.g "BTC-USD", "ETH-USD". If no symbols are provided,
    # all supported symbols will be returned
    def get_trading_pairs(self, *symbols: Optional[str]) -> list:
        params = {"symbol": list(symbols)} if symbols else {}
        query_params = self.get_query_params(params)
        path = f"/api/v2/crypto/trading/trading_pairs/{query_params}"
        
        all_results = []
        response = self.make_api_request("GET", path)
        
        while response:
            results = response.get("results", [])
            all_results.extend(results)
            
            next_url = response.get("next")
            if not next_url:
                break
            
            next_path = next_url.replace(self.base_url, "")
            response = self.make_api_request("GET", next_path)
        
        return all_results

    # The asset_codes argument must be formatted as the short form name for a crypto, e.g "BTC", "ETH". If no asset
    # codes are provided, all crypto holdings will be returned
    def get_holdings(self, account_number: str, *asset_codes: Optional[str]) -> Any:
        params = {"account_number": account_number}
        if asset_codes:
            params["asset_code"] = list(asset_codes)
        query_params = self.get_query_params(params)
        path = f"/api/v2/crypto/trading/holdings/{query_params}"
        return self.make_api_request("GET", path)

    # The symbols argument must be formatted in trading pairs, e.g "BTC-USD", "ETH-USD".
    def get_best_bid_ask(self, *symbols: str) -> Any:
        params = {"symbol": list(symbols)} if symbols else {}
        query_params = self.get_query_params(params)
        path = f"/api/v2/crypto/marketdata/best_bid_ask/{query_params}"
        return self.make_api_request("GET", path)

    # The symbol argument must be formatted in a trading pair, e.g "BTC-USD", "ETH-USD"
    # The side argument must be "bid", "ask", or "both".
    # Multiple quantities can be specified in the quantity argument, e.g. "0.1,1,1.999".
    def get_estimated_price(self, symbol: str, side: str, quantity: str) -> Any:
        params = {"symbol": symbol, "side": side, "quantity": quantity}
        query_params = self.get_query_params(params)
        path = f"/api/v2/crypto/trading/estimated_price/{query_params}"
        return self.make_api_request("GET", path)

    def place_order(
            self,
            account_number: str,
            client_order_id: str,
            side: str,
            order_type: str,
            symbol: str,
            order_config: Dict[str, str],
    ) -> Any:
        body = {
            "client_order_id": client_order_id,
            "side": side,
            "type": order_type,
            "symbol": symbol,
            f"{order_type}_order_config": order_config,
        }
        params = {"account_number": account_number}
        query_params = self.get_query_params(params)
        path = f"/api/v2/crypto/trading/orders/{query_params}"
        return self.make_api_request("POST", path, json.dumps(body))

    def cancel_order(self, order_id: str) -> Any:
        path = f"/api/v2/crypto/trading/orders/{order_id}/cancel/"
        return self.make_api_request("POST", path)

    def get_order(self, account_number: str, order_id: str) -> Any:
        params = {"account_number": account_number}
        query_params = self.get_query_params(params)
        path = f"/api/v2/crypto/trading/orders/{order_id}/{query_params}"
        return self.make_api_request("GET", path)

    def get_orders(self, account_number: str) -> Any:
        params = {
            "account_number": account_number,
            "created_at_start": "2023-01-01T20:57:50Z"
        }
        query_params = self.get_query_params(params)
        path = f"/api/v2/crypto/trading/orders/{query_params}"
        return self.make_api_request("GET", path)

def main():
    api_trading_client = CryptoAPITradingV2()
    print(api_trading_client.get_trading_pairs())
    # print(api_trading_client.get_trading_pairs("BTC-USD", "ETH-USD"))
    # print(api_trading_client.get_best_bid_ask("BTC-USD")) #"BTC-USD", "ETH-USD"
    # print(api_trading_client.get_estimated_price(symbol="BTC-USD", side="both", quantity="0.01"))

    # accounts = api_trading_client.get_accounts()
    # print(accounts)
    # account_number = accounts["results"][0]["account_number"]
    # print(f"account_number: {account_number}")
    # print(api_trading_client.get_orders(account_number))
    # print(api_trading_client.get_holdings(account_number))
    # print(api_trading_client.get_holdings(account_number, "BTC", "ETH"))

    """
    BUILD YOUR TRADING STRATEGY HERE

    order = api_trading_client.place_order(
          account_number,
          str(uuid.uuid4()),
          "buy",
          "market",
          "BTC-USD",
          {"asset_quantity": "0.000001"}
    )
    """

if __name__ == "__main__":
    main()
  1. Run your script from the command line
# to run the Python script using the v1 API endpoints:
python robinhood_api_trading.py
# to run the Python script using the v2 API endpoints:
python robinhood_api_trading_v2.py

Endpoints that return a list of results allow you to paginate to have more control over how many and which results to display.

Pagination Parameters

ParameterDescription
cursorThe cursor is a unique identifier for each page in a list of results. The cursor is used to paginate through the pages of results.
limitThe limit is the number of items to return in a single page. Some of our endpoints support this query parameter. You can view support by checking the query parameters in the documentation of each endpoint.

Pagination Response

FieldDescription
nextThe API request endpoint that includes the next cursor query parameter to use for pagination.
previousThe API request endpoint that includes the previous cursor query parameter to use for pagination.
resultsThe list of response items for the current cursor.

Rate Limits

  • Requests per minute per user account: 100
  • Requests per minute per user account in bursts: 300

Rate limiting is applied using a token bucket implementation. The burst size or capacity is the number of tokens you can use to call an endpoint. This capacity is initialized at the maximum capacity and will be refilled using a refill amount at a timed interval called refill interval until the max capacity is once again reached.

Rate Limiting Terms

TermDescription
Max capacityThe maximum amount of tokens allowed. Will no longer continue refilling if this amount is reached.
Remaining amountThe number of tokens remaining that can be consumed to call an endpoint.
Refill amountThe number of tokens that are refilled at each refill interval.
Refill intervalThe timed interval at which the tokens are refilled.

The actual values of the configuration will fluctuate depending on the availability of our service and our current expected volume at the time of service. Rate limits are applied per endpoint and may differ among each endpoint depending on their expected use case.

Example rate limiting configuration:

TermValue
Max capacity5
Remaining amount2
Refill amount1
Refill interval1 second
ActionTime (in seconds)Remaining amountDescription
Initialize05Initial state of the token bucket.
Endpoint call 10.54One token consumed for calling endpoint 1.
Endpoint call 20.73One token consumed for calling endpoint 2.
Refill14One token refilled at refill interval.
Refill25One token refilled at refill interval.
No refill35No refill since max capacity has been reached and no endpoints were called.
Endpoint call 33.54One token consumed for calling endpoint 3.

Error response format

Type

The type field in the error response will be mapped to the following:

Error typeStatus codes
validation_error400
client_error4XX, excluding 400
server_error5XX

Errors

The errors field will contain a list of error details, each item will contain a nested attr and detail field.

FieldDescription
attrError types of validation_error will specify the field name or non_field_errors if the error cannot be attributed to a field. Will be null for error types of either client_error and server_error.
detailWill contain a human readable string describing the error.

Example Error Response

Here's a sample error response where the client_order_id field in the payload was a value that was not expected when calling the Add Crypto Order endpoint. The detail field for each error in the errors list will help understand why the validation_error was thrown. The attr field will indicate which field name in the request body or query parameter the error was thrown for if applicable.

{
  "type": "validation_error"
  "errors": [
    {
      "detail": "Must be a valid UUID.",
      "attr": "client_order_id"
    }
 ]
}

Common Error Status Codes

Status CodeError
400Bad request
401Unauthorized
403Forbidden
404Not found
405Method not allowed
406Not acceptable
415Unsupported media type
429Too many requests
500Internal server error
503Service unavailable

Created by @zaydiscold (zaydiscold).

Quick Start

1. Install

See Install above.

2. Set Up Credentials

Create Robinhood Crypto API credentials from Robinhood's crypto account settings. The CLI needs both the API key and the base64 Ed25519 private key used to sign requests.

export ROBINHOOD_API_KEY="<paste-your-key>"
export ROBINHOOD_PRIVATE_KEY_B64="<paste-your-private-key-base64>"

You can also persist this in your config file at ~/.config/robinhood-pp-cli/config.toml.

3. Verify Setup

robinhood-pp-cli doctor

This checks your configuration and credentials.

4. Try Your First Command

robinhood-pp-cli crypto marketdata-best-bid-ask

Brokerage/account route map

The package also bundles the 2026-05-27 authenticated Robinhood browser map from ticker, options, crypto, account, settings, transfer, document, and market pages:

robinhood-pp-cli brokerage summary --json
robinhood-pp-cli brokerage browser-routes --host bonfire.robinhood.com --json
robinhood-pp-cli brokerage execute https://api.robinhood.com/goku/lcm --json

Read inspection has no write gate. Any route that can write defaults to --dry-run; live execution requires --live-write plus ROBINHOOD_PP_ALLOW_WRITES=1. Brokerage/account execution uses caller-owned ROBINHOOD_BROKERAGE_TOKEN or ROBINHOOD_COOKIE.

Typed brokerage commands

Alongside the route map, the brokerage group ships typed read commands for the everyday brokerage surface — accounts, positions, orders, options, performance, transfers, dividends, and history. They authenticate with the OAuth bearer credential (ROBINHOOD_BROKERAGE_TOKEN, or ROBINHOOD_COOKIE + ROBINHOOD_CSRF_TOKEN) shared with brokerage execute. This is a separate credential from the crypto API's ROBINHOOD_API_KEY / ROBINHOOD_PRIVATE_KEY_B64.

robinhood-pp-cli brokerage accounts --json                       # all accounts (individual + retirement)
robinhood-pp-cli brokerage portfolios --json                     # per-account dollar balances
robinhood-pp-cli brokerage positions --nonzero --json            # open equity positions
robinhood-pp-cli brokerage options chain --chain-id <uuid> --json
robinhood-pp-cli brokerage performance --account-id 1AB23456 --span year --json
robinhood-pp-cli brokerage transfers --json                      # ACH deposits + withdrawals
robinhood-pp-cli brokerage dividends --json

Order placement/cancellation (brokerage orders place/cancel, brokerage options place/cancel) and watchlist add/remove default to --dry-run and never auto-execute; a live mutation requires --live-write plus ROBINHOOD_PP_ALLOW_WRITES=1.

Usage

Run robinhood-pp-cli --help for the full command reference and flag list.

Commands

crypto

Access Robinhood Crypto trading, holdings, orders, pairs, and market data

  • robinhood-pp-cli crypto marketdata-best-bid-ask - Fetch a single bid and ask price per symbol, representing the best available price across our partner market makers. This price does not take into account the order size, and may not be the final execution price.

The bid and ask prices include a spread. The buy spread is the percent difference between the ask and the mid price. The sell spread is the percent difference between the bid and the mid price.

Note that in the v2 endpoint, Place crypto orders with fee tiers, partner exchanges provide prices instead of market makers, with orders routed accordingly. For more information on routing, visit our Help Center.

  • robinhood-pp-cli crypto marketdata-best-bid-ask-marketdata - Fetch a single bid and ask price per symbol, representing the best available price across our partner exchanges. This price does not take into account the order size or fee, and may not be the final execution price.
  • robinhood-pp-cli crypto marketdata-estimated-price - This endpoint returns the estimated total cost or credit for a particular symbol, book side, and asset quantity. You can include a list of quantities in a single request to retrieve the price for various hypothetical order sizes.

The estimated price represents the expected execution price if you were to subsequently place an order. To estimate the cost for a Buy order, request an Ask quote. If you are preparing to place a Sell order, request a Bid quote. The execution price may vary due to market volatility and once executed the transaction may not be undone.

The bid and ask prices are the best prices our market makers provide for an order, inclusive of a spread. The buy spread is the percent difference between the ask and the mid price. The sell spread is the percent difference between the bid and the mid price.

  • robinhood-pp-cli crypto marketdata-estimated-price-trading - This endpoint returns the estimated total cost or credit for a particular symbol, book side, asset quantity, and fee. You can include a list of quantities in a single request to retrieve the price for various hypothetical order sizes.

The estimated price represents the expected execution price if you were to subsequently place an order. The execution price may vary due to market volatility and once executed the transaction may not be undone.

The bid and ask prices are the best prices our partner exchanges provide for an order, excluding the fee.

  • robinhood-pp-cli crypto post-trading-cancel-order - Cancels an open crypto trading order.
  • robinhood-pp-cli crypto post-trading-order - Places a new crypto trading order with an order type.

Note: Depending on the type used in the request body, you must include the respective order configuration in the request body.

For order configurations that support both asset_quantity or quote_amount, only one can be present in the request body.

  • robinhood-pp-cli crypto trading-account-details - Fetches the Robinhood Crypto account details for the current user.
  • robinhood-pp-cli crypto trading-accounts - Retrieve a paginated list of crypto trading accounts for the authenticated user. Returns account details including buying power, status, and fee tier information.
  • robinhood-pp-cli crypto trading-cancel-order - Cancels an open crypto trading order.
  • robinhood-pp-cli crypto trading-holdings - Fetch a list of holdings for the current user.
  • robinhood-pp-cli crypto trading-holdings-trading - Retrieve a paginated list of crypto holdings for a specific account. Returns the total quantity and available quantity for each asset held in the account. The account_number query parameter is required.
  • robinhood-pp-cli crypto trading-orders - Fetch a list of orders for the current user.
  • robinhood-pp-cli crypto trading-orders-get - Fetch a list of orders for the current user in a specific account.
  • robinhood-pp-cli crypto trading-orders-post - Place a new crypto trading order with an order type. This endpoint only supports placing orders on USD symbols that have is_api_tradable=true as defined in our Get Crypto Trading Pairs endpoint.

Note: Depending on the type used in the request body, you must include the respective order configuration in the request body.

For order configurations that support both asset_quantity or quote_amount, only one can be present in the request body.

  • robinhood-pp-cli crypto trading-trading-pairs - Fetch a list of trading pairs.
  • robinhood-pp-cli crypto trading-trading-pairs-trading - Fetch a paginated list of available trading pairs for crypto trading. Returns trading pair details including price increments, order size limits, and tradability status. Trading pairs can be filtered by symbol.

brokerage

Inspect Robinhood brokerage/account route maps and the typed brokerage surface. Read commands authenticate with ROBINHOOD_BROKERAGE_TOKEN (OAuth bearer); write commands default to --dry-run.

  • robinhood-pp-cli brokerage summary - Summarize bundled brokerage/account route maps.
  • robinhood-pp-cli brokerage plan - Build a dry-run request plan for a mapped route.
  • robinhood-pp-cli brokerage execute - Execute a mapped brokerage/account request with PP write gates.
  • robinhood-pp-cli brokerage accounts - List all brokerage accounts (individual + retirement). Maps GET /accounts/.
  • robinhood-pp-cli brokerage ceres-accounts - List accounts via the ceres gateway. Maps GET /ceres/v1/accounts.
  • robinhood-pp-cli brokerage account - Unified balance view for one account. Maps GET /accounts/{id}/unified/ (bonfire).
  • robinhood-pp-cli brokerage account-switcher - Accounts in the app account-switcher shape. Maps GET /home/account_switcher/v2 (bonfire).
  • robinhood-pp-cli brokerage positions - List equity positions. Maps GET /positions/.
  • robinhood-pp-cli brokerage portfolios - Per-account equity/market value/withdrawable. Maps GET /portfolios/.
  • robinhood-pp-cli brokerage instrument - Look up an instrument by symbol. Maps GET /instruments/.
  • robinhood-pp-cli brokerage quote - Real-time quotes for symbols. Maps GET /marketdata/quotes/.
  • robinhood-pp-cli brokerage orders - List equity orders. Maps GET /orders/.
  • robinhood-pp-cli brokerage orders place - Place an equity order (dry-run by default). Maps POST /orders/.
  • robinhood-pp-cli brokerage orders cancel - Cancel an equity order (dry-run by default). Maps POST /orders/{id}/cancel/.
  • robinhood-pp-cli brokerage options positions - Aggregate options positions. Maps GET /options/aggregate_positions/.
  • robinhood-pp-cli brokerage options orders - Options orders. Maps GET /options/orders/.
  • robinhood-pp-cli brokerage options chain - Option chains, or one by id. Maps GET /options/chains/ and /options/chains/{id}/.
  • robinhood-pp-cli brokerage options instruments - Option contracts for a chain. Maps GET /options/instruments/.
  • robinhood-pp-cli brokerage options marketdata - Options greeks/IV/bid-ask. Maps GET /marketdata/options/.
  • robinhood-pp-cli brokerage options place - Place an options order (dry-run by default). Maps POST /options/orders/.
  • robinhood-pp-cli brokerage options cancel - Cancel an options order (dry-run by default). Maps POST /options/orders/{id}/cancel/.
  • robinhood-pp-cli brokerage performance - Portfolio value over a window (YTD, week, month, year, 5year, all). Maps GET /portfolios/historicals/{id}/.
  • robinhood-pp-cli brokerage transfers - ACH transfers (deposits + withdrawals). Maps GET /ach/transfers/.
  • robinhood-pp-cli brokerage transfers relationships - Linked bank relationships. Maps GET /ach/relationships/.
  • robinhood-pp-cli brokerage transfers unified - Unified transfers across rails. Maps GET /paymenthub/unified_transfers/ (bonfire).
  • robinhood-pp-cli brokerage dividends - Dividends (paid + pending). Maps GET /dividends/.
  • robinhood-pp-cli brokerage history - Account transaction history. Maps GET /history/transactions/ (minerva).
  • robinhood-pp-cli brokerage watchlist - Default watchlist; items/add/remove subcommands. Maps GET /discovery/lists/default/.

Output Formats

# Human-readable table (default in terminal, JSON when piped)
robinhood-pp-cli crypto marketdata-best-bid-ask

# JSON for scripting and agents
robinhood-pp-cli crypto marketdata-best-bid-ask --json

# Filter to specific fields
robinhood-pp-cli crypto marketdata-best-bid-ask --json --select id,name,status

# Dry run — show the request without sending
robinhood-pp-cli crypto marketdata-best-bid-ask --dry-run

# Agent mode — JSON + compact + no prompts in one flag
robinhood-pp-cli crypto marketdata-best-bid-ask --agent

Agent Usage

This CLI is designed for AI agent consumption:

  • Non-interactive - never prompts, every input is a flag
  • Pipeable - --json output to stdout, errors to stderr
  • Filterable - --select id,name returns only fields you need
  • Previewable - --dry-run shows the request without sending
  • Explicit retries - add --idempotent to create retries when a no-op success is acceptable
  • Confirmable - --yes for explicit confirmation of destructive actions
  • Piped input - write commands can accept structured input when their help lists --stdin
  • Offline-friendly - sync/search commands can use the local SQLite store when available
  • Agent-safe by default - no colors or formatting unless --human-friendly is set

Exit codes: 0 success, 2 usage error, 3 not found, 4 auth error, 5 API error, 7 rate limited, 10 config error.

Health Check

robinhood-pp-cli doctor

Verifies configuration, credentials, and connectivity to the API.

Configuration

Config file: ~/.config/robinhood-pp-cli/config.toml

Static request headers can be configured under headers; per-command header overrides take precedence.

Environment variables:

NameKindRequiredDescription
ROBINHOOD_API_KEYper_callYesRobinhood Crypto API key.
ROBINHOOD_PRIVATE_KEY_B64per_callYesBase64 Ed25519 private signing key from Robinhood Crypto credentials.

Troubleshooting

Authentication errors (exit code 4)

  • Run robinhood-pp-cli doctor to check credentials
  • Verify the environment variable is set: echo $ROBINHOOD_API_KEY
  • Verify the signing key environment variable is set: test -n "$ROBINHOOD_PRIVATE_KEY_B64" && echo set Not found errors (exit code 3)
  • Check the resource ID is correct
  • Run the list command to see available items

Generated by CLI Printing Press

For agents: pass /documentation/robinhood/agents.md to install this CLI from a prompt.