Felix API
Trade every market with one key.
Felix lets an AI agent (or you) trade stocks, crypto, perps, options, and prediction markets through one key and one set of endpoints. Sizes are in plain dollars, there is no contract math, and your money stays in a wallet you control. Orders are live by default; set paper: true explicitly when you want simulation.
Base URL: https://api.felix.trade. Every endpoint lives under /v1. Responses are JSON.
Start here
Three steps to your first paper trade.
1. Get your own key, free
No invite, no signup form, no human. Felix is non-custodial, so the key that will hold your funds is your identity: generate it locally, prove you control it, and the account is yours.
# 1. ask for a challenge
curl -X POST https://api.felix.trade/v1/register/challenge \
-H "Content-Type: application/json" \
-d '{"owner_address":"0xYourLocallyGeneratedAddress"}'
# → { "message": "Felix account registration\n...", "nonce": "...", "expires_at": ... }
# 2. sign that exact message locally with the owner key (EIP-191)
# 3. exchange the signature for an account and key
curl -X POST https://api.felix.trade/v1/register \
-H "Content-Type: application/json" \
-d '{"message":"<the message>","signature":"0x...","accept_terms":true}'
# → { "account_id": "...", "api_key": "fk_...", "scopes": ["read","trade"] }
# MCP users: one command does all three
npx -p felix-mcp felix-keys registerThe owner key you generate controls every dollar the account will ever hold, and no one, including us, can recover it. Back it up before you fund anything. Your account is permanently bound to that address, one account per address. The issued key trades real money but is not live-enabled yet: live is a separate owner-signed grant once a venue is onboarded on-chain.
1b. Or derive a child account from an existing key
If you already hold a manage key, you can create isolated child accounts programmatically:
curl -X POST https://api.felix.trade/v1/accounts \
-H "Authorization: Bearer $FELIX_MANAGE_KEY" \
-H "Idempotency-Key: $(uuidgen)" \
-H "Content-Type: application/json" \
-d '{"accept_terms":true,"label":"research agent","paper":true}'
# → { "account_id": "...", "key_id": "...", "paper_key": "fk_...",
# "wallet_status": "onboarding_required", "deposit_address": null }accept_terms: true is required. Creating a key records your agreement to the Terms of Service, Privacy Policy, and Risk Disclosure; without it the call is rejected. The child is isolated and zero-funded. The raw key appears only on the first successful response; exact retries are redacted. Complete client-owned wallet onboarding before funding or live-key creation.
2. Quote a market
curl https://api.felix.trade/v1/quotes/BTC \
-H "Authorization: Bearer $FELIX_KEY"
# → { "instrument": "crypto:BTC", "price": 61825.5, "market": "crypto" }3. Place a paper trade
The same call works for every market. You buy 50 dollars of something, not a number of shares or contracts.
curl -X POST https://api.felix.trade/v1/orders \
-H "Authorization: Bearer $FELIX_KEY" \
-H "Content-Type: application/json" \
-d '{"instrument":"BTC","side":"buy","size_usd":50,"paper":true}'
# → { "ok": true, "mode": "paper", "status": "filled",
# "fill_price": 61825.5, "filled_size_usd": 50, "fee": {"fee_usd": 0.04} }Use it from your AI tool
Felix has a certified local MCP build, so Claude, Cursor, and Codex can trade through it directly. Registry publication remains operator-controlled. Once published, one line of setup and the model gets tools in its loop: search_markets, get_quote, preview_order,place_order, positions, pnl, and panic. Orders are live by default and paper mode must be requested explicitly.
Claude Code (CLI)
npx -p felix-mcp felix-keys setup npx -p felix-mcp felix-keys set-api-key claude mcp add felix -- npx -y felix-mcp
On macOS, Felix reads both credentials from Keychain at process launch. The model never receives either secret. On other operating systems, inject FELIX_API_KEY from an OS secret manager; do not paste it into a prompt, chat, source file, or tool call.
Claude Desktop
Add this to claude_desktop_config.json (Settings → Developer → Edit Config):
{
"mcpServers": {
"felix": {
"command": "npx",
"args": ["-y", "felix-mcp"]
}
}
}Cursor
Settings → MCP → Add new server, or drop this in ~/.cursor/mcp.json:
{
"mcpServers": {
"felix": {
"command": "npx",
"args": ["-y", "felix-mcp"]
}
}
}Codex
[mcp_servers.felix] command = "npx" args = ["-y", "felix-mcp"]
ChatGPT, or any agent without MCP
No MCP? Point the model at the API plus the one-file docs, and it can drive Felix on its own. Thellms.txt file below is written specifically for a model to read and use without guessing.
# 1. The full API as one file (feed this to the model): https://felix.trade/llms.txt # 2. The base URL. Your application injects the key outside model context: https://api.felix.trade with header Authorization: Bearer $FELIX_API_KEY # Or just use the SDK inside your agent: pip install felixtrade # or: npm install felix-sdk
Agent playbook
These are the operational rules that keep automated trading safe. They exist because each one prevents a failure mode we have actually observed. If you are wiring Felix into an agent loop, this section matters more than any endpoint list.
The loop
GET /v1/status # is the platform healthy
GET /v1/instruments?q=... # find the market
GET /v1/quotes/{instrument} # live price
POST /v1/orders/preview # fees, min size, liquidity
POST /v1/orders (or client-signed pm flow)
GET /v1/positions + /v1/fills # VERIFY before deciding anything else
POST /v1/positions/{id}/close # exit
GET /v1/pnl # settle the loopErrors can accompany real fills
A network hiccup after submission can return an error for an order the venue actually filled. Positions and fills are the source of truth, never the error text alone. Before any retry, reconcile: for prediction markets read GET /v1/orders/polymarket/intents/{intent_id}; everywhere else read positions and fills. Retrying an ambiguous failure without reconciling is how agents double-fill.
Idempotency keys are workflow identities
A money workflow key is durable state, not per-request noise. Resume an interrupted funding or return with the same key: it replays completed checkpoints instead of moving funds twice. Start a new key only for a genuinely new intent, and never rotate a key to get past an ambiguous result. Timeouts on money workflows mean still settling, not failed: check balances before any second attempt.
Prediction-market sizing rules
- • The venue order book requires $1.00 per order; Felix requires $2.00 for a new position so it opens above the venue sell minimum.
- • The venue accepts an order only when the wallet covers the order plus its fee estimate, which scales with
min(price, 1 - price): near zero at extreme prices, roughly 4 to 6 percent of notional at mid prices. Felix enforces this at prepare and the error states the exact required total. - • Close multi-outcome positions through the order book before the market resolves.
Money movement
- • Funding a venue costs a flat $1.00 network fee, so small fundings carry a high percentage cost. The client checks the source balance before binding anything and fails closed with exact numbers.
- • Cross-chain transfers below about $4 are rejected up front: the final bridge leg is unreliable at that size.
- • Options returns take two calls: the first lands funds in the owner wallet on the venue's own chain in about 2 minutes, and a second call with a new key bridges them home automatically. The responses label every intermediate state honestly.
Keys & auth
Send your key as a Bearer token on every request:
Authorization: Bearer fk_xxxxxxxx
- • Create keys programmatically: an existing
managekey usesPOST /v1/accountsfor an isolated child. Omitted orpaper: falsereturns a read-only onboarding bootstrap;paper: trueorPOST /v1/keys/paperexplicitly requests simulation access. - • Every key starts with
fk_. Paper/live authority is server-side metadata, never a token prefix. - • Scopes:
read(data + account),trade(orders),manage(create accounts + keys, funding),transfer(withdrawals, off by default). - • No key or a bad key →
401. Valid key without the right scope →403. - • Treat every key as a secret. Raw keys are shown once; never paste them into prompts or logs. Revoke exposed keys immediately.
Instruments
One naming scheme for every market. Inputs are forgiving: BTC, btc, and BTC-USD all work.
| Market | Write it as | Example |
|---|---|---|
| Crypto / perp | SYM or crypto:SYM | BTC, ETH, SOL |
| Stock | SYM or stock:SYM | NVDA, TSLA |
| Option | option:UND-YYYYMMDD-STRIKE-C/P | option:BTC-20260711-70000-C |
| Prediction market | pm:<slug> | pm:fed-cut-in-september |
Sizes are always in USD via size_usd. Every response tells you the market it resolved to.
Place a trade
Optional but recommended: preview first to see the fill price and fee before you commit.
{ "instrument": "BTC", "side": "buy", "size_usd": 50 }
# → { "est_fill_price": 61825.5, "fee": {"fee_usd": 0.04, "bps": 8},
# "min_live_size_usd": 10 }Place the order
{
"instrument": "NVDA",
"side": "buy", // buy | sell | long | short | yes | no
"size_usd": 250,
"type": "market", // market | limit (limit_price optional)
"paper": false // false or omitted = live; true = simulate
}- • Paper vs live: omitted or
paper: falseuses real money. Setpaper: trueto simulate. Live execution needs an owner-authorized live key plus anIdempotency-Keyheader. - • Client signing: live prediction-market orders use prepare, local sign, checkpoint, server relay, commit, and reconciliation; the generic live route refuses to hold the owner key.
- • Idempotency: put a unique
Idempotency-Key: <uuid>header on any live order so a retry never double-trades. - • Live minimum: paper can be tiny; live crypto/perp is at least ~$10. Preview returns
min_live_size_usd. - • Close a position:
POST /v1/positions/{id}/close. - • Batch:
POST /v1/orders/batchaccepts up to 50 items. Omitted orpaper: falseitems execute live; onlypaper: truesimulates. Each live item has an independent idempotency key, processing stops after the first live failure, and the response must be checked item by item.
Live prediction-market order
The TypeScript and Python SDKs wrap this sequence as one call when you provide a local signer callback:
POST /v1/orders/polymarket/prepare
# locally sign the exact prepared order; never send the private key
POST /v1/orders/polymarket/checkpoint
POST /v1/orders/polymarket/submit
POST /v1/orders/polymarket/commit
GET /v1/orders/polymarket/intents/{intent_id} # reconcile ambiguityPositions & PnL
Use these endpoints to reconcile Felix state with current venue balances, fills, and positions.
GET /v1/positions — open positions with live unrealized PnLGET /v1/fills — every fill: entry, exit, price, size, fee, realized PnLGET /v1/pnl — realized + unrealized + fees + net, with countsGET /v1/balances — spendable cash + per-market balances{ "realized_pnl_usd": -0.14, "unrealized_pnl_usd": 2.31,
"total_fees_usd": 0.42, "net_pnl_usd": 1.75,
"open_positions": 2, "closed_positions": 27 }Money in & out
Your funds live in a client-owned wallet. Felix prepares policy, funding, and withdrawal actions; the owner signs them locally.
Where is my money: one answer
Money can legitimately sit in several places at once: the owner wallet on the home chain, an intermediate chain during a bridge, a venue's own chain after a withdrawal, each venue account, and open positions. One call returns all of it: GET /v1/money (or the MCP tool get_money_map) as one flat list where every entry says what the balance is for and exactly which call moves it, with gas shown separately and any unverifiable source listed as unavailable rather than counted as zero.
{ "total_usd": 5.69,
"locations": [
{ "name": "owner_wallet_polygon", "usd": 1.02,
"note": "Home base. Deposits land here; fund_market spends from here." },
{ "name": "owner_wallet_arbitrum", "usd": 2.57,
"note": "Crypto/options funding spends from here; sub-$4 returns wait here." },
{ "name": "prediction_market_wallet", "usd": 2.04, "reserved_usd": 0,
"note": "Spendable on prediction markets now. bring_home returns it." },
{ "name": "open_positions", "usd": 0, "count": 0, "note": "Cost basis; not added to total." }
],
"gas": { "polygon_native": 0.61, "note": "Gas, not spendable balance." },
"unavailable": [],
"how_to_move": { "to_venue": "fund_market", "back_home": "bring_home" } }- • Wallet: complete
/v1/wallet/onboarding/init, locally sign the prepared deployment, then call/deployand/complete. - • Deposit:
GET /v1/deposit-addressreports the owner-controlled address after onboarding. Check/v1/wallet/funding/balancesbefore routing funds. - • Fund a venue: call
/v1/wallet/funding/prepare, execute the returned owner-signed transaction plan client-side, then call/confirm. Use the matching return flow to bring venue funds home. - • Withdraw: add and confirm an address with idempotency keys, wait for the safety delay, then use
/v1/withdraw/prepare, owner-sign locally, and/v1/withdraw/submit. Only allowlisted addresses.
Agents & strategies
Describe a strategy in words, backtest it, then deploy it as an agent that runs on its own inside your limits.
// 1. Generate from a prompt
POST /v1/strategies/generate
{ "prompt": "buy BTC on a 3% intraday dip, take profit at 5%" }
// 2. Backtest it on history
POST /v1/backtests { "strategy": { ... } }
// 3. Deploy it (paper first)
POST /v1/agents
{ "strategy": {...}, "name": "dip buyer", "budget_usd": 100, "mode": "paper" }
// status / stop
GET /v1/agents/{id}
POST /v1/agents/{id}/stopMarket data
GET /v1/instruments?q=nvidia — search across every marketGET /v1/quotes/{instrument} — live price + spreadGET /v1/orderbook/{instrument} — top of bookGET /v1/options/{underlying} — full option chain (strikes, expiries, greeks, IV)GET /v1/funding/{instrument} — perp funding rateWebhooks
Get pinged when things happen instead of polling.
{ "url": "https://you.dev/hook",
"events": ["order.filled", "position.closed"] }
# → { "id": "...", "signing_secret": "whsec_..." }Each event is signed with HMAC-SHA256 over the raw body in the X-Felix-Signature header. Verify it before trusting the payload.
Errors & safety
Every error is JSON with a hint telling you how to fix it.
{ "error": { "code": "insufficient_scope",
"message": "this key can't place orders",
"hint": "create a key with the 'trade' scope" } }- • Rate limits:
X-RateLimit-*headers on every response;429+Retry-Afterwhen you hit the ceiling. A throttle is not a revoked key. - • Kill switch:
POST /v1/paniccancels everything and revokes the calling key instantly. - • Status:
GET /v1/status(no auth needed).
Codes agents will actually see
| Code | What to do |
|---|---|
| insufficient_owner_balance | Fund the owner wallet or reduce the amount. Nothing was started. |
| network_fee_unpaid (409) | A previous funding fee is unresolved. Resume with the original key or contact support; do not start new fundings for that venue. |
| clob_rejected_order | Read venue_error in the response for the venue's actual reason, usually the balance-plus-fee rule. |
| workflow_reconciliation_required | A prior process may have submitted. Verify balances and fills, then resume with the SAME key. |
| return_confirmation_timeout | Still settling. Check balances before any further action; do not resubmit. |
| high_fee_acknowledgement_required | The fee is large relative to the amount. Retry with allow_high_fee_loss:true only after accepting it. |
| return_amount_too_small | Leave the balance where it is until it exceeds the stated minimum. |
| client_upgrade_required | Upgrade the client build before live orders. |
SDKs
The Python and TypeScript SDK artifacts and the MCP build (current certified: 2.0.15) are built, contract-tested, and SHA-256-pinned. These install commands become public only after operator-approved registry publication.
pip install felixtrade
from felix import Felix
felix = Felix("fk_...")
felix.buy("BTC", usd=50) # live by default
felix.buy("BTC", usd=50, paper=True) # explicit simulation
# Live prediction markets require Felix(..., polymarket_signer=local_signer).npm install felix-sdk
import { Felix } from "felix-sdk";
const felix = new Felix("fk_...");
await felix.buy("BTC", 10); // live by default
await felix.buy("BTC", 10, "buy", { paper: true }); // simulationInteractive reference (OpenAPI): https://api.felix.trade/v1/docs
For AI agents, the full docs as one file: felix.trade/llms.txt
Non-custodial rails for AI agents. Not a brokerage. Not financial advice.