Felix documentation · API v2
One interface for agent-driven trading.
Research, fund, and trade across supported market categories through one Felix account and control layer. Sizes are always in USD. Check Felix Status for current availability.
Public MCP release
Felix developer infrastructure is live. MCP 2.0.110 is public on npm; pin this exact version while validating a new installation.
01
Research
Quotes, market data, fundamentals, and flow.
02
Test
Read-only backtests on historical data.
03
Execute
Real-money actions require separate owner authorization.
04
Verify
Reconcile through positions, fills, PnL, and money.
Browse documentation
Getting started
Choose the managed real-money MCP flow or the advanced bring-your-own-signer API flow. Every path begins with an owner identity created and retained on your device.
1. Run guided local onboarding
Your AI agent may launch and monitor this one command. Felix creates or reuses the owner identity in macOS Keychain, registers it, creates an encrypted recovery backup, configures the selected MCP client, and verifies the connection. The owner key and recovery code never enter the agent, terminal output, environment, or Felix servers.
# Choose codex, claude, or cursor for your MCP client npx -y --package felix-mcp@2.0.110 felix-keys onboard --accept-terms --client codex # Reconnect Felix, then read the MCP resource: # felix://getting-started
Node 20.10 or newer is checked before any credential changes. After the user reviews the terms, the agent completes registration, encrypted backup, client setup, and verification. Owner, API, and recovery secrets remain in macOS Keychain. No human-created password is required. Re-running the command safely reuses completed steps. After reconnecting, callget_custody_recovery_status and require ready: true before funding.
2. Create a real-money account
# Reuse this idempotency key after interruption:
create_account({
accept_terms: true,
legal_version: "2026-08-30",
idempotency_key: "primary-live-account"
})Live is the default for execution tools. The first call reserves an identity and returns its Polygon deposit address. Send at least $5 of one of the exact accepted stablecoins, wait for confirmation, then retry with the same idempotency key. Empty accounts remain database-only. After funding is verified, activation normally takes 60–120 seconds, signs the exact Safe policy locally, stores the child binding in Keychain, and never sends the owner private key to Felix.
Registration, API-key minting, and unfunded account reservation spend no chain gas. Felix's initial wallet-activation gas is covered only after the deposit is verified; this grants Felix no wallet ownership or withdrawal authority. Rejections start no activation and move no money; follow the returned action and reuse the same account-creation key.
3. Prepare an autonomous Polymarket wallet
Interactive Polymarket orders use the local client signer. A background agent uses a separate, deterministic venue-scoped wallet. Felix sets up that wallet and installs the exact pUSD and CTF exchange approvals automatically; callers never construct approval calldata or provide a private key. Fund it once with fund_polymarket_agent_wallet and a stable idempotency key before deploying the agent. Resolved winnings redeem back into the same scoped wallet so they remain working pUSD. Polymarket stop loss is optional because Felix does not offer a server-side stop order on that venue.
4. Custom signer or direct REST registration
SDK and HSM integrations generate the owner key locally and prove control by signing the registration challenge. Use the manual wallet-onboarding sequence only after validating every returned owner, chain, Safe transaction, module runtime, contract allowlist, limit, nonce, and expiry before signing. The MCP reference validators and signing example are infelix://getting-started.
# 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,"legal_version":"2026-08-30"}'
# → { "account_id": "...", "api_key": "fk_...", "scopes": ["read","trade"] }
# Acquisition metadata is optional, is carried through both registration steps,
# and never changes account or key authority.
# Self-service registration is live. Registration moves no funds and does not
# authorize live execution; those remain separate owner-signed steps.The owner key controls the account and cannot be recovered by Felix. Back it up before funding. Registration does not enable live trading; that requires a separate owner-signed grant after venue onboarding.
5. Create an isolated child account through REST
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,"legal_version":"2026-08-30","label":"research agent"}'
# → { "account_id": "...", "key_id": "...", "bootstrap_key": "fk_...",
# "wallet_status": "onboarding_required", "deposit_address": null }accept_terms: true is required. Send legal_version: "2026-08-30" or omit it to accept the current server version. Creating an account records an encrypted acceptance time and channel, plus the exact bundle version for the Terms of Service, Privacy Policy, and Risk Disclosure, and Custody & Authority Notice; without affirmative acceptance 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.
6. Quote a market
curl https://api.felix.trade/v1/quotes/BTC \
-H "Authorization: Bearer $FELIX_KEY"
# → { "instrument": "crypto:BTC", "price": 61825.5, "market": "crypto" }7. Place an owner-authorized real-money order
The normalized order shape is shared across supported market types. Runtime and account state still determine availability. 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 "Idempotency-Key: $(uuidgen)" \
-H "Content-Type: application/json" \
-d '{"instrument":"BTC","side":"buy","size_usd":50}'
# → { "ok": true, "mode": "live", "status": "filled",
# "fill_price": 61825.5, "filled_size_usd": 50, "fee": {"fee_usd": 0.04} }Connect an AI tool
Connect Claude, Cursor, or Codex through the exact checksummed Felix MCP version. MCP exposes bounded tools for research, orders, positions, PnL, and emergency controls. Live actions still require owner authorization.
Codex, Claude Code, or Cursor
# Choose codex, claude, or cursor for your MCP client npx -y --package felix-mcp@2.0.110 felix-keys onboard --accept-terms --client codex
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 Felix to claude_desktop_config.json (Settings → Developer → Edit Config):
{
"mcpServers": {
"felix": {
"command": "npx",
"args": ["-y", "felix-mcp@2.0.110"]
}
}
}Cursor
Settings → MCP → Add new server, or drop this in ~/.cursor/mcp.json:
{
"mcpServers": {
"felix": {
"command": "npx",
"args": ["-y", "felix-mcp@2.0.110"]
}
}
}Codex
[mcp_servers.felix] command = "npx" args = ["-y", "felix-mcp@2.0.110"]
Direct API review for ChatGPT or another agent
For architecture review, give the model the API contract plus the one-file docs. Your application injects the credential outside model context and calls Felix through the direct API. Thellms.txt file is written specifically for a model to read 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 # Install the exact public MCP release: felix-mcp@2.0.110. # Python and TypeScript SDKs remain private.
Agent playbook
Use this loop for every automated strategy. It prevents the retry and reconciliation mistakes that can turn one order into two.
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 loopDo not guess instrument IDs
Use MCP search_markets to resolve a phrase into returned candidates. Uselist_markets when completeness matters: select a venue and lifecycle state, follow next_cursor until complete is true, and copy the returned canonical instrument exactly. Never synthesize a Polymarket slug, Derive contract, or venue symbol. Before building logic around an instrument, call preview_order; its current minimum, collateral, leverage, liquidity, fee, and auto-funding fields are authoritative.
Errors 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.
- • Fee-credit top-ups preserve a disclosed owner-wallet trading buffer by default. An explicit low-buffer override can leave too little home USDC.e to auto-fund the next venue action.
- • Cross-chain transfers below about $4 are rejected up front: the final bridge leg is unreliable at that size.
- • Derive option minimums are instrument-specific and fixed venue fees can make a small order uneconomical even when collateral is sufficient. Use the current
preview_orderresult; never reuse a minimum learned from another contract. - • 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 accounts programmatically: an existing
managekey usesPOST /v1/accountsfor an isolated child and a one-time read-only onboarding bootstrap. Real-money execution requires a separately owner-signed key. - • Every key starts with
fk_. 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 normalized naming scheme spans five market types. 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)
}- • Real-money execution: every order uses real funds and needs an owner-authorized key plus an
Idempotency-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: crypto/perp orders are 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 with explicit top-levelmode: "live". Processing stops after the first failure, and the response must be checked item by item.
Owner-authorized 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
After any order attempt, verify the result from positions and fills before taking another action.
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.
See every balance in one response
GET /v1/money (MCP: get_money_map) lists owner wallets, venue balances, bridge states, and open positions. Gas is separate. A source that cannot be verified is marked unavailable, never treated 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: call
/v1/withdrawal-addresses/prepare, sign its exact destination message locally, then submit it to/v1/withdrawal-addresses. The address activates immediately; no waiting period applies. Use/v1/withdraw/prepare, owner-sign locally, and/v1/withdraw/submitto move funds. - • USDC.e destination safety: a USDC.e withdrawal delivers bridged USDC.e on Polygon at
0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174. Many centralized exchanges do not accept this exact token. Unless the exchange explicitly confirms support, withdraw to a self-custody Polygon wallet first and convert to native Polygon USDC before depositing to the exchange.
First withdrawal through MCP
1. get_money_map + get_situation
2. add_withdrawal_address({ address, chain: "polygon" })
3. list_withdrawal_addresses() and verify the exact destination
4. withdraw({ address, amount, token, source: "auto", idempotency_key })
5. verify operation state, transaction hash, and destination balance
# After interruption, reuse the exact idempotency key and reconcile.
# Never assert resume_reconciliation until the returned recovery contract says to.Security & custody
The wallet uses canonical Safe v1.3.0 core contracts plus a Felix-authored policy module for bounded agent actions. Safe does not audit, approve, or guarantee that module. The owner key remains on the client.
What remains under your control
- • Owner key: generated and stored on the client. Felix receives signatures, never the private key.
- • Safe ownership: the user's address is the owner. The agent cannot replace the owner, lower the threshold, or choose an arbitrary recipient.
- • Agent authority: limited to reviewed venue contracts, exact short-lived orders, fixed assets and recipients, owner-signed caps, and an expiry.
- • Agent signing: venue-scoped execution authority enforces the requested action and owner-approved mandate before producing a venue signature.
Who controls trading limits
Limits have two layers. The account's wallet policy is the immutable owner-signed ceiling; every API key's limits must fit inside it. Neither an API key, a manage key, nor Felix can raise an existing account's ceiling. This prevents authority from expanding after the owner creates the account.
- • Wallet policy: per-operation, daily, and lifetime ceilings are chosen at account creation and cannot be edited in place.
update_wallet_policysupports pause, resume, renew, and lockdown; it does not change those ceilings. - • API-key grant: the owner or launcher chooses each key's limits when minting it. Existing key caps are not edited in place; revoke and replace the key to choose different limits inside the same account ceiling.
- • Higher limits: create a new account with the intended ceilings, then move funds through the ordinary withdrawal and deposit flows. Felix still enforces available balance, venue liquidity, explicit leverage intent, and signed transaction scope.
Emergency controls are separate
POST /v1/panic cancels managed activity and revokes the calling API key. Pausing or disabling the Safe module blocks new module actions. Neither action automatically revokes token allowances that were already granted to an approved venue contract; the owner must revoke those allowances on-chain. Keep an owner-key backup and verify the Safe state before depositing significant funds.
This design has internal static analysis, runtime-bytecode attestation, and continuous Safe-state monitoring. It has not received an independent smart-contract audit. Choose conservative account ceilings during beta; increasing them later requires creating a new account and migrating funds.
Strategies & backtests
Backtests are read-only: they do not deploy an agent, place an order, sign, or change a balance. Test def think(ctx) on historical bars, inspect the methodology, then decide separately whether to deploy.
The reliable five-step loop
- 1. Read
get_strategy_guide(section="examples")orfelix://strategy/examples. - 2. Hand-write
def think(ctx), or callgenerate_strategyonce as an optional convenience. - 3. Call
backtestfor bounded work, orstart_backtestfor a durable long-history job. - 4. Reject flattering results when
historical_validity.statusisdegraded; inspect its live-only signals and methodology. - 5. Deploy separately with an explicit
budget_usd, owner-authorized live access, and hard risk limits.
Hand-write and test without an LLM
curl -X POST https://api.felix.trade/v1/backtests \
-H "Authorization: Bearer $FELIX_KEY" \
-H "Idempotency-Key: btc-breakout-v1" \
-H "Content-Type: application/json" \
-d '{
"name":"BTC 24h breakout",
"strategy":{"config":{"code":"def think(ctx):\n price = ctx.price(\"BTC\")\n if price is None:\n return {\"action\":\"hold\",\"reason\":\"price unavailable\"}\n return {\"action\":\"hold\",\"reason\":\"waiting\"}"}},
"markets":["BTC"],
"interval":"1h",
"bars":500,
"capital":100,
"detail":"summary"
}'generate_strategy consumes the account's generation budget. Manual strategies do not. Exact retries with the same strategy, parameters, and idempotency key return the cached result instead of running or charging the workflow twice.
What a result tells an agent
{
"ok": true,
"effective_params": { "markets": ["BTC"], "interval": "1h", "bars": 500 },
"performance": { "execution_ms": 794, "target_met": true, "cache_hit": false },
"result": {
"metrics": { "total_return_pct": 1.8, "max_drawdown_pct": -2.4, "num_trades": 7 },
"equity_curve": ["bounded chart-ready points"],
"monthly_returns": [],
"historical_validity": { "status": "valid", "live_only_signals": [] },
"methodology": { "historical_data": "real", "limitations": "..." }
}
}Real bars do not make a backtest predictive. Check sample size, costs, drawdown, position sizing, look-ahead risk, and out-of-sample behavior. A zero-trade or degraded run is not evidence of safety.
Current capability boundaries
Agents must plan around what is not first-class today. Event-market synthetic replay, parameter sweeps, walk-forward optimization, portfolio backtests, one cross-venue net-delta limit, tax-lot statements, and full audit-log export are not published endpoint contracts. Orchestrate bounded independent backtests externally where appropriate, preserve every effective parameter and cost assumption, and never infer portfolio neutrality from per-position data. The machine-readable version is agent-index.json.
Synchronous or durable
backtestReturns the result in one response. Best for normal bounded jobs and interactive iteration.start_backtestReturns an operation_id promptly. Persist it and poll get_backtest_operation.resume_backtest_operationUse only after an expired worker lease or API restart. Completed operations replay their terminal result.start_backtest(
strategy={"config":{"code":"def think(ctx): ..."}},
markets=["BTC"], interval="1h", bars=500, capital=100,
idempotency_key="fxbt_<32 lowercase hex characters>"
)
# Persist operation_id.
get_backtest_operation(operation_id="fxbt_...")
# Resume only if the response says its worker lease expired.
resume_backtest_operation(operation_id="fxbt_...")Bounds that are never silently clamped
- • At most 4 markets; split larger sweeps into separate backtests.
- • Intervals:
1m,5m,15m,1h,4h,1d. - • Bars: minimum 20; caps are 20,000 / 25,000 / 30,000 / 45,000 / 15,000 / 12,000 by interval.
- • Minute-level history uses
bars. Wider intervals acceptyears;1dsupports up to 40 years. - • Starting capital: $10 to $1,000,000. Detail:
summaryorfull.
Research & market data
These endpoints return bounded, structured data without an LLM call. Delayed feeds identify themselves, and research never places an order.
Research limits are 12 calls/minute on Free, 60 on Pro, and 180 on Scale. Cold provider reads can take up to 20–25 seconds; cached reads are faster. Honor Retry-After on 429.
GET /v1/instruments?q=nvidia: search across normalized market typesGET /v1/quotes/{instrument}: live price + spreadGET /v1/orderbook/{instrument}: top of bookGET /v1/options/{underlying}: tradeable Derive crypto-option chainGET /v1/funding/{instrument}: perp funding rateGET /v1/research/{symbol}: historical research cards + structured signalsGET /v1/markets/screener: bounded stock/crypto momentum and volatility screenGET /v1/markets/earnings: upcoming earnings dates and estimatesGET /v1/markets/fundamentals/{symbol}: separately labelled live/TTM and filed periodsGET /v1/equity-options/{symbol}: delayed consolidated equity-option chainPOST /v1/options-flow: delayed unusual volume/open-interest and premium scanResearch a market
{
"kind": "research",
"symbol": "BTC",
"interval": "1h",
"signals": { "regime": "...", "trend": { ... }, "volatility": { ... } },
"cards": [ ... ],
"requested_bars": 750,
"tier_bar_limit": 750,
"execution_note": "Decision support only; research never places an order."
}Scan delayed equity-options flow
{
"symbols": ["SPY", "NVDA", "TSLA"],
"side": "call",
"min_premium": 50000,
"min_vol_oi": 2,
"min_volume": 200,
"limit": 30
}
# source: delayed consolidated chains
# data_class: delayed_decision_support
# This is not tape-level sweep detection.Live market streams
Stream normalized Hyperliquid, Polymarket, and Derive quotes, books, and trades over a read-only WebSocket. API keys never go in the WebSocket URL: mint a one-time ticket over HTTPS, then authenticate with that ticket as the first WebSocket message.
POST /v1/stream/tickets: mint a one-use, 30-second ticket with a read-scoped bearer keywss://api.felix.trade/v1/streamconnect with subprotocol felix.market.v1quote | book | tradessubscribe using canonical instruments from searchconst ticketResponse = await fetch("https://api.felix.trade/v1/stream/tickets", {
method: "POST",
headers: { Authorization: `Bearer ${felixKey}` },
});
const { ticket, websocket_url: url } = await ticketResponse.json();
const ws = new WebSocket(url, "felix.market.v1");
ws.addEventListener("open", () => {
ws.send(JSON.stringify({ op: "authenticate", ticket }));
});
ws.addEventListener("message", ({ data }) => {
const event = JSON.parse(data);
if (event.type === "ready") {
ws.send(JSON.stringify({
op: "subscribe",
request_id: "market-screen-1",
subscriptions: [
{ channel: "quote", instrument: "crypto:BTC" },
{ channel: "book", instrument: "pm:<market-slug>" },
],
}));
}
});Delivery and recovery
- • Tickets expire after 30 seconds, work once, and must be sent within five seconds of connecting.
- • Subscription batches are atomic: if one item is invalid or exceeds capacity, none are applied.
- • Quotes and books are latest-state streams, so intermediate updates may be coalesced for a slow consumer.
- • Trades stay ordered in a bounded queue; Felix disconnects before silently dropping trade events.
- • After reconnect, a sequence gap, or
resync_required, fetch a fresh REST snapshot before acting. - • Reconnect with exponential backoff and jitter, mint a fresh ticket, then resubscribe.
Every market event carries sequence, source_time_ms, received_at, andsource_lag_ms when the venue supplies a timestamp. The socket is market data only: it never accepts orders, signatures, account IDs, private state, or provider credentials.
Plans & renewal
Free and Pro use the same owner-control boundaries. Pro is currently specified at $20 for 30 days and adds throughput, research depth, larger flow scans, more backtests, and a small Felix fee discount.
GET /v1/tiers: canonical Free, Pro, and Scale capabilitiesGET /v1/me/subscription: current entitlement, limits, expiry, and renewal contractPOST /v1/me/subscription/prepare: exact $20 native Polygon USDC transfer intentPOST /v1/me/subscription/confirm: verify receipt and atomically activate 30 days# Both mutations require a stable Idempotency-Key and manage scope.
POST /v1/me/subscription/prepare
{ "plan": "pro" }
# Validate locally: chain 137, native Polygon USDC, fixed treasury,
# amount_units 20000000. The owner signs and broadcasts that exact transfer.
POST /v1/me/subscription/confirm
{ "subscription_token": "...", "transaction_hash": "0x..." }
# MCP does the local validation/signing/reconciliation as one command:
upgrade_subscription(plan="pro", idempotency_key="stable-workflow-key")Auto-renew is off. Felix cannot silently pull funds: each 30-day period needs a fresh owner-signed payment. If confirmation is interrupted after broadcast, retry the same workflow key and transaction; never send a second payment.
Webhooks
Receive signed events 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 & recovery
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. - • Emergency stop:
POST /v1/paniccancels managed activity where possible and revokes the calling key. It does not automatically close positions or revoke existing token allowances. - • Status:
GET /v1/status(no auth needed) returns service health, API/MCP compatibility, and bounded freshness.
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
Felix MCP 2.0.110 is a verified public npm release. Python 2.1.1 and TypeScript 2.1.0 remain private, contract-tested source artifacts and are not public-registry packages.
pip install /absolute/path/to/felix-python
from felix import Felix
felix = Felix("fk_...")
felix.buy("BTC", usd=50) # owner-authorized real-money order
result = felix.backtest(strategy, markets=["BTC"], interval="1h", bars=500)
job = felix.start_backtest(strategy, markets=["BTC"], bars=500)
status = felix.backtest_operation(job["operation_id"])
# Live prediction markets require Felix(..., polymarket_signer=local_signer).npm install /absolute/path/to/felix-ts
import { Felix } from "felix-sdk";
const felix = new Felix("fk_...");
await felix.buy("BTC", 10); // owner-authorized real-money order
const result = await felix.backtest(strategy, { markets: ["BTC"], interval: "1h", bars: 500 });
const job = await felix.startBacktest(strategy, { markets: ["BTC"], bars: 500 });
const status = await felix.backtestOperation(job.operation_id);For AI agents, start with the compact contract: felix.trade/llms.txt
For the complete agent guide: felix.trade/llms-full.txt
Real-money infrastructure for AI agents. Not a brokerage. Not financial advice.