# Gambit > Gambit (gambit.trading) is an AI-native trading platform for Hyperliquid: > research and market context first — live market data, computed quant > features, the Today's Market opportunity feed, sentiment/news/equity-options > context, portfolio updates, and an agent that produces trade > recommendations. Trading happens through an explicit propose → confirm > flow (api:trade scope, agent wallet only, server-side guardrails and > hourly caps). Clients are REQUIRED to show the proposal to a human and > obtain approval before confirming — but that approval is a client-side > obligation, not something the server can verify, so treat an api:trade > key or OAuth grant as a live trading credential: it can execute trades if > misused or compromised. Keys and grants without api:trade cannot trade at > all. Perps and spot, including HIP-3 builder-DEX equities/commodities like > xyz:TSLA. Connect: add https://api.gambit.trading/mcp to any MCP client > and sign in with OAuth; headless agents use a scoped API key. ## Connect your agent (MCP / API) There are two ways in: 1. **Sign in with OAuth** — for interactive MCP clients (Claude, ChatGPT, Claude Code, Codex, Cursor, VS Code, …). Add the URL, sign in to Gambit in the browser, pick the scopes. No key to create, copy, or paste. Start here. 2. **API key** — for headless agents, scripts, cron jobs, and plain-JSON HTTPS calls where no human is around to sign in. See "Headless agents and scripts: API key" below. ### Sign in with OAuth (interactive MCP clients — start here) Add `https://api.gambit.trading/mcp` as a remote (Streamable HTTP) MCP server. The client discovers everything else: the first unauthenticated call returns 401 with `WWW-Authenticate: Bearer ... resource_metadata=...`, the client registers itself, and it opens the Gambit consent page (https://gambit.trading/oauth/authorize) in the browser. The human signs in and chooses which scopes to grant (`api:read` is always included; `api:trade` is only granted if they tick it). - Claude Code: claude mcp add --transport http gambit https://api.gambit.trading/mcp then run `/mcp` inside Claude Code, pick gambit, and sign in in the browser. - Claude (web and desktop): Customize → Connectors → + Add → Add custom connector. Name it Gambit, paste the URL, continue, and sign in when prompted. Turn it on per chat from the + menu → Connectors. On Team and Enterprise, an owner adds it first under Organization settings → Connectors; members then click Connect. - ChatGPT: open chatgpt.com/plugins → + → Add custom MCP server. Paste the URL as the public endpoint, keep the discovered authentication, and select Create as a plugin; sign in when prompted. Availability depends on your plan and workspace policy. - Codex CLI: codex mcp add gambit --url https://api.gambit.trading/mcp codex mcp login gambit - Cursor: add to `~/.cursor/mcp.json` (or `.cursor/mcp.json` in a project); Cursor prompts you to sign in: { "mcpServers": { "gambit": { "url": "https://api.gambit.trading/mcp" } } } - VS Code: add to `.vscode/mcp.json` (or run MCP: Open User Configuration), start the server, and sign in when VS Code prompts: { "servers": { "gambit": { "type": "http", "url": "https://api.gambit.trading/mcp" } } } - Any other MCP client: if it supports remote (Streamable HTTP) servers with OAuth, the URL is all it needs. Vendor docs for each client. The steps above were checked against these on 2026-10-08; menus move, so follow the vendor page if the two differ: - Claude Code: https://code.claude.com/docs/en/mcp - Claude (web and desktop): https://support.claude.com/en/articles/11175166-get-started-with-custom-connectors-using-remote-mcp - ChatGPT: https://developers.openai.com/plugins/deploy/connect-chatgpt - Codex CLI: https://learn.chatgpt.com/docs/extend/mcp?surface=cli - Cursor: https://cursor.com/docs/mcp - VS Code: https://code.visualstudio.com/docs/agent-customization/mcp-servers - Any other client (MCP authorization spec): https://modelcontextprotocol.io/specification/2025-06-18/basic/authorization OAuth discovery, for client implementers: - Protected resource metadata: `https://api.gambit.trading/mcp/.well-known/oauth-protected-resource` - Authorization server metadata: `https://api.gambit.trading/.well-known/oauth-authorization-server` — OAuth 2.1, authorization code + PKCE (S256 only), refresh tokens, Dynamic Client Registration at `https://api.gambit.trading/oauth/register`, and Client ID Metadata Documents (an `https://` client_id) supported - Consent page: `https://gambit.trading/oauth/authorize` - Server card: `https://api.gambit.trading/mcp/server.json` (MCP registry name `trading.gambit/gambit`) An OAuth grant is held to the same rules as a key: it only does what its scopes allow, and a grant that includes `api:trade` is a live trading credential — `propose_trade`, show the preview to the human, and `confirm_trade` only after their explicit approval. ### Headless agents and scripts: API key No browser and no human at sign-in time? Use a scoped API key. Create one in Settings → API (https://gambit.trading/settings/api), then (Claude Code shown; any MCP client that accepts a custom header works the same way): read -rs GAMBIT_API_KEY && export GAMBIT_API_KEY claude mcp add --transport http gambit https://api.gambit.trading/mcp \ --header 'Authorization: Bearer ${GAMBIT_API_KEY}' Public endpoints: - MCP: `https://api.gambit.trading/mcp` - REST base: `https://api.gambit.trading` - Legacy alias: `https://api.hypergambit.xyz` (same backend; keeps serving indefinitely — no need to migrate existing configs) - Human-readable API / MCP page (ungated): `https://gambit.trading/mcp` - Signed-in API reference: `https://gambit.trading/settings/api/docs/reference` Key handling (for agents): have the user supply the key via a silent local prompt (`read -rs GAMBIT_API_KEY && export GAMBIT_API_KEY`) or a secret manager. Never ask the user to paste the key into the conversation, and never write it into files, configs, logs, shell history, or command arguments. Keys are scoped (see Scopes below) and revocable in Settings. A key only does what its scopes grant — only `api:trade` keys can place trades, and only from the user's agent wallet, never the main wallet. For plain REST, exchange the key for a 5-minute token at `POST /api/auth/api-token` (send the key as `Authorization: Bearer`), then call the endpoints below with the returned token as the bearer. **Exchange immediately before each call or batch** — the token is deliberately short-lived; the exchange is cheap and rate-limited generously (30/5min per key). ### No MCP client? Call /mcp as plain JSON The MCP endpoint runs in stateless JSON mode: each `POST /mcp` is an ordinary HTTPS request carrying one JSON-RPC message, authenticated with your API key directly — no MCP SDK, no session, and **no token exchange or 5-minute expiry to manage**. This is the easiest path for an agent that can make HTTP calls but does not speak the MCP protocol, and the responses are shaped for LLM consumption (lean envelopes, self-correction hints): The auth header is piped via stdin (`-H @-`) so the key never appears in process arguments or shell history, and the `Accept` header must offer BOTH content types (the MCP transport rejects JSON-only accepts with a 406; the response still arrives as plain JSON): printf 'Authorization: Bearer %s\n' "$GAMBIT_API_KEY" | curl -sS \ https://api.gambit.trading/mcp -H @- \ -H "Content-Type: application/json" \ -H "Accept: application/json, text/event-stream" \ -d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}' printf 'Authorization: Bearer %s\n' "$GAMBIT_API_KEY" | curl -sS \ https://api.gambit.trading/mcp -H @- \ -H "Content-Type: application/json" \ -H "Accept: application/json, text/event-stream" \ -d '{"jsonrpc":"2.0","id":2,"method":"tools/call","params":{"name":"get_opportunities","arguments":{"view":"for_you","limit":10}}}' ## Scopes - `api:read` — market data, features, sentiment, news, Today's Market opportunities, portfolio updates, your Hyperliquid balances / positions / orders, and your recommendations - `api:portfolio` — your connected brokerage holdings and cash (Robinhood and any other broker linked to Gambit through SnapTrade) via `get_holdings`. Read-only. A separate grant from `api:read` because brokerage balances are more sensitive than market data. It gates the direct holdings endpoint and tool; an `api:chat` key can still discuss your account — including brokerage holdings — with your Gambit agent, as the in-app chat does - `api:respond` — record your accept/reject responses to recommendations - `api:recommend` — ask your Gambit agent for a fresh recommendation (uses your monthly quota) - `api:chat` — chat with your Gambit agent (uses your AI token allowance; advisory only — the agent cannot execute trades from this channel) - `api:trade` — place trades from your agent wallet via a two-step propose → confirm flow with server-side guardrails (price-drift checks, notional/leverage caps, hourly caps); never touches the main wallet - `api:account` — account setup, not trading: onboarding survey, setup status, key rotation, the agent-wallet approval poll, and the brokerage connect portal. Available on Settings keys, device-code signup keys, and OAuth grants alike Over OAuth the human picks these on the consent page; for an API key they are fixed when the key is created. A key or grant missing the scope an endpoint or tool needs gets a 403. ## What the API offers (read tools) - Market scanner ranked by funding/volume/OI/price-change across all Hyperliquid perps incl. HIP-3 DEX assets - Prices, OHLCV bars, computed features (returns, realized vol, z-scores, funding, OI deltas, market regime) — snapshot, timeseries, outliers - Live hot-cache snapshots per instrument - Sentiment indices (CNN Fear&Greed, Crypto F&G), news headlines, US equity options positioning (GEX/IV/dark pool) for major tickers - Today's Market opportunities: a ranked, evidence-backed feed of market observations (funding extremes, unusual flow, analyst actions, big equity moves, technical breaks), with a personalized For You view, per-card detail (evidence, model-written reads, price history, market stats), and a Daily Moves equity-session screen - Portfolio updates (rolling out — flag-gated server-side; a 401 that persists with a fresh, valid token means the deployment gate rather than your key): what changed for the instruments you hold or watch — symbol-tagged news with model-written digests, notable price moves, and upcoming earnings. Only symbols, coarse weight buckets, and PnL directions can cross the wire — sizes, dollar values, and account labels have no representation in the request schema. - Your Hyperliquid balances, open perp positions, and resting orders - Your connected brokerage holdings (needs `api:portfolio`; rolling out — flag-gated server-side like portfolio updates): Robinhood and any other broker linked to Gambit, stocks/ETFs and cash, read on demand from the brokerage through a short server cache and never persisted - Your agent's trade recommendations (pending + history) and the ability to record your accept/reject response ## MCP tool inputs and REST routes All REST routes below are relative to `https://api.gambit.trading` and use the 5-minute token as `Authorization: Bearer`. Account and agent routes derive the user from that token — never send a wallet address, user id, or agent id. - `whoami()` — MCP-only; returns the key's scopes - `scan_markets(sort_by?, top?, min_volume?, reverse?, include_hip3?)` → `GET /api/v1/info/scan` (`sort_by` is named `sort` in REST) - `get_prices(symbols?)` → `GET /api/v1/info/prices?resolve_spot=true`; `symbols` filters on both MCP and REST (comma-separated; REST names absent symbols in `missing_symbols`); omit for all prices - `get_bars(instrument_id, interval, start?, end?, max_points?)` → `GET /api/v1/raw/bars`; intervals are 1m/5m/15m/1h/1d. An omitted range defaults to the last 24h on both MCP and REST; a single supplied boundary anchors the other (end-24h / start+24h). - `get_feature(mode, feature_name, …)` → `GET /api/v1/transformed/{snapshot|timeseries|outliers}`. Optional route-specific inputs are instrument_id, universe_id, start, end, and n. Valid features: ret_1h, ret_4h, ret_1d, ret_1h_z, rv_1d, rv_1d_z, rv_7d, ewma_vol, vol_regime, range_expansion_z, trend_strength, drawdown_current, drawdown_max_30d, ma20h_zscore, ma50h_zscore, ma20d_zscore, ma50d_zscore, corr_btc_7d, corr_btc_30d, beta_btc_7d, beta_btc_30d, skew_30d, kurt_30d, cum_ret_7d, cum_ret_30d, ret_1h_pctl, rv_1d_pctl, funding_rate, funding_z_30d, oi_chg_1h, oi_chg_1h_z, oi_chg_4h, oi_chg_1d, oi_chg_1d_z, oi_price_divergence. - `get_live_snapshot(instrument_id? | instrument_ids?)` → `GET /api/v1/live/snapshot` or `GET /api/v1/live/batch` - `get_market_regime()` → `GET /api/v1/live/regime` - `get_sentiment()` → `GET /api/v1/sentiment/latest` - `get_news_headlines(hours?, symbol?, priority?, limit?)` → `GET /api/v1/news/headlines` - `get_equity_flow(kind, ticker, start?, end?, limit?)` → `GET /api/v1/equities/{gex|iv|darkpool}`; kind is gex, iv, or darkpool, and darkpool requires start + end - `get_opportunities(view?, categories?, ticker?, limit?, sort?, min_market_cap_usd?)` → `GET /api/v1/market-opportunities`; view is market (shared ranking, default), for_you (personalized to YOUR watchlist/cases/mandates), or saved; categories is an MCP array / REST CSV of trending, analyst_desk, idiosyncrasy, unusual_flow, prediction_markets, technical, institutional; limit caps at 24. Feed refreshes every ~10 minutes — do not poll faster. for_you backfills with market-ranked cards once your personal matches run out (by design — each item's `section` says personalized vs market_fallback). - `get_opportunity_detail(opportunity_id)` → `GET /api/v1/market-opportunities/{opportunity_id}`; ids are `mo_` + 32 hex from get_opportunities. Retired cards return with expired=true — historical, not a current signal. - `get_daily_moves(view?, limit?, min_abs_z?, min_session_dollar_volume_usd?, min_market_cap_usd?, market_session?)` → `GET /api/v1/market-opportunities/daily-moves`; view=compact (MCP default) returns qualifying US-equity session movers, view=all includes non-qualifying rows with their rejection reasons; scoped callers are capped at 500 rows. - `get_portfolio_updates(window?, limit?, holdings?, watchlist?)` → `POST /api/portfolio/updates` (note: not under /api/v1; rolling out — flag-gated server-side). Over MCP, omitting both lists derives holdings from your open positions; over REST send a JSON body with at least one instrument — entries are bare symbols or `{ id, weightBucket?, pnlDirection? }` objects. Only symbols, coarse weight buckets, and PnL directions can be sent — sizes, dollar values, and account labels have no representation in the schema. - `get_account_balances()` → `GET /api/v1/account/balances` - `get_positions()` → `GET /api/v1/account/positions` - `get_open_orders()` → `GET /api/v1/account/orders` - `get_holdings(view?, symbol?)` → `GET /api/portfolio/stocks/holdings` (needs `api:portfolio`). Your connected brokerage holdings — stocks/ETFs and cash, not crypto. `view=compact` (default over MCP) returns total value, `cashUsd` and `buyingPowerUsd` (the web app's numbers: USD-labelled or unlabelled balances only, other currencies not summed, and null — not 0 — when the total is zero or negative, so a CAD-only account or a negative margin balance reads null), each connected account, and `topHoldings` — the 10 largest account-level lots by absolute market value per currency (a symbol held in two accounts appears twice; shorts rank by exposure) with `holdingsCount` so you know what the cap hid. `symbol=NVDA` (compact only) adds `activeSymbolPosition`: the aggregate of that exact ticker across accounts (summed quantity and value, weighted cost, `lotCount`, `lots`), null when not held; tickers match exactly, so `BRK.B` never resolves to `BRK.A` and `BRK` matches neither (a `dex:` prefix like `xyz:TSLA` is stripped). `view=full` returns the raw snapshot instead — `holdings` (every lot), `totalCash`, `accounts` — with none of the compact-only fields, so do not read a missing `topHoldings` as an empty portfolio. No FX: amounts are never compared across currencies (lots with no currency code form an unranked sample — last, ordered by symbol, under the same 10-row cap; `caps_applied.top_holdings.unknown_currency_truncated` says if that sample dropped rows, and `per_currency` refers to known currencies only); a spotlight whose lots span currencies or lack a currency code reports null `marketValue`/`marketPrice`/`averageCost`/`currency` (quantity still sums), and one mixing long and short lots keeps net `quantity`, net `marketValue` and `currency` but reports null `marketPrice` and `averageCost`; the spotlight's `marketPrice` is the quantity-weighted average of the lots' own prices. `meta.data_freshness.status` is `fresh` inside the ~60s server cache and `stale` when a cached snapshot was served past it — brokerages sync roughly daily, so stale is fine for reading, not for sizing a trade. `meta.caps_applied` is non-null only when the top-10 cap dropped rows. `meta.degraded_reason` `brokerage_not_connected` means the user has not linked a brokerage in Gambit (Portfolio → Connect brokerage); an empty list is never silent. Read-only — there is no brokerage order placement. - `list_recommendations(status, limit?)` → `GET /api/v1/recommendations/{pending|history}`; row ids are the same ids `generate_recommendation` returns as `recommendation_id`. Not every generated id is listed: a watch mints none, and a run whose `ledger.status` is `recorded` (a different recommendation on the same instrument/direction was already pending) has a respondable id that is not in the pending list — the pending one is `ledger.existing_pending_recommendation_id` - `respond_to_recommendation(recommendation_id, response)` → `POST /api/v1/recommendations/{recommendation_id}/response`; response is accepted, rejected, or modified and does not execute a trade; pass the `recommendation_id` from `generate_recommendation` or a pending row — never `snapshot_id` - `generate_recommendation(watch_instrument?, all_universe?)` → `POST /api/v1/account/agent/recommend`. The answer is `user_facing_recommendation` with `state` recommend or watch (a reasoned no-trade). A recommend is `expression_kind` single_instrument (`instrument_id` + `direction`, plus `sizing` / `trade_ticket` when the desk could size it) or pair_trade (long/short `legs[{instrument_id, side}]`, no top-level instrument or direction). `recommendation_id` is the ledger id when the run produced a single-instrument recommend, and `respond_to_recommendation` takes it; `ledger.status` says how it lists: `pending` (in `list_recommendations(pending)`; when the same recommendation was already pending it is that row's id, `ledger.reason` `existing_pending_primary`) or `recorded` (a different recommendation on the same instrument/direction is already pending — this id is respondable but not listed; the pending one is `ledger.existing_pending_recommendation_id`). It is `null` when nothing was persisted (every watch, and a pair_trade for now), with the reason under `ledger.reason`. Only a `ledger.status` `pending` outcome can be reconciled from the pending list: a completed watch leaves no row, and a `recorded` outcome leaves the list unchanged, so `list_recommendations` cannot prove a timed-out run failed — wait out the run window (~2 min) before re-running; each run spends quota. `no_recommendation_reason.retryable` tells an operational failure (retry now) from a desk judgement (do not re-run). `snapshot_id` is the run's audit snapshot, not a recommendation id. - `ask_gambit_agent(message, new_conversation?)` → `POST /api/v1/account/agent/chat` (SSE; advisory only) - `propose_trade(symbol, side, notional_usd?, leverage?)` → `POST /api/v1/account/trade/propose`; side is long, short, or close - `confirm_trade(proposal_id, decision, asset?, side?, size_usd?)` → `POST /api/v1/account/trade/confirm`; execute requires the exact `confirm_echo` fields returned by propose, after explicit human approval; cancel needs no echo fields ## Agent actions (rolling out) New scoped endpoints and MCP tools are rolling out — availability is flag-gated server-side, so expect 403s (or a 400 when creating a key with a not-yet-grantable scope) until each lands: - Generate a recommendation: `POST /api/v1/account/agent/recommend` — MCP tool `generate_recommendation` (needs `api:recommend`) - Chat with your Gambit agent: `POST /api/v1/account/agent/chat` (SSE) — MCP tool `ask_gambit_agent` (needs `api:chat`) - Positions and open orders: `GET /api/v1/account/positions`, `GET /api/v1/account/orders` — MCP tools `get_positions`, `get_open_orders` - Brokerage holdings: `GET /api/portfolio/stocks/holdings` — MCP tool `get_holdings` (needs `api:portfolio`) - Trade from the agent wallet: `POST /api/v1/account/trade/propose` then `POST /api/v1/account/trade/confirm` — MCP tools `propose_trade`, `confirm_trade` (needs `api:trade`; show the proposal to the human and confirm only after explicit human approval) ## Key facts - Trading venue: Hyperliquid (mainnet). Minimum order ~$10 notional. - Instrument ids: bare Hyperliquid symbols (`BTC`, `HYPE`); HIP-3 perps use a DEX prefix (`xyz:TSLA`). Do not send `hl_perp:BTC` or `hl_spot:HYPE` — those prefixed forms do not match the public data store. Intervals: 1m/5m/15m/1h/1d. - API responses carry a `meta` envelope (generated_at, freshness, quality, caps_applied) — trust it over assumptions about data freshness. - Rate limits: data/account reads are budgeted at 120 requests/min per user, and the MCP endpoint separately enforces 120 requests/min per key plus a small concurrent-request cap. On a 429, wait the `Retry-After` seconds before retrying, and issue long calls (`ask_gambit_agent`, `generate_recommendation`) one at a time. Agent actions carry their own tighter limits (recommend 5/min plus a monthly quota, chat 10/min, trade executions capped hourly). - Keys and OAuth grants without `api:trade` cannot place trades or move funds. With `api:trade`, trades are agent-wallet-only, two-step propose → confirm, guardrailed, and require explicit human approval before confirming. - `api:read` does not grant the direct brokerage-holdings endpoint or `get_holdings`; that needs `api:portfolio`. ## Learn more - App: https://gambit.trading - Public MCP / API page (ungated): https://gambit.trading/mcp - Connect guide: https://gambit.trading/learn/connect-mcp - Learn hub: https://gambit.trading/learn - FAQ: https://gambit.trading/learn/faq - Settings → API (create a key for headless use): https://gambit.trading/settings/api - Full API reference (signed-in): https://gambit.trading/settings/api/docs/reference