# Felix API v2: Full Agent Reference Compact operating contract: https://felix.trade/llms.txt Base URL: https://api.felix.trade Runtime status: https://api.felix.trade/v1/status Human-readable service status: https://felix.trade/status Machine-readable agent index: https://felix.trade/agent-index.json Felix is non-custodial real-money trading infrastructure for agents. Send `Authorization: Bearer fk_` on authenticated requests. Use `llms.txt` for the minimum safe operating loop. Use this file for detailed endpoint families, money movement, venue-specific rules, and recovery. Public runtime status is authoritative for service health and client compatibility. Instrument availability is authoritative only when returned by search/preview at the time of action. The Felix docs define the public request and response contract. ## Getting started and owner registration Owner registration is live. Felix MCP 2.0.110 is public on npm. After reviewing the terms, run the pinned guided onboarding command, reconnect, and read `felix://getting-started`. The workflow creates the client-owned key locally when absent and proves control by signature without printing the owner, launcher, or recovery secret. The same guided command creates and authenticates the encrypted local recovery file automatically. No follow-up terminal command or copy/paste is required. After reconnect, call `get_custody_recovery_status` and require `ready:true` before funding; the tool returns status only and exposes no recovery material. MCP 2.0.96+ namespaces persisted child selection to the calling client process. Reconnects inside the same Claude/Codex process restore only that process's child. Another chat, test, or terminal cannot overwrite it, and a genuinely new client starts on the launcher. Verify `get_status.mcp.active_account_id` before money workflows and call `use_child_account` explicitly when needed. ```text POST /v1/register/challenge {owner_address} -> {message, nonce, expires_at, legal_bundle_version} sign `message` locally with that owner key (EIP-191 / personal_sign) POST /v1/register {message, signature, accept_terms:true, legal_version:"2026-08-30"} -> {account_id, api_key, ...} # api_key is shown exactly once ``` Rules that matter: - The guided flow generates the owner key locally. It controls every dollar the account will ever hold and cannot be recovered by Felix. Require the automatic encrypted recovery status to be ready before funding. - The account is permanently bound to the address that signed. One account per owner address. - The issued key is `read`+`trade` but NOT live yet. Live is a separate owner-signed grant (`/v1/keys/live/prepare` + `/submit`) that is only possible once a venue is genuinely onboarded on-chain. Registration cannot shortcut it, by design. - Registration moves no funds. Wallet deployment happens later. - Registration, API-key minting, and an unfunded account reservation create no on-chain object and spend no chain gas. The first `create_account` call returns a Polygon deposit address; deposit at least the returned $5 minimum and retry the exact same key. Only then does Felix activate the policy wallet and cover its initial gas. This grants Felix no wallet ownership or withdrawal authority. - The signed challenge binds legal bundle `2026-08-30`. Review https://felix.trade/legal before acceptance; stale supplied versions fail. - Challenges are single-use and expire in 10 minutes; registration is rate-limited per IP. The normal path is `create_account` with one stable idempotency key. Advanced custom signers should follow the complete Safe validation and signing sequence in `felix://getting-started`. ### Autonomous Polymarket wallet Interactive Polymarket orders use the local client signer. Background live agents use a distinct deterministic venue-scoped wallet. Read both identities with `get_polymarket_wallet`, then call `fund_polymarket_agent_wallet` with an exact pUSD amount and one stable idempotency key. Felix deploys the scoped wallet and installs only the configured pUSD/CTF exchange approvals; callers do not supply arbitrary approval calldata. Resolved agent positions redeem back into that same scoped wallet so winnings remain available for the next cycle. A checkpoint is persisted before any redemption submission. If the result is `reconcile_required`, observe the existing intent and do not create a replacement close. A stop loss is optional; Polymarket has no Felix server-side stop order, so a strategy may manage its own exit or hold an event position through resolution. ## Authority and controls - `read`: market data and the key's own account state. - `trade`: bounded real-money orders only when owner-authorized. - `manage`: owned child accounts, keys, onboarding, and funding preparation. - `transfer`: withdrawal and money-movement workflows. - Token prefixes do not reveal authority. All new tokens start with `fk_`. - Every executed order uses real money and requires owner-authorized live access. - Raw keys appear once at mint time; idempotent replay is redacted. - The owner private key never goes to Felix. Sign prepared messages locally. - Honor `Retry-After` on 429; a throttle is not a revoked credential. ### Custody and contract boundary - The policy wallet uses canonical Safe v1.3.0 core contracts (formerly Gnosis Safe): the Safe singleton, proxy, and proxy factory are not Felix-authored. - Autonomous prediction-market execution uses Felix-authored `HubScopedModuleV3`. Safe does not audit, approve, or guarantee this module. - The user remains the Safe owner. The module cannot replace the owner, change the threshold, call arbitrary targets, choose arbitrary recipients, send native value, or use delegatecall. - Its authority is restricted to fixed assets, reviewed venue contracts, exact short-lived orders, immutable recipients, owner-signed caps, and expiry. - Venue-scoped execution signing enforces the exact prepared action and the owner-approved mandate. The owner private key remains client-side. - `POST /v1/panic`, module pause, and on-chain allowance revocation are distinct controls. Pausing the module does not revoke an ERC20/ERC1155 allowance that was already granted to a reviewed venue; the owner must revoke it on-chain. - The module has no independent smart-contract audit. Keep beta caps low and retain a tested owner-key recovery path. ## Instruments and trading Never invent an instrument identifier. Use MCP `search_markets` for fuzzy phrase-to-candidate discovery. Use `list_markets` and follow `next_cursor` until `complete:true` for deterministic complete venue enumeration, then copy the returned canonical instrument exactly. `preview_order` is the authoritative per-instrument source for live minimum, collateral, leverage, liquidity, fees, and auto-funding requirements. ```text BTC, ETH, SOL crypto/perp resolver stock:NVDA stock option:BTC-YYYYMMDD-STRIKE-C option pm: prediction market ``` ```text GET /v1/instruments?q=&kind=&limit= GET /v1/quotes/{instrument} GET /v1/orderbook/{instrument} GET /v1/funding/{instrument} GET /v1/options/{underlying} POST /v1/orders/preview POST /v1/orders POST /v1/orders/batch DELETE /v1/orders/{order_id} POST /v1/quotes/make POST /v1/positions/{position_id}/close ``` Order body: `{instrument,side,size_usd,type?,limit_price?,reduce_only?}`. Preview before live execution and obey `min_live_size_usd`, liquidity, fee, and round-trip risk fields. Use returned canonical IDs for reconciliation. Batch requests use explicit top-level `mode:"live"`. Each item receives an independent idempotency identity and processing stops after the first failure. ## Exit plans ```text PUT /v1/positions/{position_id}/exit-plan GET /v1/positions/{position_id}/exit-plan DELETE /v1/positions/{position_id}/exit-plan GET /v1/exit-plans ``` Plans accept stop-loss, take-profit, trailing stop/activation, break-even, and maximum holding time. They are monitored reduce-only exits, not guaranteed-price venue-native orders. ## Accounts and keys ```text GET /v1/accounts POST /v1/accounts GET /v1/keys DELETE /v1/keys/{key_id} POST /v1/keys/live/prepare POST /v1/keys/live/submit GET /v1/keys/live DELETE /v1/keys/live/{key_id} ``` `POST /v1/accounts` requires an existing manage key, `accept_terms:true`, and an idempotency key. Send `legal_version:"2026-08-30"` or omit it to accept the current server version. Felix stores the exact version and application-encrypted acceptance time/channel. It creates an isolated zero-fund child and returns a one-time read-only onboarding bootstrap. Use `account_id` only for children owned by the managing parent. Live-key prepare returns an exact message for owner `personal_sign`; submit verifies the owner and single-use nonce before returning a live key once. ## Client-owned wallet and policy ```text POST /v1/wallet/onboarding/init POST /v1/wallet/onboarding/deploy POST /v1/wallet/onboarding/complete GET /v1/wallet/onboarding/{onboarding_id} POST /v1/wallet/migration/init POST /v1/wallet/migration/deploy POST /v1/wallet/migration/gas POST /v1/wallet/migration/confirm POST /v1/wallet/policy/prepare POST /v1/wallet/policy/submit ``` Onboarding and policy messages bind owner, fixed home address, per-operation, daily, lifetime, and delegation limits. Pause, resume, and renew are owner-signed. The account-level per-operation, daily, and lifetime ceilings are immutable once the account is created. `update_wallet_policy` supports pause, resume, renew, and lockdown; it cannot edit those ceilings. Existing live-key caps are changed by revoking and minting a replacement within the same account ceiling. Higher account ceilings require a new account and an ordinary withdrawal/deposit migration. This prevents an API key, manager, or Felix from escalating an existing account's signed authority. ## Venue onboarding ```text POST /v1/derive/onboarding/prepare POST /v1/derive/onboarding/submit GET /v1/derive/onboarding POST /v1/wallet/hyperliquid/onboarding/init POST /v1/wallet/hyperliquid/onboarding/complete GET /v1/wallet/hyperliquid/onboarding/{onboarding_id} ``` ## Client-signed prediction-market flow ```text POST /v1/wallet/polymarket/deploy GET /v1/wallet/polymarket POST /v1/wallet/polymarket/approvals/prepare POST /v1/wallet/polymarket/approvals/submit POST /v1/orders/polymarket/prepare POST /v1/positions/{position_id}/polymarket/prepare POST /v1/orders/polymarket/checkpoint POST /v1/orders/polymarket/submit POST /v1/orders/polymarket/commit GET /v1/orders/polymarket/intents/{intent_id} POST /v1/wallet/polymarket/withdrawal-grant/prepare POST /v1/wallet/polymarket/withdrawal-grant/submit POST /v1/wallet/polymarket/withdrawal-grant/revoke ``` Do not send a generic live order for this market class. Prepare, client-sign the exact request, checkpoint the order hash, relay the signed request through `/submit`, then commit for independent reconciliation. ## Funding and withdrawals ```text GET /v1/wallet/funding/balances POST /v1/wallet/funding/prepare POST /v1/wallet/funding/confirm POST /v1/wallet/funding/return/prepare POST /v1/wallet/funding/return/submit POST /v1/wallet/funding/return/confirm POST /v1/wallet/funding/fees/prepare POST /v1/wallet/funding/fees/confirm POST /v1/fund POST /v1/bring-home GET /v1/withdrawal-addresses POST /v1/withdrawal-addresses/prepare POST /v1/withdrawal-addresses POST /v1/withdrawal-addresses/{addr_id}/confirm POST /v1/withdraw/prepare POST /v1/withdraw/submit POST /v1/withdraw ``` Prefer `/v1/wallet/funding/*` and owner-signed withdrawal prepare/submit. Execute only the exact prepared transactions and fee transfer, preserve the intent token, and confirm with exact transaction hashes. Prepare the withdrawal address, sign its exact account/address/chain/expiry message with the client-held owner key, then submit it. It activates immediately; elapsed time never grants withdrawal authority. The legacy confirm route re-authorizes old entries with the same owner signature. The plain `/v1/withdraw` route is deprecated compatibility behavior. USDC.e withdrawals deliver bridged USDC.e on Polygon at contract `0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174`. Many centralized exchanges do not accept that exact token. Unless an exchange explicitly confirms support, withdraw to a self-custody Polygon wallet first and convert to native Polygon USDC before depositing to the exchange. ## Strategies and backtests ```text POST /v1/strategies/generate POST /v1/backtests POST /v1/backtests with {"async":true} GET /v1/backtests/operations/{operation_id} POST /v1/backtests/operations/{operation_id}/resume POST /v1/agents GET /v1/agents/{agent_id} POST /v1/agents/{agent_id}/stop ``` Backtesting is read-only. It never deploys an agent, places an order, signs a transaction, or changes a balance. Deployment is always a separate real-money mutation with an explicit budget, owner authorization, and hard risk limits. Manual authoring does not depend on an LLM or generation quota: ```text MCP resource: felix://strategy/ctx-api MCP resource: felix://strategy/examples MCP fallback: get_strategy_guide(section="all") strategy shape: {"config":{"code":"def think(ctx): ..."}} ``` `generate_strategy` is optional and consumes provider-token budget. Backtests themselves do not consume that generation budget. Synchronous contract: ```json POST /v1/backtests Idempotency-Key: stable-logical-test-key { "strategy": {"config": {"code": "def think(ctx):\n return {'action':'hold','reason':'waiting'}"}}, "name": "BTC certification", "markets": ["BTC"], "interval": "1h", "bars": 500, "capital": 100, "detail": "summary" } ``` Use the same idempotency key only for the exact same logical request. Exact replays return the cached result and do not consume another daily workflow. Durable contract: ```text start_backtest(...) -> persist operation_id get_backtest_operation(operation_id) until completed|failed resume_backtest_operation(operation_id) only after an expired worker lease POST /v1/backtests with body field async:true and Idempotency-Key fxbt_<32 hex> GET /v1/backtests/operations/{operation_id} POST /v1/backtests/operations/{operation_id}/resume ``` Completed start/resume replays return the terminal result. Unknown or foreign operation IDs return 404 and do not disclose another account's job. Bounds are rejected, never clamped: ```text markets: maximum 4 intervals: 1m, 5m, 15m, 1h, 4h, 1d bar caps by interval: 20000, 25000, 30000, 45000, 15000, 12000 minimum bars: 20 years: use bars for 1m; wider intervals support up to 40 years at 1d capital: 10 to 1000000 USD detail: summary | full ``` Result checks before deployment: ```text performance.execution_ms and performance.cache_hit result.metrics: return, drawdown, fees, trade count result.equity_curve and result.monthly_returns result.methodology.historical_data == "real" result.methodology.limitations is present result.historical_validity.status result.historical_validity.live_only_signals ``` `historical_validity.status == "degraded"` means at least one live-only signal could not be replayed. Treat that result as incomplete, not proof. Real history does not remove look-ahead, selection, overfitting, liquidity, or execution-gap risk. Live agents inherit both originating key caps and owner wallet policy. ## Programmatic research and options flow ```text GET /v1/research/{symbol}?interval=1h&bars=750 GET /v1/markets/screener?kind=&limit= GET /v1/markets/earnings?limit= GET /v1/markets/fundamentals/{symbol} GET /v1/equity-options/{symbol}?max_expiries=&limit= POST /v1/options-flow ``` These routes are deterministic, bounded provider reads and never place orders. Equity-option chains and options flow are delayed decision support, not tape-level sweep detection. The response says `data_class: delayed_decision_support`. Tradeable Derive crypto options remain under `GET /v1/options/{underlying}`. Free/Pro/Scale limits are returned by `GET /v1/me/subscription`. The isolated research bucket allows 12 calls/minute on Free, 60 on Pro, and 180 on Scale. Cold provider reads are bounded to 20–25 seconds; cached reads are faster. Honor `Retry-After` on every `429`. ## Reporting, webhooks, and feedback ```text GET /v1/balances GET /v1/deposit-address GET /v1/positions GET /v1/portfolio GET /v1/fills GET /v1/pnl GET /v1/insights GET /v1/webhooks POST /v1/webhooks DELETE /v1/webhooks/{webhook_id} POST /v1/webhooks/test POST /v1/feedback GET /v1/feedback GET /v1/feedback/{feedback_id} ``` Webhook URLs must be public HTTPS and events are signed over the raw body. Never put secrets or signed payloads in feedback. ## Live market-data WebSocket Normalized Hyperliquid, Polymarket, and Derive quotes, books, and trades stream from `wss://api.felix.trade/v1/stream`. ```text POST /v1/stream/tickets with Authorization: Bearer fk_ open websocket_url with subprotocol felix.market.v1 send within 5 seconds: {"op":"authenticate","ticket":""} wait for ready send: {"op":"subscribe","request_id":"prices-1","subscriptions":[...]} ``` Ticket properties: - a `read`-scoped key is required to mint one; - the opaque ticket expires after 30 seconds and can be consumed exactly once; - the key is checked again for ownership, scope, and active state; - API keys never belong in WebSocket URLs or messages. Valid subscription channels are `quote`, `book`, and `trades`. Instruments must be canonical values returned by `/v1/instruments`. A subscription batch is atomic: if one item is invalid or capacity is exhausted, none of that batch is applied. The `subscribed` response returns IDs accepted by `unsubscribe`. Every market event includes `sequence`, `source_time_ms`, `received_at`, and `source_lag_ms` where the venue supplies timestamps. Quotes and books are latest-state streams, so a slow consumer can receive coalesced state instead of every intermediate update. Trades use a bounded ordered queue and Felix closes the connection before silently dropping them. After reconnect, any sequence gap, or `resync_required`, fetch a fresh REST snapshot before making a stateful decision. Sessions expire after 30 minutes and heartbeat at least every 15 seconds. Reconnect with exponential backoff and jitter, request a fresh ticket, then resubscribe and resnapshot. Browser connections require an allowlisted Origin; CLI and server clients may omit Origin. The WebSocket is read-only. It never accepts orders, signatures, account IDs, private state, or provider credentials. Orders continue through preview and the normal idempotent execution routes. This is low-latency market data, not a claim that venue execution or blockchain settlement is sub-second. ## Platform and emergency ```text GET /v1/health GET /v1/ready GET /v1/status GET /v1/fees GET /v1/tiers GET /v1/me/subscription POST /v1/me/subscription/prepare POST /v1/me/subscription/confirm POST /v1/referrals POST /v1/panic ``` `GET /v1/status` is intentionally minimal: service, status, API version, minimum MCP version, and bounded freshness fields only. Authenticated `GET /v1/metrics` documents the per-response request ID, server latency, and retry fields available to clients; it does not return platform diagnostics. Errors use `{error:{code,message,hint},_meta:{http_status,request_id,retry_after}}`. Standard statuses include 400, 401, 403, 404, 409, 422, 429, 500, 502, 503, and 504. The live OpenAPI is authoritative for exact request schemas. The planned Free and Pro tiers use the same owner-control boundaries. Pro is currently specified at $20 for one 30-day period and adds throughput, deeper research, larger options-flow scans, more backtests, and a small Felix fee discount. Programmatic renewal prepares one exact native Polygon USDC transfer to the fixed treasury; the owner validates and signs locally, then confirmation verifies the receipt and atomically activates the period. Auto-renew is off. MCP wraps this as `upgrade_subscription(plan="pro", idempotency_key="...")`. ## Operational rules for agents These rules prevent the failure modes that actually lose money. Follow them exactly. 1. Recommended loop: `GET /v1/status`, search instruments, `GET /v1/quotes`, `POST /v1/orders/preview`, place the order, then verify through `GET /v1/positions` and `GET /v1/fills` before deciding anything else. 2. An order ERROR can accompany a REAL fill. 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}`; elsewhere read positions and fills. Retrying an ambiguous "failure" without reconciling is how agents double-fill. 3. Idempotency keys are durable workflow identities, not per-request noise. Resume an interrupted money workflow with the SAME key; it replays checkpoints instead of re-moving funds. Start a NEW key only for a new intent. Never rotate a key to "get past" an ambiguous result. 4. Timeouts on money workflows mean "still settling", not "failed". The hint in the error says whether to re-poll with the same key or to stop. Check balances before any second attempt. 5. `429` means throttled, not revoked. Honor `Retry-After` and keep the key. 6. Preview responses carry `min_live_size_usd`, fees, and liquidity: read them instead of guessing venue minimums. ## Prediction-market order rules - Live prediction-market orders use the client-signed flow (prepare, local sign, checkpoint, submit, commit). The generic `/v1/orders` route refuses this market class for live execution by design. - Minimums: 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. Top-ups of an existing outcome may go as low as $1.00. - Balance rule: the venue accepts an order only when the wallet covers the order PLUS its fee estimate. The fee estimate 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, for example "about $2.17 total for this $2.05 order at 0.360 (fee estimate $0.12)". Fund to the stated total or reduce `size_usd`. - Multi-outcome ("family") markets trade normally, but close positions through the order book BEFORE the market resolves. Redemption of resolved multi-outcome positions is not yet self-serve; a resolved position is recoverable by support, not lost. - Sells of very small remainders can fall under the venue sell minimum; prefer closing positions whole. ## Funding lifecycle and fees - Funding a venue binds a durable network-fee obligation server-side. The network fee is a flat $1.00 per funding, so small fundings carry a high percentage cost: $10.00 costs $11.00 plus a small gas buffer. - The client checks the owner balance BEFORE binding anything and fails closed with exact numbers when the source cannot cover `amount + $1.00 + gas buffer`. Nothing is reserved on that failure. - If a funding workflow is interrupted, resume it with the SAME `idempotency_key`. Abandoned obligations self-clear on a timer in the common case; a wedged one returns `network_fee_unpaid` (409) and is a support fix, not something to retry around. - Cross-chain transfers below about $4 are unreliable on the final bridge leg and are rejected up front with an actionable message. ## Bring-home (returns) by venue - Prediction markets: single signed return flow; funds land on the owner wallet. - Crypto/perps: two stages inside one workflow key: venue withdrawal (the venue charges an expected $1.00 withdrawal fee; below $10 requires `allow_high_fee_loss:true`), then an automatic bridge to the owner wallet. - Options: TWO calls. The first executes the venue withdrawal, which lands in the owner wallet on the venue's own chain in about 2 minutes; the response says so and is honest that the money is not on the home chain yet. A second `bring_home` call with a NEW idempotency key detects the landed funds and bridges them home automatically. Arrivals below $4 stop on the intermediate chain, where funding flows can spend them directly; the response labels this state precisely. ## Error codes agents will actually see - `insufficient_owner_balance`: fund the owner wallet or reduce the amount; nothing was started. - `network_fee_unpaid` (409): a previous funding fee is unresolved; do not start new fundings for that venue, resume with the original key or ask support. - `clob_rejected_order`: the response's `venue_error` carries the venue's actual reason, usually the balance-plus-fee rule above. - `workflow_reconciliation_required`: a prior process may have submitted; verify balances and fills first, then resume with the SAME key. - `return_confirmation_timeout`: still settling; re-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 that. - `return_amount_too_small` / `return_output_too_small`: leave the balance where it is until it exceeds the stated minimum. - `client_upgrade_required`: upgrade the client build before live orders. ## Where is my money (one answer) Money can legitimately sit in several places: the owner wallet on the home chain (deposits, withdrawals), the owner wallet on an intermediate chain (bridge legs, sub-$4 remainders), a venue's own chain (a landed options withdrawal), each venue account, and open positions. Track it with ONE call: - API: `GET /v1/money`. MCP: `get_money_map` (same response). Both return a flat `locations` list where every entry says what the balance is for and exactly which call moves it, plus `total_usd`, a separated `gas` section (native token amounts, never conflated with spendable balance), a `how_to_move` cheat sheet, and an `unavailable` list: any source that cannot be verified is named and excluded from the total, never assumed zero. Prefer this over raw balance endpoints for money decisions. - Underlying detail endpoints remain: `/v1/balances` (venue accounts with reservations), `/v1/wallet/funding/balances` (owner wallets across chains), `/v1/positions`. Rule: if a balance source errors, treat that location as UNKNOWN and say so; never treat a failed read as zero. ## Latency profile - REST quotes, previews, and order books are sub-second. - On the production WebSocket certification run, steady source lag was 9/48 ms p50/p95 for Polymarket, 311/529 ms for Hyperliquid, and 159/163 ms for Derive. These are observed venue-to-Felix data latencies, not execution guarantees. - Order placement is dominated by one client-signed round trip plus the venue; the client caches venue credentials, tick metadata, and server time, so repeat orders on the same market are meaningfully faster than the first. - On-chain money movement confirms at chain speed: seconds for a transaction, one to a few minutes for a cross-chain leg. Poll with the same workflow key; the workflows poll internally every few seconds. Felix MCP 2.0.110 is a verified public npm release. Install the exact version while validating a new connection; do not use an unpinned tag. Owner registration and developer infrastructure are live. The retail trading app launches September 17, 2026. Python `felixtrade` 2.1.1 and TypeScript `felix-sdk` 2.1.0 remain private, contract-tested source artifacts and are not public-registry install targets. Browser chat is outside this developer release. Trading can lose all allocated capital. Scoped permissions reduce specific authority risks; they do not eliminate owner-key, contract/module, integration, venue, software, operational, or market risk. Risk disclosure: https://felix.trade/legal/risk Non-custodial infrastructure, not a brokerage or financial advice.