Skip to main content
The Trading primitive links a user’s brokerage account via an OAuth2 Connect flow. Each user authorizes their own brokerage account (paper and/or live); Naive performs the token exchange and proxies the brokerage’s trading API on their behalf — so you never touch OAuth plumbing, token storage, or per-user isolation. One primitive trades stocks, options, and crypto: the order symbol decides the market (AAPL, BTC/USD, AAPL241213C00250000).
Naive is not the broker, a broker-dealer, or an investment adviser, and does not exercise trading discretion — the connected brokerage is the broker. Naive is a governed gateway in front of your users’ own brokerage accounts: the user directs and approves the trades. Money-moving actions (place/cancel order, close position) are approval-gated by default — see Approvals.

CLI First

How the OAuth connection works

Naive owns a single platform OAuth app registered with the brokerage. connect returns an authorize_url; the user opens it, approves access, and the brokerage redirects back to Naive’s callback, which exchanges the code for a bearer token and stores it encrypted. The token is then used to call the brokerage’s trading API for that user.
1

Start the flow

Returns { "authorize_url": "https://<brokerage-oauth>/authorize?...", "env": "paper" }.
2

User authorizes

Open the authorize_url and approve access. The brokerage redirects to Naive’s callback (/v1/trading/oauth/callback), which stores the token.
3

Confirm and trade

Use --env paper for paper trading and --env live for a funded account. A user can connect both; when both are connected, pass --env (or env) on each call. OAuth access tokens are long-lived (there is no refresh token); if access is ever revoked, calls return unauthorized and you simply reconnect.
Disclosure. A disclosure must be shown to the user at connection time. POST /v1/trading/connect returns it as a disclosure field (and the dashboard renders it as an “Authorize naive” consent step before redirecting). Display it before sending the user to the authorize URL.

Tools

Placing orders

The same endpoint trades every asset class — the symbol selects the market. Provide either qty (shares/coins) or notional (dollar amount).
Via the API:

Order parameters

Naive sends the request’s Idempotency-Key as the order’s client_order_id, so a retried logical order deduplicates at the broker.

Asset class differences

Crypto trading must be enabled on the user’s brokerage account (the crypto agreement signed). Check trading_accountcrypto_status. Naive surfaces this but does not toggle it — it’s an account-level setting on the brokerage.
The brokerage enforces a $10 minimum per crypto order. An order below it is rejected with a forbidden error ("cost basis must be >= minimal amount of order 10") — the connection stays valid; just resize the order.

Positions & orders

Market data

Governance

trading.order.create, trading.order.cancel, and trading.position.close are in the default approval set. For a real end-user (not the account’s own default agent profile), an agent (API-key) call returns 202 { "status": "pending_approval" } and the action runs only after a human approves it in Approvals. AgentProfiles can opt in/out per Account Kit via primitives_config.trading.requiresApproval.

Connection statuses

Disconnecting (DELETE /v1/trading/connections/:env) removes the stored connection entirely; reconnecting creates a fresh one.

Configuration

The trading primitive requires the platform OAuth app credentials + an encryption key on the API:
Your brokerage OAuth app must be approved before it can execute live trades; paper works for development.