# Felix documentation > Research markets, build a strategy with AI, and run trading agents on Polymarket, Hyperliquid, Lighter, and Derive from one balance. This file is every page of https://felix.trade/docs in reading order. The compact index is https://felix.trade/llms.txt. API reference generated from Felix API 2.0.221. --- # Overview: Felix documentation Source: https://felix.trade/docs > Research markets, build a strategy with AI, and run trading agents on Polymarket, Hyperliquid, Lighter, and Derive from one balance. Felix lets you research markets, turn an idea into a trading strategy with AI, test it on historical data, and run it as an agent that trades for you. Agents trade on third-party venues from accounts that belong to you, inside limits you set. You can use Felix in the app or through the REST API at `https://api.felix.trade`. ## Where to start | If you want to | Read | | --- | --- | | Open an account and run your first agent | [Get started](https://felix.trade/docs/guides/get-started) | | Understand where your money is and who controls it | [How Felix works](https://felix.trade/docs/overview/how-felix-works) | | See what you can trade and the rules on each venue | [Venues](https://felix.trade/docs/overview/venues) | | Know what everything costs | [Fees](https://felix.trade/docs/overview/fees) and [Plans](https://felix.trade/docs/overview/plans) | | Add money or take it out | [Deposits and withdrawals](https://felix.trade/docs/guides/deposits-and-withdrawals) | | Set limits and keep agents under control | [Run agents](https://felix.trade/docs/guides/run-agents) | | Build on the API | [API quickstart](https://felix.trade/docs/guides/api-quickstart) and the [API reference](https://felix.trade/docs/api/overview) | ## What Felix is not Felix is software. It is not a broker, an exchange, a bank, or an investment adviser, and nothing it shows you is a recommendation. Trading can lose all of your money. The rules that apply are in the [Terms of Service](https://felix.trade/legal/terms), and the main risks are in the [Risk Disclosure](https://felix.trade/legal/risk). ## Status and changes - [Felix status](https://felix.trade/status) shows whether each part of the service is working. - [Changelog](https://felix.trade/changelog) lists what changed and when. - [llms.txt](https://felix.trade/llms.txt) is a plain-text version of these docs for AI tools. --- # Overview: How Felix works Source: https://felix.trade/docs/overview/how-felix-works > Your balance, agent capital, agents, and venues, and how money moves between them. Felix has four parts: your balance, your agent capital, your agents, and the venues they trade on. ## Your balance Your balance is USDC on the Arc network, held in a Safe smart-contract wallet. Your owner key is the only owner of that wallet. The key is created on your device, and Felix is designed never to receive it. Money leaves your balance only when you sign for it: to withdraw, to pay for a plan, or to give money to your agents. ## Agent capital Agents never spend from your balance directly. When you want agents to trade, you sign an allocation that moves an amount from your balance into **agent capital**. Agent capital is a set of accounts that belong to you alone: - an **agent treasury**, which holds money that is not on a venue yet; and - one account on each venue your agents use, such as a Polymarket wallet, a Hyperliquid account, or a Lighter account. The keys for these accounts are held in a sealed signing environment called an enclave (see [Security](https://felix.trade/docs/overview/security)). After you allocate, Felix moves money between your agent treasury and your venue accounts on its own, so each agent has what it needs when it trades. The signing enclave is designed to refuse sending agent capital anywhere else. ## How Felix moves agent money A planner checks every account about every 30 seconds. 1. Each running agent has a target amount on each venue it trades: its budget, divided by its leverage on perpetual venues. 2. If a venue is below 80% of its target, the planner funds it from the agent treasury. 3. If the treasury is empty, the planner moves free money from another venue that holds more than its share. It uses fast venues first and Lighter last. Money that backs an open position is never moved. 4. Money above an agent's budget, or on a venue no agent uses, goes back to the treasury. The planner waits 30 minutes after any money move on a venue before doing this, so it does not send money back and forth. An agent whose strategy asks for money only when it is about to trade (with `ctx.prepare`) has no standing target. It is funded when it asks. Funding a venue takes about 30 to 45 seconds for Hyperliquid and Polymarket and 3 to 6 minutes for Lighter. Returning money from Lighter takes about a minute, and Lighter charges $1 for it. ## Agents An agent is a strategy written in Python that runs on Felix's servers. On each cycle it reads market data and its own positions and decides to buy, close, or hold. Felix checks every decision against your limits before anything is sent to a venue. Agents keep running when you close the app, and they continue automatically after Felix restarts its servers. Read [Run agents](https://felix.trade/docs/guides/run-agents) for limits, pauses, and what happens when you stop one. ## Venues Felix trades on Polymarket (prediction markets), Hyperliquid and Lighter (perpetual futures), and Derive (options). Each venue has its own minimums, fees, and maintenance windows. See [Venues](https://felix.trade/docs/overview/venues). ## What you see in the app The app adds up your balance, agent treasury, venue accounts, money in transit, and open positions. These come from several sources that update at different speeds. When a source cannot be read, Felix shows it as unavailable instead of counting it as zero. --- # Overview: Venues Source: https://felix.trade/docs/overview/venues > What you can trade on Polymarket, Hyperliquid, Lighter, and Derive, each venue's minimums and fees, and what happens when one is down. Felix trades on four venues. Each one has its own rules. Felix enforces them before an order is sent, so an order that breaks a rule is refused with a clear reason instead of failing at the venue. | Venue | What you trade | Minimum order | Leverage in Felix | | --- | --- | --- | --- | | Polymarket | Prediction markets | $1 and the market's minimum size (usually 5 shares) | None | | Hyperliquid | Perpetual futures on crypto and stocks | $10 | 1x to 20x | | Lighter | Perpetual futures on crypto | $10 | 1x to 20x | | Derive | Crypto options | Set by the market | None | Leverage is also capped by each market's own maximum on the venue, which is often lower than 20x. ## Polymarket Each share pays $1 if its outcome happens and $0 if it does not. Prices run from $0.01 to $0.99. - **Orders.** Agents can take the best available price or post a limit order that rests on the book for up to 30 seconds and is then cancelled if it has not filled. A limit order must be for at least 5 shares. If the price moves while the order is on its way, Felix places it one tick below the new best ask so it still rests instead of crossing. - **Fees.** Polymarket charges takers `shares x rate x price x (1 - price)`. The rate is 0.07 for crypto markets, 0.03 to 0.05 for sports, 0.04 for politics, and 0 for geopolitics. At a price of $0.50 on a crypto market, that is $0.0175 per share, or 3.5% of the order. Makers pay nothing. Felix records the exact fee Polymarket charged in your profit and loss. - **Sports orders** are held by Polymarket for a few seconds before they reach the book. - **Resolution.** When a market resolves, Felix collects the payout automatically and adds it to the same wallet, including for agents you have stopped. A losing position settles at $0. - **Both sides.** If an agent holds both outcomes of the same market, Felix merges matching pairs back into $1 each, without selling into the book. - **Near the end.** A losing position close to resolution often has no buyers. Felix keeps trying to sell it and otherwise lets it settle. ## Hyperliquid Perpetual futures on crypto and on stocks, settled in USDC. Positions pay or receive funding every hour. - **Fees.** Hyperliquid's base rate is 0.045% for takers and 0.015% for makers, lower at higher monthly volume. - **Leverage.** Felix sets the leverage you chose for an agent before its first order on each market. ## Lighter Perpetual futures on crypto. Lighter is available to agents only. Direct API orders do not route to it. - **Fees.** Felix opens standard Lighter accounts, which pay no trading fees. - **Moving money.** Funding Lighter takes 3 to 6 minutes. Returning money takes about a minute and Lighter charges $1 for it. - **Order size.** Orders are rounded down to the market's size step. For BTC that step is 0.00001 BTC, so an order needs a little more than $10 to stay above the $10 minimum after rounding. ## Derive Crypto options. Option books can be thin, and an option can expire worthless. Selling options can lose far more than the premium you receive. Derive charges its own fees, shown in each order preview. ## When a venue is down Venues go into maintenance and have outages. While a venue is down: - Agents cannot open, close, or change positions on it. Stop-losses and exits on that venue cannot fire until it is back. - Agents keep trading on the venues that are working. A problem on one venue does not block orders on the others. - If you allowed an agent to trade the same market on Hyperliquid and Lighter, new orders aimed at the venue that is down go to the other one, with the same side and size and leverage capped at that venue's maximum. Felix never sends an order to a venue or market you did not allow. - Felix values a position it cannot price at its worst case when it checks your loss limit. For a perpetual, that is its last known price moved 10% against you, or its full size if no recent price exists. For a prediction-market position, it is what you paid. --- # Overview: Fees Source: https://felix.trade/docs/overview/fees > What Felix charges on trades, what venues and bridges charge, and how agent fees are paid. You pay three kinds of cost: Felix's trading fee, the venue's own fees, and the cost of moving money between networks. Every order preview shows the Felix fee for that order before anything is sent. ## Felix trading fees Felix charges a percentage of each filled trade's size. A basis point (bp) is 0.01%. | Market | Fee | On a $100 trade | | --- | --- | --- | | Crypto and stock perpetuals | 8 bps | $0.08 | | Spot | 10 bps | $0.10 | | Prediction markets | 20 bps | $0.20 | | Options | 30 bps plus $0.10, capped at 12.5% of the option's price | $0.40 | You pay the fee only when a trade actually fills. A rejected or unfilled order costs nothing. These rates apply to agents in the app. Orders placed through the API get 1 bp off on Pro and 2 bps off on Max. Every order preview shows the exact fee in its `fee` field. ## How agent fees are paid Agents do not pay a fee on every trade. Felix adds up what your agents owe and pays it from your agent capital to Felix in one transfer, once you owe at least $0.50 or the oldest unpaid fee is 30 minutes old. Felix never takes these fees from your balance, and it never lets you go into debt for them. ## Venue fees Venues charge their own fees on top of Felix's. Felix does not set or receive them. | Venue | Fee | | --- | --- | | Polymarket | Takers pay `shares x rate x price x (1 - price)`; the rate is 0.07 for crypto, 0.03 to 0.05 for sports, 0.04 for politics, 0 for geopolitics. Makers pay nothing. | | Hyperliquid | 0.045% taker and 0.015% maker at the base volume tier. | | Lighter | None on the standard accounts Felix uses. | | Derive | Set by Derive and shown in the order preview. | Perpetual positions also pay or receive funding while they are open. ## Moving money | Action | Cost | | --- | --- | | Deposit | Relay's conversion and bridge cost, shown in the quote before you send | | Withdraw to Base, Arbitrum, Ethereum, or Polygon | Relay's cost, at most 1% of the amount, shown before you sign | | Return agent money from Lighter | $1, charged by Lighter | | First transfer out of a new Hyperliquid account | About $1, charged once by Hyperliquid | Felix pays the network gas for your transactions. You never need to hold ETH or another gas token. ## Small balances On a small balance, these costs add up to a large share of what you hold, and venue minimums (such as $10 on Hyperliquid and Lighter, and 5 shares on Polymarket) can make some orders impossible. As a rough guide, keep at least $20 per venue an agent trades. --- # Overview: Plans Source: https://felix.trade/docs/overview/plans > What Free, Pro, and Max include, how to pay, and how auto-renew works. Every plan can trade with real money. Plans differ in how many agents you can run, how much AI you can use each day, and which research tools you get. | | Free | Pro | Max | | --- | --- | --- | --- | | Price | $0 | $20 a month | $99 a month | | Agents running at once | 3 | 10 | 50 | | AI usage per day | 300,000 tokens (600,000 after your first deposit) | 1,000,000 tokens | 3,000,000 tokens | | Backtest history | Up to 1 year | Full history | Full history | | Walk-forward and robustness tests | No | Yes | Yes | | Price alerts | No | Yes | Yes | | Agents that react to every market move | No | Yes | Yes | On Free, agents run on a timer. On Pro and Max, an agent can also wake up the moment its market moves. AI usage resets at midnight UTC. When you reach the limit, chat stops until the next day; your agents keep trading. ## Paying for a plan You pay from your Felix balance in the app. You sign one payment and the plan starts immediately. Plan payments go to Felix, not to a venue. ## Auto-renew If you turn on auto-renew, you approve Felix to take the plan price once per billing period from your balance, for up to twelve periods. Felix cannot take more than the price you approved. If the price goes up, renewal stops until you approve the new price. To stop renewing, turn off auto-renew in Settings. Your plan stays active until the end of the period you already paid for. If a renewal fails because your balance is too low, Felix tries again for up to three days, then your account moves to Free. ## Changing or cancelling Moving to Free does not stop your agents. If you have more agents running than Free allows, you cannot start new ones until you are back under the limit. Plan payments are not refunded except where the law requires. --- # Overview: Security Source: https://felix.trade/docs/overview/security > Who holds the keys, what Felix can sign without asking you, the limits you control, and how to stop everything. Felix is designed so that no one at Felix, and no single server, can send your money wherever it wants. This page explains how. The legal version is the [Custody and Authority Notice](https://felix.trade/legal/custody). ## Your owner key Your owner key controls your balance. In the app it is a recovery phrase created in your browser and stored encrypted on your device. If you turn on account sync, an encrypted copy that only your passkey can unlock is stored with Felix so you can sign in on another device. Felix does not hold the key needed to decrypt it. Back up your recovery phrase from Settings. Felix cannot recover a lost key, and support will never ask for it. ## Your balance Your balance sits in a Safe smart-contract wallet whose only owner is your owner key. Withdrawals, plan payments, and allocations to agents each need a signature from that key. ## Agent capital and the signing enclave Money you allocate to agents moves into accounts created only for you: an agent treasury and one account per venue. Their keys live inside an AWS Nitro Enclave, a sealed environment that runs exactly one reviewed version of Felix's signing code. The key that unlocks them can only be used by that exact code, and our ordinary servers never see the private keys. Before signing anything, the enclave checks it against fixed rules: - money can move only between your own agent treasury and your own venue accounts, or back to your balance; - the only payment out is Felix's fee for your agents' trades; - every action must be a known type, to a known contract, within size limits; and - orders must fit the limits you signed. Every change to the enclave's rules goes through a security review and an attack test before it is switched on for real money. ## Who controls trading limits You set every trading limit, and Felix cannot raise them for you. Before agents trade real money, you sign a mandate that sets what they may do and how much they may risk. Felix checks every order against it, and the enclave checks it again before signing. Each agent also has its own limits: - **Budget:** the most money the agent may use. - **Maximum position:** the largest single position it may hold. - **Daily loss limit:** the agent can only open a position that fits in what is left of this limit for the day (UTC). Closed losses from all your agents count toward it, so once they reach the limit, the agent opens nothing new until the next day. You can change these limits by stopping the agent, editing it, and starting it again. ## API keys API keys are separate from your owner key. Each key has scopes, such as `read`, `trade`, `manage`, or `transfer`, and can carry its own spending limits. A trade key cannot withdraw money to an address you have not approved. If a key leaks, revoke it at once; until you do, it can cause losses within its scopes. ## Emergency controls | Control | What it does | | --- | --- | | Pause or stop an agent | That agent places no new orders. Its open positions stay open. | | Kill switch | No agent on your account can open a new position. Exits and closes keep working. | | Panic (`POST /v1/panic` with `"confirm": true`) | Turns on the kill switch, pauses every agent, revokes every API key on the account, cancels open orders, and closes positions where it can. | None of these can revoke on-chain token approvals, cancel a transaction already sent to a blockchain, or close a position on a venue that is down. After using one, check your positions and balances. ## Reporting a problem If you find a security issue, email legal@felix.trade with the details and steps to reproduce it. Do not include private keys, recovery phrases, or full API keys. --- # Guides: Get started Source: https://felix.trade/docs/guides/get-started > Open an account, add money, build a strategy with AI, test it, and run your first agent. This takes about 15 minutes. You need an email address and something to deposit, such as USDC on Base or Solana. ## Create your account 1. Go to felix.trade and choose **Get started**. 2. Enter your email and the 6-digit code we send you. If you sign in with Google, you also enter the code. 3. Accept the [Terms](https://felix.trade/legal/terms). This also confirms you have read the Privacy Policy, Risk Disclosure, and Custody and Authority Notice. ## Set up your wallet Felix creates your owner key in your browser. This key controls your balance. Felix is designed never to receive it. 1. When asked, approve the passkey. This keeps an encrypted copy of your key so you can sign in on other devices. 2. Open **Settings**, then **Wallet security**, and write down your recovery phrase. Store it somewhere safe and offline. If you lose it and every device, your money cannot be recovered. ## Add money 1. Open **Deposit** and choose the token and network you are sending from. 2. Send the exact asset to the address shown, within 30 minutes. After 30 minutes the address closes; anything sent to it later may not arrive. 3. Your balance updates when the deposit converts to USDC, usually within a few minutes. See [Deposits and withdrawals](https://felix.trade/docs/guides/deposits-and-withdrawals) for the full list of tokens and networks. ## Build a strategy Describe what you want in chat, in plain words. For example: ```text example request Buy the side of the BTC 15-minute Polymarket market that is underpriced by at least 3 cents. Spend at most $5 per trade and sell before the window closes. ``` Felix writes the strategy, checks that it runs, and shows you a draft with its rules and limits. Ask for changes until it matches what you meant. ## Test it Run a backtest from the draft. It replays the strategy on historical data and shows trades, profit and loss, and the worst drop. Read [Research and backtests](https://felix.trade/docs/guides/research-and-backtests) before trusting the numbers. ## Run it 1. Start in **paper** mode. The agent trades with simulated money against live prices, so you can watch it without risk. 2. When you are ready for real money, switch the agent to **live**. Felix asks you to set its budget, maximum position, and daily loss limit. If you have not given money to agents yet, use **Allocate to agents** on the Agent capital card and sign with your owner key. 3. Watch the agent's activity log. Every decision shows what it did and why. You can pause or stop an agent at any time. See [Run agents](https://felix.trade/docs/guides/run-agents) for what each control does. --- # Guides: Deposits and withdrawals Source: https://felix.trade/docs/guides/deposits-and-withdrawals > Which tokens and networks you can deposit from, how long a deposit address lasts, and how to withdraw. Your Felix balance is held in USDC on the Arc network. Deposits are converted to USDC on the way in, and withdrawals are converted to native USDC on the network you choose. Felix uses Relay for both and pays the network gas. ## Deposit 1. In the app, open **Deposit**. 2. Choose the token and network you are sending from. 3. Felix shows an address, the amount you will receive after conversion, and the minimum. 4. Send the exact token on the exact network shown, within 30 minutes. > **Warning: The address expires after 30 minutes** > If you send after the window closes, on the wrong network, or in a token that was not shown, the deposit may not be credited and may not be recoverable. Start a new deposit if your window has run out. Your balance updates once the conversion finishes, usually within a few minutes. A Bitcoin deposit waits for Bitcoin confirmations and can take longer. ### What you can deposit | Network | Tokens | | --- | --- | | Ethereum | USDC, USDT, ETH, WETH, DAI, USDe, PYUSD, APE | | Base | USDC, USDT, ETH, WETH, cbBTC, SOL | | Arbitrum | USDC, USDT, ETH, WETH, APE | | Optimism | USDC, USDT, ETH, WETH | | Polygon | USDC, USDT | | Solana | USDC, USDT, SOL, PYUSD, PENGU | | BNB Chain | USDC, USDT, BNB, USDe | | Avalanche | USDC, USDe | | HyperEVM | HYPE, USDe | | Bitcoin | BTC | | Abstract | PENGU | | ApeChain | APE | Tokens other than stablecoins are converted at the market price when the deposit arrives, so the USDC you receive can differ slightly from the quote. ## Withdraw 1. Open **Withdraw** and choose a network: Base, Arbitrum, Ethereum, or Polygon. You receive native USDC. 2. Enter the address and amount. The first time you use an address, you approve it with your owner key. 3. Review the amount you will receive and sign. Withdrawals can be from $5 to $10,000 at a time. Relay's cost is shown before you sign and is never more than 1% of the amount. Most withdrawals arrive within a few minutes. ## Money your agents are using Only your balance can be withdrawn directly. Money you gave to agents sits in your agent capital. To withdraw it, return it to your balance first: 1. Stop the agents that use it, or lower their budgets. 2. On the **Agent capital** card, move the money back to your balance. Money on Lighter takes about a minute and Lighter charges $1. Money that backs an open position cannot move until the position is closed. 3. Withdraw from your balance as above. ## When deposits and withdrawals pause Felix pauses deposits and withdrawals for a few minutes when it releases an update. A deposit that arrives during a pause is credited when it ends. A withdrawal cannot start during a pause; try again a few minutes later. --- # Guides: Run agents Source: https://felix.trade/docs/guides/run-agents > Set an agent's limits, understand what it will and will not do, and control it while it runs. An agent is a strategy that runs on Felix's servers and trades for you. It keeps running when you close the app, and it continues on its own after Felix restarts its servers. ## What an agent is allowed to trade When you deploy an agent, you fix which venues and markets it may trade. It cannot trade anything else. For prediction markets you can allow a single market, a rolling series (such as the BTC 15-minute markets), or every outcome of an event. If you allow the same perpetual market on both Hyperliquid and Lighter, the agent can keep trading on one while the other is down. See [Venues](https://felix.trade/docs/overview/venues#when-a-venue-is-down). ## Set its limits | Limit | What it does | | --- | --- | | Budget | The most money the agent may use. | | Maximum position | The largest single position it may open. | | Daily loss limit | How much the account may lose in closed trades today (UTC) before this agent stops opening positions. | | Leverage | 1x to 20x on Hyperliquid and Lighter, also capped by each market's own maximum. | The maximum position cannot be larger than the daily loss limit, and the daily loss limit cannot be larger than the budget. > **Note: The daily loss limit counts your whole account** > Closed losses from all of your agents count against every agent's daily loss limit. If one agent loses $8 today and another agent's limit is $10, the second agent can only open a position that risks up to $2 until midnight UTC. Agents always remain free to close positions. To change a limit, stop the agent, edit it, and start it again. You cannot edit a live agent's limits while it is running. ## Read its activity Every cycle, the agent records one decision with a reason: | Decision | Meaning | | --- | --- | | Hold | It looked and chose to do nothing. | | Buy or close | It sent an order. The entry shows the price, size, and result. | | Skip | It wanted to trade but a rule or condition stopped it, such as not enough money on the venue, a venue being down, or a limit. Skips do not count against the agent. | | Error | Something failed or the agent asked for an order it is not allowed to place. | ## Automatic pauses After three errors in a row, Felix pauses the agent. A paused agent places no new orders until you resume it. The most common cause is a strategy that keeps asking for an order larger than its maximum position. Fix the strategy or the limit, then resume. ## How agents get their money Agents trade from your agent capital, not your balance. After you allocate money to agents, Felix keeps each venue stocked for the agents that use it, moves free money from one venue to another when one is short, and returns money no agent needs. Money that backs an open position is never moved. [How Felix works](https://felix.trade/docs/overview/how-felix-works#how-felix-moves-agent-money) explains the rules. If a venue does not have enough money for an order, the agent skips that cycle and Felix starts moving money. On Polymarket, if there is not enough for the full order but there is enough for the venue minimum, the agent buys what it can afford instead. ## Stop, pause, and kill switch - **Pause or stop** an agent and it places no new orders. Its open positions stay open, because stopping is not an instruction to sell. Close them yourself if you want out. - **Prediction-market positions** still settle when their market resolves, even after you stop the agent. The payout goes to the same wallet. - **Kill switch** stops every agent on your account from opening new positions. See [Security](https://felix.trade/docs/overview/security#emergency-controls) for the full list of emergency controls. ## How many agents you can run Free accounts can run 3 agents at once, Pro 10, and Max 50. On Pro and Max, an agent can also react the moment its market moves instead of waiting for its timer. See [Plans](https://felix.trade/docs/overview/plans). --- # Guides: Research and backtests Source: https://felix.trade/docs/guides/research-and-backtests > Use chat to research markets, test a strategy on history, and read the results honestly. ## Research in chat Ask Felix about any market you can trade: prices, recent moves, news, prediction-market odds, company fundamentals, or options activity. Felix answers from live market data. AI answers can still be wrong or out of date. Check any number you plan to trade on, especially in fast markets. ## Run a backtest A backtest replays a strategy on historical prices and reports what would have happened. You can run one from any strategy draft in chat, or ask for one directly: ```text example request Backtest this on BTC hourly bars over the last two years with $1,000. ``` On Free, a backtest can use up to one year of history; Pro and Max can use the full history. Pro and Max also add walk-forward tests, which check the strategy on periods it was not tuned on, and robustness tests, which check how much the result depends on its exact settings. ## Read a backtest Look at these, in this order: 1. **Coverage.** The banner at the top says how much of the requested period had data. If coverage is low, the rest of the result means little. 2. **Warnings.** Missing data, gaps, or assumptions Felix had to make are listed here. 3. **Number of trades.** A result built on a handful of trades is mostly luck. 4. **Worst drop.** The largest fall from a peak. Ask yourself whether you could sit through it with real money. 5. **Profit and comparison.** Return, Sharpe ratio, and how the strategy compares with holding the asset over the same period. Returns are measured on the money the strategy actually had at risk, not on idle cash. ## Why a good backtest can still lose - Live fills are worse than historical prices, especially in thin markets. - Fees and funding add up, particularly for strategies that trade often. - A strategy tuned until it looks good on the past often fails on the future. - Markets change. What worked last year may not work next month. Run the agent in paper mode before giving it real money, and start live with a small budget. --- # Guides: API quickstart Source: https://felix.trade/docs/guides/api-quickstart > Create a key, make your first request, preview an order, and place it. The Felix API is a REST API at `https://api.felix.trade`. Requests and responses are JSON, and every size is in US dollars. This guide uses curl. ## Create a key 1. Sign in to the Felix app and open **Developers**, then **API keys**. 2. Choose **Create paper key** to trade against live prices with simulated money, or **Create live key** to trade real money. A live key asks you to sign with your owner key, and it can only trade within the limits you set for your wallet. 3. Copy the key. It starts with `fk_` and is shown only once. ```bash save the key export FELIX_API_KEY="fk_..." ``` ## Check that Felix is up This call needs no key. ```bash request curl https://api.felix.trade/v1/status ``` ```json response { "service": "felix-api", "status": "operational", "version": "2.0.221" } ``` ## Get a price ```bash request curl https://api.felix.trade/v1/quotes/BTC \ -H "Authorization: Bearer $FELIX_API_KEY" ``` ```json response { "instrument": "crypto:BTC", "product_type": "crypto_perpetual", "price": 83600.5, "tradeable": true } ``` ## Preview an order A preview tells you exactly what an order would cost and whether it can go through. It never moves money. ```bash request curl -X POST https://api.felix.trade/v1/orders/preview \ -H "Authorization: Bearer $FELIX_API_KEY" \ -H "Content-Type: application/json" \ -d '{"instrument": "BTC", "side": "buy", "size_usd": 50}' ``` ```json response { "canonical_instrument": "crypto:BTC", "side": "long", "est_fill_price": 83584.5, "fee": { "fee_usd": 0.0351, "bps": 7 }, "min_live_size_usd": 10.0, "collateral_check": { "ok": false, "status": "leverage_opt_in_required" } } ``` Read `collateral_check` before placing. In this example the account does not have $50 free on the venue, so the order would need leverage that the caller has not allowed. Fix that first, by funding the venue or allowing leverage, or the order will be refused. ## Place the order Every order needs an `Idempotency-Key` header. Use a new unique value for each new order, and reuse the same value if you retry the same order. That way a retry after a timeout can never place the order twice. ```bash request curl -X POST https://api.felix.trade/v1/orders \ -H "Authorization: Bearer $FELIX_API_KEY" \ -H "Content-Type: application/json" \ -H "Idempotency-Key: btc-long-2026-10-11-001" \ -d '{"instrument": "BTC", "side": "buy", "size_usd": 50}' ``` The response includes `status`, the fill price and size, the fee, and an `order_id` and `position_id`. > **Warning: A timeout does not mean the order failed** > If a request times out or returns an error after you sent it, the order may still have filled. Retry with the same `Idempotency-Key`, or check `GET /v1/positions`, before sending anything new. ## Check the result ```bash request curl https://api.felix.trade/v1/positions \ -H "Authorization: Bearer $FELIX_API_KEY" ``` `GET /v1/money` shows where all of your money is, across your balance, venues, and open positions. ## Next - [API reference](https://felix.trade/docs/api/overview) for every endpoint, its scope, and its errors. - [Idempotency](https://felix.trade/docs/api/idempotency) and [Errors](https://felix.trade/docs/api/errors) before you automate anything. - [Venues](https://felix.trade/docs/overview/venues) for minimums and leverage on each venue. --- # API reference: API overview Source: https://felix.trade/docs/api/overview > Base URL, request and response conventions, the rules every automated client must follow, and how the reference pages are generated. The Felix API is a JSON REST API at `https://api.felix.trade`, versioned under `/v1`. Every reference page in this section is generated from the OpenAPI document of the deployed engine, with the required scope and rate-limit bucket read from the same code. The REST API is the supported integration. A Felix MCP server exists, but the version published on npm is older than the minimum the API accepts for account, money, and agent actions, so build against the REST API. ## Conventions | Convention | Detail | | --- | --- | | Base URL | `https://api.felix.trade` | | Authentication | `Authorization: Bearer fk_` on every authenticated request. See [Authentication](https://felix.trade/docs/api/authentication). | | Content type | Request bodies are JSON with `Content-Type: application/json`. Responses are JSON. | | Amounts | Order sizes and transfers are in USD, as `size_usd`, `amount_usd`, or a six-decimal USDC `amount` string where the entry says so. | | Instruments | Canonical identifiers returned by search or the catalog. See [Markets](https://felix.trade/docs/api/markets). | | Mutations | Most mutations require an `Idempotency-Key` header. See [Idempotency](https://felix.trade/docs/api/idempotency). | | Identifiers | UUIDs for accounts, keys, orders, positions, agents, webhooks, feedback, and tickets. Some operation ids carry a prefix such as `fxop_` or `fxbt_`. | | Caching | JSON responses are sent with `Cache-Control: no-store`. | | Limits | Rate limits are per key and per bucket. See [Rate limits](https://felix.trade/docs/api/rate-limits). | ## Response envelope Successful responses return the resource directly, with `ok: true` on mutation results. Errors always use one envelope: ```json error envelope { "error": { "code": "forbidden", "message": "This key cannot place orders.", "hint": "Use a key with the trade scope." }, "_meta": { "http_status": 403, "request_id": "..." } } ``` Quote `_meta.request_id` in a support ticket. `_meta.retry_after` accompanies throttles. See [Errors](https://felix.trade/docs/api/errors). ## Rules for automated clients If an AI agent or a script calls the API on your behalf, it should follow these rules. They prevent the mistakes that cost money. 1. Send an `Idempotency-Key` on every mutation, and reuse the same key and body when you retry. A new key is a new order. 2. Never guess an instrument. Search with `GET /v1/instruments` or page the catalog, and use the canonical identifier it returns. 3. Preview before you trade. `POST /v1/orders/preview` returns the fee, the venue minimum, and the collateral you need without moving money. 4. Treat a timeout or a 5xx on a mutation as "maybe it happened". Read the intent, positions, and fills before sending anything new. 5. An error can follow a real fill. After any order attempt, read `GET /v1/positions` and `GET /v1/fills`. 6. Treat an unavailable balance source as unknown, never as zero. 7. Respect the limits the owner set: key caps, mandates, the portfolio mandate, and agent budgets. A refusal is the system working, not a reason to retry with different parameters. 8. Honor `Retry-After` on `429`. A throttle is not a revoked key. 9. Stop and report when an error code says reconciliation is required. Do not start a replacement workflow. ## How to read an endpoint entry Each entry shows the method and path, the authorization it needs, the rate-limit bucket it counts against, whether it requires an `Idempotency-Key`, its parameters and request-body fields, an example request, and the error statuses it can return. Field descriptions come from the contract; where the contract has none, the entry says so. ## Sections - [Registration](https://felix.trade/docs/api/registration), [Accounts](https://felix.trade/docs/api/accounts), [Keys](https://felix.trade/docs/api/keys), and [Mandates](https://felix.trade/docs/api/mandates): identity and authority. - [Markets](https://felix.trade/docs/api/markets), [Orders](https://felix.trade/docs/api/orders), [Positions and exit plans](https://felix.trade/docs/api/positions), and [Reporting](https://felix.trade/docs/api/reporting): trading and records. - [Balance](https://felix.trade/docs/api/balance), [Agent capital](https://felix.trade/docs/api/agent-capital), [Venue funding and returns](https://felix.trade/docs/api/venue-funding), and [Settlement transfers](https://felix.trade/docs/api/settlement): money on the Arc home. - [Wallet](https://felix.trade/docs/api/wallet), [Funding](https://felix.trade/docs/api/funding), [Venue onboarding](https://felix.trade/docs/api/venue-onboarding), [Prediction-market orders](https://felix.trade/docs/api/prediction-market-orders), [Withdrawals](https://felix.trade/docs/api/withdrawals), and [Routing](https://felix.trade/docs/api/routing): owner wallets and venue setup. - [Strategies](https://felix.trade/docs/api/strategies), [Backtests](https://felix.trade/docs/api/backtests), [Agents](https://felix.trade/docs/api/agents), and [Portfolio risk](https://felix.trade/docs/api/portfolio-risk): automation. - [Streams](https://felix.trade/docs/api/streams), [Webhooks](https://felix.trade/docs/api/webhooks), [Plans](https://felix.trade/docs/api/plans), [Feedback and support](https://felix.trade/docs/api/feedback-and-support), and [Platform](https://felix.trade/docs/api/platform): everything else. ## Compatibility Changes to `/v1` are additive. A deprecated operation is marked in its entry and keeps working until the changelog announces removal. A retired operation returns `410` with a code that names its replacement. --- # API reference: Authentication Source: https://felix.trade/docs/api/authentication > How to send an API key, what each scope allows, the kinds of keys Felix issues, and the ownership boundary every request is checked against. Send the key as a bearer token: ```http authorization header Authorization: Bearer fk_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx ``` The `X-API-Key` header is accepted as an alternative. Every key begins with `fk_`; the prefix reveals nothing about its authority, which is server-side metadata. A missing or unrecognized key returns `401 unauthorized`. A valid key without the required scope returns `403 forbidden`. ## Scopes | Scope | Authority | | --- | --- | | `read` | Market data and the key's own account state, including previews and backtests. | | `trade` | Real-money orders, agents, and emergency stop, but only when the key is live-enabled and capped. | | `manage` | Owned child accounts, keys, Arc home onboarding, venue setup, webhooks, and subscription. | | `transfer` | Withdrawals, deposits, allocations to agent capital, venue funding and returns. Not granted to ordinary agent keys. | Some endpoints require more than one scope; each entry lists exactly what it needs. ## Kinds of keys | Key | How it is issued | What it can do | | --- | --- | --- | | Registration key | `POST /v1/register` | `read`, `trade`, `manage`, and `transfer` scopes, but not live-enabled. Sets up the Arc home, moves money with owner signatures, reads data, and runs previews and backtests. It cannot place live orders. | | Bootstrap key | `POST /v1/accounts` | Read-only key for a new child account, returned once. | | Live key | `POST /v1/keys/live/submit` after an owner signature | Executes real-money orders within owner-signed per-order, daily-notional, and daily-loss caps and an expiry. | | Paper key | A child account created with `paper: true` | Simulation only. | The API's `live_enabled` flag on a key, together with its caps, is what turns `trade` scope into real authority. See [Keys](https://felix.trade/docs/api/keys). ## Ownership boundary A key can access only its own account. A parent `manage` key may target a child only when that child is bound to the parent; pass `account_id` on the endpoints that accept it. Arbitrary account, key, position, agent, feedback, webhook, and ticket identifiers never cross that boundary, and a foreign id returns `404` without disclosing whether it exists. ## Handling keys - Raw keys are returned once. Exact idempotent replays are redacted. - Store keys in a secret manager. Never place one in a prompt, URL, log, screenshot, or source control. - Revoke with `DELETE /v1/keys/{key_id}` or `DELETE /v1/keys/live/{key_id}`. `POST /v1/panic` revokes every active key for the account. - A throttle (`429 rate_limited`) is not a revoked key. Keep the key and honor `Retry-After`. --- # API reference: Idempotency Source: https://felix.trade/docs/api/idempotency > The Idempotency-Key header, the key format, what a replay returns, how conflicts and unknown sends are reported, and why a money workflow key is durable state. Send an `Idempotency-Key` header on every mutation that accepts one. Felix stores the key with a fingerprint of the route and body. A retry with the same key and body returns the original result instead of executing again; a retry with the same key and a different body is rejected. ```http idempotent request headers POST /v1/orders Authorization: Bearer fk_... Idempotency-Key: 6f1d2c4e-3b8a-4f0e-9c21-7a5e0d9b1c33 Content-Type: application/json ``` ## Key format - 8 to 128 printable ASCII characters with no whitespace. A UUID is a good default. - Reuse the same key only for an exact retry of the same route and body. - Durable backtests use the form `fxbt_` followed by 32 lowercase hexadecimal characters. - In batch orders, every live item receives its own deterministic identity derived from the batch key. ## What you get back | Situation | Result | | --- | --- | | First request | Executes and stores the response. | | Same key, same body | Returns the stored response. Raw secrets in the original response are redacted on replay. | | Same key, different body | `409 idempotency_conflict`. | | Same key while the original is still in progress | The original's pending state, never a second execution. | | Felix cannot tell whether the venue received the request | `idempotency_send_unknown`. Reconcile state before sending anything new. | Idempotent replays of backtests and support writes do not consume another daily quota. ## Money workflows For deposits, withdrawals, allocations, venue fundings and returns, subscription payments, and account creation, the key identifies the workflow, not a single HTTP call. The workflow saves checkpoints under the key. Resuming with the same key replays completed checkpoints and continues from the first incomplete one; it never moves funds twice. Start a new key only for a genuinely new intent, and never change keys to get past an unclear result. A timeout means still settling. ## Recovering from an unclear result 1. Read the operation or intent by its id: `GET /v1/orders/intents/{intent_id}`, `GET /v1/arc-home/operations/{operation_id}`, or the status route on that workflow's page. 2. Read `GET /v1/positions`, `GET /v1/fills`, and `GET /v1/money`. 3. If the workflow has a `reconcile` route, call it. It proves what happened from venue and chain evidence and sends nothing new. 4. Retry only with the original `Idempotency-Key` and body. ## Endpoints without the header Read endpoints and some safety endpoints, such as cancelling an order or stopping an agent, are naturally repeatable and do not take the header. Each endpoint entry states whether the header is required, accepted, or absent. --- # API reference: Errors Source: https://felix.trade/docs/api/errors > The error envelope, HTTP statuses, the stable error codes, and what to do when you meet each one. Every error is JSON with a stable code, a message safe to show a user, and, where one applies, a hint that says what to do next. ```json error envelope { "error": { "code": "bad_request", "message": "...", "hint": "..." }, "_meta": { "http_status": 400, "request_id": "...", "retry_after": 12 } } ``` - `error.code` never changes meaning. Branch on it, not on the message. - `_meta.request_id` is the id to quote to support. - `_meta.retry_after` appears on throttles and on some pending states. - Many money and venue errors also carry `reason` (the stable service code) and a field saying whether money moved. ## HTTP statuses | Status | Meaning | | --- | --- | | 400 | Invalid request. | | 401 | Missing, unknown, or revoked API key. | | 403 | Missing scope, key not live-enabled, cap exceeded, or blocked by policy. | | 404 | No owned resource with that id. Another account's ids also return 404. | | 409 | State or idempotency conflict. | | 410 | Retired operation. The error names the replacement. | | 422 | The request body failed schema validation. | | 429 | Rate limit or daily quota exceeded. Honor `Retry-After`. | | 500 | Internal failure. | | 502 | Venue or provider failure. Retry with the same `Idempotency-Key`. | | 503 | A required dependency is unavailable. The mutation was not started; retry later with the same key. | | 504 | Request timeout. Reconcile before retrying a mutation. | ## General codes | Code | Status | Meaning | | --- | --- | --- | | `bad_request` | 400 | A field is missing, malformed, or out of bounds. | | `unauthorized` | 401 | The key is missing, unknown, or revoked. | | `forbidden` | 403 | The key lacks a scope, is not live-enabled, exceeds a cap, or the action is blocked by policy. | | `not_found` | 404 | No owned resource with that id. | | `idempotency_conflict` | 409 | The key was reused with a different body. | | `idempotency_send_unknown` | 409 | Felix cannot tell whether the venue received the request. Reconcile first. | | `legal_version_mismatch` | 409 | The supplied `legal_version` is not the current legal bundle. | | `terms_acceptance_required` | 409 | The account has not accepted the current legal bundle. Accept it with `POST /v1/legal/accept`, then retry. | | `rate_limited` | 429 | Throttled. The key is still valid. | | `upstream_error` | 502 | A venue or data provider failed. | | `service_unavailable` | 503 | A required dependency, such as the replay store or the daily-spend guard, is unavailable. Nothing was started. | ## Codes you will meet in practice | Code | What it means and what to do | | --- | --- | | `paper_only_key` | The key is not live-enabled. Mint a live key. | | `order_below_venue_minimum` | The order is under the venue minimum. Read `min_live_size_usd` from the preview and size up. | | `live_limit_orders_unavailable` | `POST /v1/orders` takes market orders only. | | `venue_funding_required` | The venue account does not hold enough collateral. Fund the venue, or reduce the size. No order was started. | | `clob_rejected_order` | The prediction-market venue refused the order. Read `venue_error` for its reason, usually balance plus fee. | | `reconcile_required`, `polymarket_close_reconciliation_required` | An earlier action may have reached the venue and is being confirmed. Read the intent. Never submit a replacement. | | `network_fee_unpaid` | An earlier funding network fee is still outstanding. Resolve it before starting a new funding to that venue. | | `derive_return_reconciliation_pending` | Retry the identical body with the same key after `retry_after`. | | `arc_admission_frozen` | New Arc home money workflows are paused for a few minutes during a release. Wait; do not retry in a loop. Reads and recovery still work. | | `agent_capital_not_enabled` | The account has no agent capital yet. Allocate first. | | `agent_must_be_stopped` | Stop the agent before changing its limits. | | `polygon_safe_hub_retired` | The Polygon wallet routes are retired. Use the Arc home routes in [Balance](https://felix.trade/docs/api/balance). | When a mutation's outcome is unclear, follow the order in [Idempotency](https://felix.trade/docs/api/idempotency): read the intent or operation, check positions and balances, then retry only with the original key. --- # API reference: Rate limits Source: https://felix.trade/docs/api/rate-limits > Per-minute limits by bucket and tier, the headers that report them, durable daily quotas, and how the limiter behaves when its store is unavailable. Limits are enforced per API key, per minute, per bucket. Every endpoint entry names its bucket. The tier follows the account's plan: Free, Pro (API tier `dev`), or Max (API tier `scale`). Safety exits and post-signature reconciliation live in their own buckets so an exhausted order bucket can never stop you from reducing risk or recording an order that already reached the venue. ## Per-minute limits by bucket | Bucket | Used by | Free | Pro | Max | | --- | --- | --- | --- | --- | | `read` | Account state and reporting | 60 | 300 | 1,200 | | `market` | Instruments, quotes, order books, previews, wallet state | 30 | 120 | 600 | | `research` | Research cards, screener, earnings, equity options, options flow | 12 | 60 | 180 | | `stream` | WebSocket tickets | 10 | 30 | 120 | | `order` | Placing orders, deploying agents, prediction-market prepare and submit | 10 | 60 | 300 | | `safety` | Cancels, closes, exit plans, agent stop and update | 30 | 180 | 900 | | `reconcile` | Intent status, checkpoint, commit, redemption | 30 | 180 | 900 | | `manage` | Accounts, keys, webhooks, Arc home onboarding, subscription | 5 | 20 | 60 | | `transfer` | Deposits, withdrawals, allocations, venue funding and returns | 20 | 60 | 180 | | `wallet_rpc` | Workflow-scoped JSON-RPC relays | 120 | 600 | 1,200 | | `strategy` | Strategy generation | 10 | 30 | 90 | | `backtest` | Backtests and their operations | 20 | 60 | 180 | | `expensive` | Webhook tests and heavier backtests (sensitivity, walk-forward, portfolio replay) | 3 | 10 | 30 | | `feedback` | Feedback and support writes | 3 | 10 | 30 | | `panic` | Emergency stop | 5 | 10 | 20 | Endpoints that need no key, such as health, status, tiers, and registration, are limited per IP address instead. ## Headers and throttling Every authenticated response carries `X-RateLimit-Limit`, `X-RateLimit-Remaining`, and `X-RateLimit-Reset`. When a bucket is exhausted the request fails with `429 rate_limited` and a `Retry-After` header; `_meta.retry_after` repeats the value in the body. Wait at least that long. A throttle is not a revoked key, and rotating credentials to bypass a limit is not supported. Cold provider reads on research endpoints can take up to 20 to 25 seconds; cached reads are faster. ## Durable daily quotas Some workflows are counted per UTC day in durable storage, not per minute: | Quota | Free | Pro | Max | | --- | --- | --- | --- | | New backtest workflows | 50 | 500 | 5,000 | | Sensitivity, walk-forward, revision review, and portfolio replay (each) | 10 | 50 | 200 | | Strategy generations | 60 | 600 | 6,000 | | Support tickets | 10 | 10 | 10 | | Support messages | 30 | 30 | 30 | Exact idempotent replays do not count again. `GET /v1/me/subscription` returns the limits for the calling key's tier. ## Fail-closed behavior If the durable limiter store is unavailable, risk-increasing buckets (`order`, `manage`, `strategy`, `backtest`, `expensive`) fail closed with `503 service_unavailable` and the mutation is not started. Read buckets keep working from a bounded in-process window. ## Related limits - Webhooks per account by tier: [Webhooks](https://felix.trade/docs/api/webhooks). - Live-key per-order, daily-notional, and daily-loss caps: [Keys](https://felix.trade/docs/api/keys). - Agent counts and AI usage by plan: [Plans](https://felix.trade/docs/api/plans). --- # API reference: Pagination Source: https://felix.trade/docs/api/pagination > How list endpoints page with cursors and limits, and how to know when a listing is complete. List endpoints return a bounded page and an opaque cursor for the next one. Page order is stable within a listing but is not a creation order or a ranking unless the entry says so. ## Cursor pattern ```text page through a venue catalog GET /v1/markets/catalog?venue=polymarket&status=active&limit=100 GET /v1/markets/catalog?venue=polymarket&status=active&limit=100&cursor= ... until next_cursor is null and complete is true ``` - `limit` bounds the page size; each endpoint states its maximum. - `cursor` is the exact `next_cursor` value from the previous page. Do not construct or modify it. - A null `next_cursor` ends the listing. The catalog also returns `complete: true` so an agent can prove it enumerated everything before deciding an instrument does not exist. ## Endpoints that page | Endpoint | Parameters | | --- | --- | | `GET /v1/markets/catalog` | `venue`, `status`, `kind`, `q`, `cursor`, `limit` (1 to 200) | | `GET /v1/accounts` | `limit`, `cursor` (an account id), `include_archived` | | `GET /v1/agents` | `status`, `mode`, `before`, `limit` | | `GET /v1/agents/{agent_id}/decisions` | `before`, `limit` | | `GET /v1/fills` | `limit` | | `GET /v1/exit-plans` | `status`, `limit` | | `GET /v1/feedback` | `limit` | | `GET /v1/support/tickets` | `status`, `limit` | `GET /v1/events/wait` is a long-poll rather than a list: pass the previous `next_after` cursor as `after` and it returns after the next matching event or the bounded timeout. --- # API reference: Registration Source: https://felix.trade/docs/api/registration > Register an owner address with a locally signed challenge and receive the account's first API key. Registration binds a new account to the address that signs the challenge. It needs no API key, spends no gas, moves no funds, and does not enable live trading. The walkthrough is in the [API quickstart](https://felix.trade/docs/guides/api-quickstart). - Challenges are single-use and expire after 10 minutes. - Registration is rate-limited per IP address. - One account per owner address. - The signed challenge binds the current legal bundle version, `2026-10-11`. A different supplied version is rejected with `409 legal_version_mismatch`. - Optional `attribution` metadata is carried through both steps and never changes account or key authority. ### POST /v1/register/challenge Return the exact message the owner key must sign, with its nonce and expiry. Authorization: No API key. Request body (JSON): - `owner_address` (string, required): Fresh client-held EVM owner address. [matches ^0x[0-9a-fA-F]{40}$] - `attribution` (object, optional): Optional bounded acquisition metadata for anonymous registration-start measurement. It never changes account authority, key scope, wallet state, or trading permissions. - `anonymous_id` (string, optional): Optional browser attribution UUID. [matches ^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$] - `utm_source` (string, optional): First- or last-touch campaign source. [at least 1 character; at most 120 characters] - `utm_medium` (string, optional): Campaign medium. [at least 1 character; at most 120 characters] - `utm_campaign` (string, optional): Campaign name. [at least 1 character; at most 120 characters] - `utm_content` (string, optional): Content or creator identifier. [at least 1 character; at most 120 characters] - `utm_term` (string, optional): Optional campaign term. [at least 1 character; at most 120 characters] - `referral_code` (string, optional): Optional Felix referral code. [at least 4 characters; at most 32 characters; matches ^[A-Za-z0-9_-]{4,32}$] - `landing_path` (string, optional): First Felix site path. [at least 1 character; at most 200 characters; matches ^/(?!/).*$] - `referrer_host` (string, optional): External referrer hostname. [at least 1 character; at most 100 characters] Error statuses: 400 Invalid request; 401 Missing or invalid API key; 403 Scope, policy, or live-trading restriction; 404 Owned resource not found; 409 State or idempotency conflict; 422 Request body failed schema validation; 429 Rate limit or durable quota exceeded; 500 Internal failure; 502 Venue or provider failure; 503 Required dependency unavailable; 504 Request timeout. ### POST /v1/register Exchange the owner's EIP-191 signature over the challenge for an account and its first key, returned once. Authorization: No API key. Request body (JSON, required): - `message` (string, required): Exact unexpired message returned by the registration challenge. [at least 1 character; at most 512 characters] - `signature` (string, required): Canonical 65-byte personal-sign signature by the challenged owner. [matches ^0x[0-9a-fA-F]{130}$] - `accept_terms` (constant true, required): Explicit acceptance of the versioned Felix legal bundle. [must be true] - `legal_version` (constant "2026-10-11", optional): Accepted Felix Terms, Privacy, Risk, and Custody bundle version. Omit to accept the current server version. [must be "2026-10-11"; default "2026-10-11"] - `label` (string, optional): Optional account label. [at most 60 characters] - `attribution` (object, optional): Optional bounded acquisition metadata. It never changes account authority, key scope, wallet state, or trading permissions. - `anonymous_id` (string, optional): Optional browser attribution UUID. [matches ^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$] - `utm_source` (string, optional): First- or last-touch campaign source. [at least 1 character; at most 120 characters] - `utm_medium` (string, optional): Campaign medium. [at least 1 character; at most 120 characters] - `utm_campaign` (string, optional): Campaign name. [at least 1 character; at most 120 characters] - `utm_content` (string, optional): Content or creator identifier. [at least 1 character; at most 120 characters] - `utm_term` (string, optional): Optional campaign term. [at least 1 character; at most 120 characters] - `referral_code` (string, optional): Optional Felix referral code. [at least 4 characters; at most 32 characters; matches ^[A-Za-z0-9_-]{4,32}$] - `landing_path` (string, optional): First Felix site path. [at least 1 character; at most 200 characters; matches ^/(?!/).*$] - `referrer_host` (string, optional): External referrer hostname. [at least 1 character; at most 100 characters] Error statuses: 400 Invalid request; 401 Missing or invalid API key; 403 Scope, policy, or live-trading restriction; 404 Owned resource not found; 409 State or idempotency conflict; 422 Request body failed schema validation; 429 Rate limit or durable quota exceeded; 500 Internal failure; 502 Venue or provider failure; 503 Required dependency unavailable; 504 Request timeout. ## Response ```json registration response { "account_id": "...", "api_key": "fk_...", "scopes": ["read", "trade", "manage", "transfer"] } ``` The key is not live-enabled. Before live trading, set up the Arc home ([Balance](https://felix.trade/docs/api/balance)), fund it, and mint an owner-signed live key ([Keys](https://felix.trade/docs/api/keys)). ## Accepting updated terms When Felix publishes a new legal bundle, every existing account accepts it again before its next risk-adding action. Until it does, placing a live order that is not reduce-only, deploying or resuming a live agent, and allocating money to agents return `409 terms_acceptance_required`. The error includes `current_legal_version`, `accepted_legal_version`, and links to the four documents. Withdrawals, reduce-only orders, closing positions, stopping agents, and agents that are already running are never blocked. ### GET /v1/legal Return the current legal bundle, its documents, and the version this account last accepted. Authorization: API key with `read` scope. Query parameters: - `account_id` (string, nullable, optional) Error statuses: 400 Invalid request; 401 Missing or invalid API key; 403 Scope, policy, or live-trading restriction; 404 Owned resource not found; 409 State or idempotency conflict; 422 Request body failed schema validation; 429 Rate limit or durable quota exceeded; 500 Internal failure; 502 Venue or provider failure; 503 Required dependency unavailable; 504 Request timeout. ### POST /v1/legal/accept Record this account's acceptance of the current legal bundle. Authorization: API key with `read` scope. Rate-limit bucket: `manage`. Request body (JSON, required): - `accept_terms` (constant true, required): Explicit acceptance of the current Felix legal bundle. [must be true] - `legal_version` (constant "2026-10-11", optional): Accepted Felix Terms, Privacy, Risk, and Custody bundle version. Omit to accept the current server version. [must be "2026-10-11"; default "2026-10-11"] - `account_id` (string, optional): Owned child account to accept for (requires the manage scope). Omit for this account. [matches ^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$] Error statuses: 400 Invalid request; 401 Missing or invalid API key; 403 Scope, policy, or live-trading restriction; 404 Owned resource not found; 409 State or idempotency conflict; 422 Request body failed schema validation; 429 Rate limit or durable quota exceeded; 500 Internal failure; 502 Venue or provider failure; 503 Required dependency unavailable; 504 Request timeout. ```json accept request { "accept_terms": true, "legal_version": "2026-10-11" } ``` A key with the `manage` scope can accept for a child account it owns: add `account_id` to the body, the same way the child accepted when you created it. `GET /v1/legal?account_id=` shows a child's status. Read the documents before you accept. A `legal_version` that is not the current bundle returns `409 legal_version_mismatch`; fetch `GET /v1/legal` again and retry with the version it returns. --- # API reference: Accounts Source: https://felix.trade/docs/api/accounts > Create, list, and archive isolated child accounts under a manage key. A child account is an isolated identity with its own wallet, keys, and balances, owned by the account whose `manage` key created it. The parent can create, inspect, and archive children and target them with `account_id` on endpoints that accept it. It cannot spend their funds. ### GET /v1/accounts List owned child accounts with wallet readiness and active key counts, without emails or secrets. Authorization: API key with `manage` scope. Rate-limit bucket: `manage`. Query parameters: - `limit` (integer, optional) [minimum 1; maximum 100; default 50] - `cursor` (string, nullable, optional) - `include_archived` (boolean, optional) [default false] Error statuses: 400 Invalid request; 401 Missing or invalid API key; 403 Scope, policy, or live-trading restriction; 404 Owned resource not found; 409 State or idempotency conflict; 422 Request body failed schema validation; 429 Rate limit or durable quota exceeded; 500 Internal failure; 502 Venue or provider failure; 503 Required dependency unavailable; 504 Request timeout. ### POST /v1/accounts Create an isolated, zero-funded child and return its one-time read-only bootstrap key and legal acceptance receipt. Authorization: API key with `manage` scope. Rate-limit bucket: `manage`. `Idempotency-Key` header: required. Request body (JSON): - `email` (string, optional): Optional unique child-account email. Omit for an internal agent identity. [at most 254 characters] - `label` (string, optional): Human-readable key/account label. [at most 80 characters] - `accept_terms` (constant true, required): Explicit acceptance of the versioned Felix legal bundle. [must be true] - `legal_version` (constant "2026-10-11", optional): Accepted Felix Terms, Privacy, Risk, and Custody bundle version. Omit to accept the current server version. [must be "2026-10-11"; default "2026-10-11"] - `paper` (boolean, optional): Create a simulation account instead of the default live-onboarding account. [default false] Error statuses: 400 Invalid request; 401 Missing or invalid API key; 403 Scope, policy, or live-trading restriction; 404 Owned resource not found; 409 State or idempotency conflict; 422 Request body failed schema validation; 429 Rate limit or durable quota exceeded; 500 Internal failure; 502 Venue or provider failure; 503 Required dependency unavailable; 504 Request timeout. ## Create response ```json child account response { "account_id": "...", "key_id": "...", "bootstrap_key": "fk_...", "wallet_status": "onboarding_required", "deposit_address": null } ``` `bootstrap_key` appears only on the first successful response; exact retries are redacted. Account creation requires `accept_terms: true`, which accepts the [Terms of Service](https://felix.trade/legal/terms) and acknowledges the Privacy Policy, Risk Disclosure, and Custody & Authority Notice. ### POST /v1/accounts/{account_id}/archive Pause and archive a flat child, revoke every key it holds, and retain wallet and financial records for audit. Authorization: API key with `manage` scope. Rate-limit bucket: `manage`. `Idempotency-Key` header: required. Path parameters: - `account_id` (string, required) Request body (JSON, required): - `confirm_account_id` (string, required): Exact child account UUID confirmation. The account must already be flat and owner-paused. [matches ^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$] Error statuses: 400 Invalid request; 401 Missing or invalid API key; 403 Scope, policy, or live-trading restriction; 404 Owned resource not found; 409 State or idempotency conflict; 422 Request body failed schema validation; 429 Rate limit or durable quota exceeded; 500 Internal failure; 502 Venue or provider failure; 503 Required dependency unavailable; 504 Request timeout. --- # API reference: Keys Source: https://felix.trade/docs/api/keys > List and revoke API keys, and mint owner-signed live keys with per-order, daily-notional, and daily-loss caps. Keys carry scopes; live keys additionally carry owner-signed caps and an expiry. Caps must fit inside the account's wallet policy, whose per-operation, daily, and lifetime ceilings are immutable after account creation. An existing key's caps cannot be edited: revoke it and mint a replacement inside the same ceiling. Limits higher than the ceiling require a new account and an ordinary withdrawal and deposit migration. ## Inventory and revocation ### GET /v1/keys List active key metadata for this account or an owned child. Raw keys and hashes are never returned. Authorization: API key with `manage` scope. Rate-limit bucket: `manage`. Query parameters: - `account_id` (string, nullable, optional) Error statuses: 400 Invalid request; 401 Missing or invalid API key; 403 Scope, policy, or live-trading restriction; 404 Owned resource not found; 409 State or idempotency conflict; 422 Request body failed schema validation; 429 Rate limit or durable quota exceeded; 500 Internal failure; 502 Venue or provider failure; 503 Required dependency unavailable; 504 Request timeout. ### DELETE /v1/keys/{key_id} Revoke one key owned by this account or an owned child. Authorization: API key with `manage` scope. Rate-limit bucket: `manage`. Path parameters: - `key_id` (string, required) Query parameters: - `account_id` (string, nullable, optional) Error statuses: 400 Invalid request; 401 Missing or invalid API key; 403 Scope, policy, or live-trading restriction; 404 Owned resource not found; 409 State or idempotency conflict; 422 Request body failed schema validation; 429 Rate limit or durable quota exceeded; 500 Internal failure; 502 Venue or provider failure; 503 Required dependency unavailable; 504 Request timeout. ## Live keys ### POST /v1/keys/live/prepare Return the canonical message binding scopes, caps, nonce, and expiry that the wallet owner must sign with personal_sign. Authorization: API key with `manage` scope. Rate-limit bucket: `transfer`. Request body (JSON, required): - `account_id` (string, optional): Target isolated account UUID. Omit to use the key's own account. [matches ^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$] - `scopes` (string or array of string, optional): Live-key scopes, restricted to read and trade. - `max_order_usd` (number, optional): Owner-approved maximum notional per order. [greater than 0] - `max_daily_usd` (number, optional): Owner-approved maximum opening notional per UTC day. [greater than 0] - `max_daily_loss_usd` (number, optional): Owner-approved maximum realized loss per UTC day. [greater than 0] - `ttl_seconds` (integer, optional): Lifetime of the message awaiting owner signature. [minimum 60; maximum 3600; default 600] Error statuses: 400 Invalid request; 401 Missing or invalid API key; 403 Scope, policy, or live-trading restriction; 404 Owned resource not found; 409 State or idempotency conflict; 422 Request body failed schema validation; 429 Rate limit or durable quota exceeded; 500 Internal failure; 502 Venue or provider failure; 503 Required dependency unavailable; 504 Request timeout. ### POST /v1/keys/live/submit Verify the owner signature and the single-use nonce, then mint the live key exactly once. Authorization: API key with `manage` scope. Rate-limit bucket: `transfer`. Request body (JSON, required): - `account_id` (string, optional): Target isolated account UUID. Omit to use the key's own account. [matches ^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$] - `message` (string, required): Exact canonical message returned by live-key prepare. [at least 1 character; at most 1024 characters] - `signature` (string, required): Owner's canonical 65-byte personal-sign signature. [matches ^0x[0-9a-fA-F]{130}$] - `label` (string, optional): Human-readable label for the newly minted key. [at most 80 characters] Error statuses: 400 Invalid request; 401 Missing or invalid API key; 403 Scope, policy, or live-trading restriction; 404 Owned resource not found; 409 State or idempotency conflict; 422 Request body failed schema validation; 429 Rate limit or durable quota exceeded; 500 Internal failure; 502 Venue or provider failure; 503 Required dependency unavailable; 504 Request timeout. ### GET /v1/keys/live List active live-key metadata for this account or an owned child. Authorization: API key with `manage` scope. Rate-limit bucket: `manage`. Query parameters: - `account_id` (string, nullable, optional) Error statuses: 400 Invalid request; 401 Missing or invalid API key; 403 Scope, policy, or live-trading restriction; 404 Owned resource not found; 409 State or idempotency conflict; 422 Request body failed schema validation; 429 Rate limit or durable quota exceeded; 500 Internal failure; 502 Venue or provider failure; 503 Required dependency unavailable; 504 Request timeout. ### DELETE /v1/keys/live/{key_id} Revoke one live key without engaging the emergency stop. Authorization: API key with `manage` scope. Rate-limit bucket: `manage`. Path parameters: - `key_id` (string, required) Query parameters: - `account_id` (string, nullable, optional) Error statuses: 400 Invalid request; 401 Missing or invalid API key; 403 Scope, policy, or live-trading restriction; 404 Owned resource not found; 409 State or idempotency conflict; 422 Request body failed schema validation; 429 Rate limit or durable quota exceeded; 500 Internal failure; 502 Venue or provider failure; 503 Required dependency unavailable; 504 Request timeout. --- # API reference: Markets Source: https://felix.trade/docs/api/markets > Discover instruments, read quotes, order books, funding, and option chains, and call the bounded research endpoints that never place an order. Every endpoint here is a read. Instrument identifiers returned by search and the catalog are canonical; use them unchanged in quotes, previews, orders, and subscriptions. Research endpoints return structured data without a model call, identify delayed feeds explicitly, and count against the `research` bucket. ## Discovery ### GET /v1/instruments Search across every market type with one phrase and return canonical instruments the caller can quote or trade. Authorization: API key with `read` scope. Rate-limit bucket: `market`. Query parameters: - `q` (string, optional): ticker, name, or question, fuzzy across all venues [default ""] - `kind` (string, optional): filter: crypto|stock|perp|option|pm [default ""] - `limit` (integer, optional) [default 20] Error statuses: 400 Invalid request; 401 Missing or invalid API key; 403 Scope, policy, or live-trading restriction; 404 Owned resource not found; 409 State or idempotency conflict; 422 Request body failed schema validation; 429 Rate limit or durable quota exceeded; 500 Internal failure; 502 Venue or provider failure; 503 Required dependency unavailable; 504 Request timeout. ### GET /v1/markets/catalog Page deterministically through one venue's complete inventory, including active, future, resolved, and inactive markets, until next_cursor is null. Authorization: API key with `read` scope. Rate-limit bucket: `market`. Query parameters: - `venue` (string, required): polymarket|hyperliquid|derive|lighter|predictfun - `status` (string, optional): active|future|resolved|inactive|all [default "active"] - `kind` (string, optional): Optional venue product filter. [default ""] - `q` (string, optional): Optional text filter within this page. [default ""] - `cursor` (string, optional): Opaque next_cursor from the previous page. [default ""] - `limit` (integer, optional) [minimum 1; maximum 200; default 100] Error statuses: 400 Invalid request; 401 Missing or invalid API key; 403 Scope, policy, or live-trading restriction; 404 Owned resource not found; 409 State or idempotency conflict; 422 Request body failed schema validation; 429 Rate limit or durable quota exceeded; 500 Internal failure; 502 Venue or provider failure; 503 Required dependency unavailable; 504 Request timeout. `venue` is one of `polymarket`, `hyperliquid`, `derive`, `lighter`, or `predictfun`. Lighter markets are traded by agents only; `POST /v1/orders` does not route to Lighter. predict.fun is listed for research and is not tradable. ## Prices ### GET /v1/quotes/{instrument} Return the price and market metadata for one instrument, including product_type, price_role, venue, tradeable, and data_class. Authorization: API key with `read` scope. Rate-limit bucket: `market`. Path parameters: - `instrument` (string, required) Error statuses: 400 Invalid request; 401 Missing or invalid API key; 403 Scope, policy, or live-trading restriction; 404 Owned resource not found; 409 State or idempotency conflict; 422 Request body failed schema validation; 429 Rate limit or durable quota exceeded; 500 Internal failure; 502 Venue or provider failure; 503 Required dependency unavailable; 504 Request timeout. ```json quote response { "instrument": "crypto:BTC", "price": 61825.5, "market": "crypto", "venue": "hyperliquid", "tradeable": true } ``` A listed equity ticker resolves to an equity perpetual, and its quote can be an execution mark rather than the delayed cash share price. Inspect the metadata fields before using the number. ### GET /v1/orderbook/{instrument} Return the top of book for a tradeable instrument. Authorization: API key with `read` scope. Rate-limit bucket: `market`. Path parameters: - `instrument` (string, required) Error statuses: 400 Invalid request; 401 Missing or invalid API key; 403 Scope, policy, or live-trading restriction; 404 Owned resource not found; 409 State or idempotency conflict; 422 Request body failed schema validation; 429 Rate limit or durable quota exceeded; 500 Internal failure; 502 Venue or provider failure; 503 Required dependency unavailable; 504 Request timeout. ### GET /v1/funding/{instrument} Return the current perpetual funding rate for an instrument. Authorization: API key with `read` scope. Rate-limit bucket: `market`. Path parameters: - `instrument` (string, required) Error statuses: 400 Invalid request; 401 Missing or invalid API key; 403 Scope, policy, or live-trading restriction; 404 Owned resource not found; 409 State or idempotency conflict; 422 Request body failed schema validation; 429 Rate limit or durable quota exceeded; 500 Internal failure; 502 Venue or provider failure; 503 Required dependency unavailable; 504 Request timeout. ### GET /v1/options/{underlying} Return the tradeable crypto option chain for an underlying: expiries, strikes, greeks, implied volatility, quotes, and the tightest round-trip candidates by quoted spread. Authorization: API key with `read` scope. Rate-limit bucket: `market`. Path parameters: - `underlying` (string, required) Error statuses: 400 Invalid request; 401 Missing or invalid API key; 403 Scope, policy, or live-trading restriction; 404 Owned resource not found; 409 State or idempotency conflict; 422 Request body failed schema validation; 429 Rate limit or durable quota exceeded; 500 Internal failure; 502 Venue or provider failure; 503 Required dependency unavailable; 504 Request timeout. ## Research Research limits are 12 calls per minute on Free, 60 on Pro, and 180 on Max. Cold provider reads can take up to 20 to 25 seconds; cached reads are faster. Honor `Retry-After` on 429. ### GET /v1/research/{symbol} Return chart-ready research cards and structured signals over real historical bars for one symbol. Authorization: API key with `read` scope. Rate-limit bucket: `research`. Path parameters: - `symbol` (string, required) Query parameters: - `interval` (string, optional) [default "1h"] - `bars` (integer, optional) [minimum 300; default 750] - `compact` (boolean, optional) [default false] Error statuses: 400 Invalid request; 401 Missing or invalid API key; 403 Scope, policy, or live-trading restriction; 404 Owned resource not found; 409 State or idempotency conflict; 422 Request body failed schema validation; 429 Rate limit or durable quota exceeded; 500 Internal failure; 502 Venue or provider failure; 503 Required dependency unavailable; 504 Request timeout. ```json research response { "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." } ``` `tier_bar_limit` is 750 bars per call on Free, 2,500 on Pro, and 5,000 on Max. ### GET /v1/markets/screener Screen a bounded liquid stock and crypto universe by momentum, trend, RSI, volatility, and dollar volume. Authorization: API key with `read` scope. Rate-limit bucket: `research`. Query parameters: - `kind` (string, optional): optional stock|crypto filter [default ""] - `limit` (integer, optional) [minimum 1; default 25] Error statuses: 400 Invalid request; 401 Missing or invalid API key; 403 Scope, policy, or live-trading restriction; 404 Owned resource not found; 409 State or idempotency conflict; 422 Request body failed schema validation; 429 Rate limit or durable quota exceeded; 500 Internal failure; 502 Venue or provider failure; 503 Required dependency unavailable; 504 Request timeout. ### GET /v1/markets/earnings Return upcoming earnings dates and estimates from the delayed market-data feed for a bounded liquid-stock universe. Authorization: API key with `read` scope. Rate-limit bucket: `research`. Query parameters: - `limit` (integer, optional) [minimum 1; default 15] Error statuses: 400 Invalid request; 401 Missing or invalid API key; 403 Scope, policy, or live-trading restriction; 404 Owned resource not found; 409 State or idempotency conflict; 422 Request body failed schema validation; 429 Rate limit or durable quota exceeded; 500 Internal failure; 502 Venue or provider failure; 503 Required dependency unavailable; 504 Request timeout. ### GET /v1/markets/fundamentals/{symbol} Return period-labelled company fundamentals with live or trailing-twelve-month snapshots and filed figures kept separate, never blended. Authorization: API key with `read` scope. Rate-limit bucket: `market`. Path parameters: - `symbol` (string, required) Error statuses: 400 Invalid request; 401 Missing or invalid API key; 403 Scope, policy, or live-trading restriction; 404 Owned resource not found; 409 State or idempotency conflict; 422 Request body failed schema validation; 429 Rate limit or durable quota exceeded; 500 Internal failure; 502 Venue or provider failure; 503 Required dependency unavailable; 504 Request timeout. ## Equity options flow Equity option chains and options flow are delayed decision support, not tape-level sweep data. Responses carry `data_class: delayed_decision_support`. Tradeable crypto options remain under `GET /v1/options/{underlying}`. ### GET /v1/equity-options/{symbol} Return a normalized, delayed consolidated equity-option chain for a stock or ETF. Authorization: API key with `read` scope. Rate-limit bucket: `research`. Path parameters: - `symbol` (string, required) Query parameters: - `max_expiries` (integer, optional) [minimum 1; maximum 4; default 2] - `limit` (integer, optional) [minimum 1; default 150] Error statuses: 400 Invalid request; 401 Missing or invalid API key; 403 Scope, policy, or live-trading restriction; 404 Owned resource not found; 409 State or idempotency conflict; 422 Request body failed schema validation; 429 Rate limit or durable quota exceeded; 500 Internal failure; 502 Venue or provider failure; 503 Required dependency unavailable; 504 Request timeout. ### POST /v1/options-flow Scan delayed consolidated equity-option chains for unusual volume, open interest, and premium across up to the tier's symbol allowance. Authorization: API key with `read` scope. Rate-limit bucket: `research`. Request body (JSON): - `symbols` (array of string, optional): Optional deduplicated ticker universe. Omit to use the bounded default universe. [at most 20 items] - `side` (string, optional): Optional contract side filter. [one of "call", "put"] - `min_premium` (integer, optional): Minimum estimated premium in USD. [minimum 1000; maximum 100000000; default 50000] - `min_vol_oi` (number, optional): Minimum volume/open-interest ratio. [minimum 0.5; maximum 100; default 2] - `min_volume` (integer, optional): Minimum contract volume. [minimum 10; maximum 1000000; default 200] - `limit` (integer, optional): Maximum delayed decision-support rows. Tier limits also apply. [minimum 1; maximum 100; default 30] Error statuses: 400 Invalid request; 401 Missing or invalid API key; 403 Scope, policy, or live-trading restriction; 404 Owned resource not found; 409 State or idempotency conflict; 422 Request body failed schema validation; 429 Rate limit or durable quota exceeded; 500 Internal failure; 502 Venue or provider failure; 503 Required dependency unavailable; 504 Request timeout. ```json options-flow request body { "symbols": ["SPY", "NVDA", "TSLA"], "side": "call", "min_premium": 50000, "min_vol_oi": 2, "min_volume": 200, "limit": 30 } ``` The symbol allowance per scan is 8 on Free and 20 on Pro and Max. --- # API reference: Orders Source: https://felix.trade/docs/api/orders > Preview and place real-money orders, batch them, inspect an ambiguous intent, cancel resting orders, and trigger the emergency stop. One order shape covers crypto perpetuals, equity perpetuals, spot, and options. Prediction markets use the client-signed flow in [Prediction-market orders](https://felix.trade/docs/api/prediction-market-orders). Felix's trading fee is in [Fees](https://felix.trade/docs/overview/fees); the preview returns the exact amount. Live orders through this endpoint are immediate-or-cancel market orders. `type` accepts `market`; a `limit` order is refused with `live_limit_orders_unavailable`. Every placement requires an `Idempotency-Key`. ## Preview and place ### POST /v1/orders/preview Resolve the instrument and return the estimated fill, exact fee, live minimum, collateral and leverage requirements, and liquidity without moving money. Authorization: API key with `read` scope. Rate-limit bucket: `market`. Request body (JSON, required): - `instrument` (string, required): Canonical symbol or Felix instrument, for example BTC, NVDA, option:BTC-..., or pm:. [at least 1 character; at most 180 characters] - `side` (string, required): Order direction or outcome. [one of "buy", "sell", "long", "short", "yes", "no"] - `size_usd` (number, required): USD notional. [greater than 0] - `type` (string, optional): Execution type. Public real-money execution currently supports market orders. [one of "market"; default "market"] - `reduce_only` (boolean, optional): Only reduce an existing live position when the venue supports it. [default false] - `allow_leverage` (boolean, optional): Explicitly permit Hyperliquid notional above free collateral. Omitted or false blocks leveraged exposure. [default false] Error statuses: 400 Invalid request; 401 Missing or invalid API key; 403 Scope, policy, or live-trading restriction; 404 Owned resource not found; 409 State or idempotency conflict; 422 Request body failed schema validation; 429 Rate limit or durable quota exceeded; 500 Internal failure; 502 Venue or provider failure; 503 Required dependency unavailable; 504 Request timeout. ```json preview response { "est_fill_price": 61825.5, "fee": { "fee_usd": 0.04, "bps": 8 }, "min_live_size_usd": 10 } ``` ### POST /v1/orders Place a real-money market order with an owner-authorized live key and return the fill, fee, canonical instrument, order id, and position id. Authorization: API key with `trade` scope. Rate-limit bucket: `order`. `Idempotency-Key` header: required. Request body (JSON, required): - `instrument` (string, required): Canonical symbol or Felix instrument, for example BTC, NVDA, option:BTC-..., or pm:. [at least 1 character; at most 180 characters] - `side` (string, required): Order direction or outcome. [one of "buy", "sell", "long", "short", "yes", "no"] - `size_usd` (number, required): USD notional. [greater than 0] - `type` (string, optional): Execution type. Public real-money execution currently supports market orders. [one of "market"; default "market"] - `reduce_only` (boolean, optional): Only reduce an existing live position when the venue supports it. [default false] - `allow_leverage` (boolean, optional): Explicitly permit Hyperliquid notional above free collateral. Omitted or false blocks leveraged exposure. [default false] Error statuses: 400 Invalid request; 401 Missing or invalid API key; 403 Scope, policy, or live-trading restriction; 404 Owned resource not found; 409 State or idempotency conflict; 422 Request body failed schema validation; 429 Rate limit or durable quota exceeded; 500 Internal failure; 502 Venue or provider failure; 503 Required dependency unavailable; 504 Request timeout. ```json order response { "ok": true, "mode": "live", "status": "filled", "fill_price": 61825.5, "filled_size_usd": 50, "fee": { "fee_usd": 0.04 }, "canonical_instrument": "crypto:BTC", "order_id": "...", "position_id": "..." } ``` ### POST /v1/orders/batch Place 1 to 50 live orders in one request; each item gets its own idempotency identity and processing stops after the first failure. Authorization: API key with `trade` scope. Rate-limit bucket: `order`. `Idempotency-Key` header: required. Request body (JSON, required): - `mode` (string, required): Required real-money execution mode for the entire batch. [one of "live"; default "live"] - `orders` (array of object, required): One to 50 unleveraged, open-only real-money orders; the caller's current order-rate budget can impose a lower maximum. Venue quotes, minimums, economics, cumulative collateral, and portfolio constraints are preflighted as one set, but venue execution is sequential and not atomic. [at least 1 item; at most 50 items] - `instrument` (string, required): Canonical symbol or Felix instrument, for example BTC, NVDA, option:BTC-..., or pm:. [at least 1 character; at most 180 characters] - `side` (string, required): Order direction or outcome. [one of "buy", "sell", "long", "short", "yes", "no"] - `size_usd` (number, required): USD notional. [greater than 0] - `type` (string, optional): Execution type. Public real-money execution currently supports market orders. [one of "market"; default "market"] - `reduce_only` (boolean, optional): Only reduce an existing live position when the venue supports it. [default false] - `allow_leverage` (boolean, optional): Explicitly permit Hyperliquid notional above free collateral. Omitted or false blocks leveraged exposure. [default false] Error statuses: 400 Invalid request; 401 Missing or invalid API key; 403 Scope, policy, or live-trading restriction; 404 Owned resource not found; 409 State or idempotency conflict; 422 Request body failed schema validation; 429 Rate limit or durable quota exceeded; 500 Internal failure; 502 Venue or provider failure; 503 Required dependency unavailable; 504 Request timeout. ## Reconcile ### POST /v1/orders/replay Inspect the saved state of one exact caller-owned order key before client-side funding, without sending anything. Authorization: API key with `trade` scope. Rate-limit bucket: `read`. `Idempotency-Key` header: required. Request body (JSON, required): - `kind` (string, required): Exact server order journal to inspect before client-side funding. [one of "direct", "polymarket"] - `order` (object, required): The exact normalized order body used by the matching order endpoint. This inspection is read-only and key-scoped. - `instrument` (string, optional): Canonical symbol or Felix instrument, for example BTC, NVDA, option:BTC-..., or pm:. [at least 1 character; at most 180 characters] - `side` (string, optional): Order direction or outcome. [one of "buy", "sell", "long", "short", "yes", "no"] - `size_usd` (number, optional): USD notional. [greater than 0] - `type` (string, optional): Execution type. Public real-money execution currently supports market orders. [one of "market"; default "market"] - `reduce_only` (boolean, optional): Only reduce an existing live position when the venue supports it. [default false] - `allow_leverage` (boolean, optional): Explicitly permit Hyperliquid notional above free collateral. Omitted or false blocks leveraged exposure. [default false] - `client_reconciliation` (string, optional): Required exact client reconciliation contract for Polymarket preparations. [one of "builder_order_v1"] Error statuses: 400 Invalid request; 401 Missing or invalid API key; 403 Scope, policy, or live-trading restriction; 404 Owned resource not found; 409 State or idempotency conflict; 422 Request body failed schema validation; 429 Rate limit or durable quota exceeded; 500 Internal failure; 502 Venue or provider failure; 503 Required dependency unavailable; 504 Request timeout. ### GET /v1/orders/intents/{intent_id} Return recovery-safe status for one direct live order, including whether it is safe to retry with the same key. Authorization: API key with `trade` scope. Rate-limit bucket: `reconcile`. Path parameters: - `intent_id` (string, required) Error statuses: 400 Invalid request; 401 Missing or invalid API key; 403 Scope, policy, or live-trading restriction; 404 Owned resource not found; 409 State or idempotency conflict; 422 Request body failed schema validation; 429 Rate limit or durable quota exceeded; 500 Internal failure; 502 Venue or provider failure; 503 Required dependency unavailable; 504 Request timeout. ## Cancel ### DELETE /v1/orders/{order_id} Request cancellation of an open resting order owned by the caller. Authorization: API key with `trade` scope. Rate-limit bucket: `safety`. Path parameters: - `order_id` (string, required) Error statuses: 400 Invalid request; 401 Missing or invalid API key; 403 Scope, policy, or live-trading restriction; 404 Owned resource not found; 409 State or idempotency conflict; 422 Request body failed schema validation; 429 Rate limit or durable quota exceeded; 500 Internal failure; 502 Venue or provider failure; 503 Required dependency unavailable; 504 Request timeout. ## Liquidity provision ### POST /v1/quotes/make Submit a bounded two-sided resting quote. Reserved: live use is disabled until compensated two-leg execution ships. Authorization: API key with `trade` scope. Rate-limit bucket: `order`. `Idempotency-Key` header: required. Request body (JSON, required): - `instrument` (string, required): Canonical symbol or Felix instrument, for example BTC, NVDA, option:BTC-..., or pm:. [at least 1 character; at most 180 characters] - `bid_price` (number, required): Bid price. [minimum 0] - `ask_price` (number, required): Ask price; must exceed bid_price. [greater than 0] - `size` (number, required): Quote size. [greater than 0] Error statuses: 400 Invalid request; 401 Missing or invalid API key; 403 Scope, policy, or live-trading restriction; 404 Owned resource not found; 409 State or idempotency conflict; 422 Request body failed schema validation; 429 Rate limit or durable quota exceeded; 500 Internal failure; 502 Venue or provider failure; 503 Required dependency unavailable; 504 Request timeout. ## Emergency stop ### POST /v1/panic Engage the account kill switch, pause every agent, revoke every active key, cancel open orders, and close positions where possible. Requires confirm set to true. Authorization: API key with `trade` scope. Rate-limit bucket: `panic`. Request body (JSON): - `confirm` (string, required): Human-provided emergency confirmation phrase. Felix never reveals it in errors. [at least 1 character] Error statuses: 400 Invalid request; 401 Missing or invalid API key; 403 Scope, policy, or live-trading restriction; 404 Owned resource not found; 409 State or idempotency conflict; 422 Request body failed schema validation; 429 Rate limit or durable quota exceeded; 500 Internal failure; 502 Venue or provider failure; 503 Required dependency unavailable; 504 Request timeout. ```json panic request body { "confirm": true } ``` Panic revokes every key on the account, including the one that called it. It does not revoke on-chain token approvals and cannot guarantee every position closes, for example on a venue that is down. Check positions and `GET /v1/money` afterwards. See [Security](https://felix.trade/docs/overview/security). --- # API reference: Positions and exit plans Source: https://felix.trade/docs/api/positions > Read open positions, close them, poll asynchronous closes, and manage server-monitored exit plans. Positions are venue truth for live funds, scoped to the caller's account. After any order attempt, read positions and fills before deciding anything else. Exit plans are server-monitored, reduce-only exits on perpetuals and options positions. They cannot fire while the position's venue is down. ## Positions ### GET /v1/positions List open positions with live unrealized PnL, scoped to the key's account. Authorization: API key with `read` scope. Error statuses: 400 Invalid request; 401 Missing or invalid API key; 403 Scope, policy, or live-trading restriction; 404 Owned resource not found; 409 State or idempotency conflict; 429 Rate limit or durable quota exceeded; 500 Internal failure; 502 Venue or provider failure; 503 Required dependency unavailable; 504 Request timeout. ### POST /v1/positions/{position_id}/close Close a caller-owned position reduce-only. Option closes return an asynchronous operation to poll. Authorization: API key with `trade` scope. Rate-limit bucket: `safety`. `Idempotency-Key` header: required. Path parameters: - `position_id` (string, required) Error statuses: 400 Invalid request; 401 Missing or invalid API key; 403 Scope, policy, or live-trading restriction; 404 Owned resource not found; 409 State or idempotency conflict; 422 Request body failed schema validation; 429 Rate limit or durable quota exceeded; 500 Internal failure; 502 Venue or provider failure; 503 Required dependency unavailable; 504 Request timeout. ### GET /v1/close-operations/{operation_id} Poll one asynchronous close by its operation id without resubmitting it. Authorization: API key with `read` scope. Rate-limit bucket: `read`. Path parameters: - `operation_id` (string, required) Error statuses: 400 Invalid request; 401 Missing or invalid API key; 403 Scope, policy, or live-trading restriction; 404 Owned resource not found; 409 State or idempotency conflict; 422 Request body failed schema validation; 429 Rate limit or durable quota exceeded; 500 Internal failure; 502 Venue or provider failure; 503 Required dependency unavailable; 504 Request timeout. ## Exit plans An exit plan replaces any existing plan on the position and is one-cancels-other across its rules. Rules are decimal fractions of entry: `0.05` means five percent. ### PUT /v1/positions/{position_id}/exit-plan Create or replace one encrypted, server-monitored exit plan with any combination of stop loss, take profit, trailing stop, break-even, and maximum holding time. Authorization: API key with `trade` scope. Rate-limit bucket: `safety`. `Idempotency-Key` header: required. Path parameters: - `position_id` (string, required) Request body (JSON, required): - `stop_loss_pct` (number, optional): Loss fraction from entry, e.g. 0.05 for 5%. [minimum 0.001; maximum 0.99] - `take_profit_pct` (number, optional): Profit fraction from entry, e.g. 0.10 for 10%. [minimum 0.001; maximum 10] - `trailing_stop_pct` (number, optional): Trailing distance as a decimal fraction. [minimum 0.001; maximum 0.99] - `trailing_activation_pct` (number, optional): Profit fraction required before trailing protection arms. [minimum 0; maximum 10] - `break_even_after_pct` (number, optional): Profit fraction that activates a break-even exit. [minimum 0.001; maximum 10] - `max_holding_minutes` (number, optional): Maximum position age in minutes. [minimum 1; maximum 525600] Error statuses: 400 Invalid request; 401 Missing or invalid API key; 403 Scope, policy, or live-trading restriction; 404 Owned resource not found; 409 State or idempotency conflict; 422 Request body failed schema validation; 429 Rate limit or durable quota exceeded; 500 Internal failure; 502 Venue or provider failure; 503 Required dependency unavailable; 504 Request timeout. ### GET /v1/positions/{position_id}/exit-plan Read the exit plan attached to one owned position. Authorization: API key with `read` scope. Rate-limit bucket: `market`. Path parameters: - `position_id` (string, required) Error statuses: 400 Invalid request; 401 Missing or invalid API key; 403 Scope, policy, or live-trading restriction; 404 Owned resource not found; 409 State or idempotency conflict; 422 Request body failed schema validation; 429 Rate limit or durable quota exceeded; 500 Internal failure; 502 Venue or provider failure; 503 Required dependency unavailable; 504 Request timeout. ### DELETE /v1/positions/{position_id}/exit-plan Cancel an armed exit plan. A plan that is already triggering cannot be cancelled. Authorization: API key with `trade` scope. Rate-limit bucket: `safety`. `Idempotency-Key` header: required. Path parameters: - `position_id` (string, required) Error statuses: 400 Invalid request; 401 Missing or invalid API key; 403 Scope, policy, or live-trading restriction; 404 Owned resource not found; 409 State or idempotency conflict; 422 Request body failed schema validation; 429 Rate limit or durable quota exceeded; 500 Internal failure; 502 Venue or provider failure; 503 Required dependency unavailable; 504 Request timeout. ### GET /v1/exit-plans List this account's exit plans and their trigger state. Authorization: API key with `read` scope. Rate-limit bucket: `market`. Query parameters: - `status` (string, nullable, optional) - `limit` (integer, optional) [default 100] Error statuses: 400 Invalid request; 401 Missing or invalid API key; 403 Scope, policy, or live-trading restriction; 404 Owned resource not found; 409 State or idempotency conflict; 422 Request body failed schema validation; 429 Rate limit or durable quota exceeded; 500 Internal failure; 502 Venue or provider failure; 503 Required dependency unavailable; 504 Request timeout. --- # API reference: Reporting Source: https://felix.trade/docs/api/reporting > Balances, the money map, deposit address, portfolio, fills, PnL, and insights, all scoped to the key's account and honest about unavailable sources. Reporting endpoints read venue and chain state. Each response marks its sources available or unavailable. An unavailable source is left out of totals and means unknown, never zero. ## Money ### GET /v1/money Return every location a balance can sit, what each is for, and which call moves it, with gas separated and unverifiable sources named as unavailable. Authorization: API key with `read` scope. Query parameters: - `account_id` (string, nullable, optional) - `wait_for_complete` (boolean, optional) [default false] Error statuses: 400 Invalid request; 401 Missing or invalid API key; 403 Scope, policy, or live-trading restriction; 404 Owned resource not found; 409 State or idempotency conflict; 422 Request body failed schema validation; 429 Rate limit or durable quota exceeded; 500 Internal failure; 502 Venue or provider failure; 503 Required dependency unavailable; 504 Request timeout. Locations include the Arc home Safe, agent capital accounts (treasury and each venue), prediction-market wallets and positions, and open positions. A location whose source could not be read is listed under `unavailable` and `complete` is false. ```json money map response { "total_usd": 24.75, "complete": true, "locations": [ { "name": "arc_home_safe", "chain": "arc", "asset": "USDC", "usd": 2.11 }, { "name": "agent_capital_treasury", "chain": "arc", "asset": "USDC", "usd": 0.16 }, { "name": "agent_capital_hyperliquid", "usd": 9.34 }, { "name": "prediction_agent_wallet", "asset": "pUSD", "usd": 1.81 }, { "name": "prediction_market_positions", "usd": 0.25 }, { "name": "open_positions", "usd": 21.05, "note": "Notional of open positions; not added to total." } ], "unavailable": [] } ``` Pass `wait_for_complete=true` to wait through the bounded refresh of slower venue reads instead of receiving a fast snapshot with explicit freshness. ### GET /v1/balances Return venue collateral with reservations, owner wallet cash, and the live key's daily usage. Authorization: API key with `read` scope. Error statuses: 400 Invalid request; 401 Missing or invalid API key; 403 Scope, policy, or live-trading restriction; 404 Owned resource not found; 409 State or idempotency conflict; 429 Rate limit or durable quota exceeded; 500 Internal failure; 502 Venue or provider failure; 503 Required dependency unavailable; 504 Request timeout. ### GET /v1/deposit-address Return the owner wallet's Polygon deposit address for accounts that still use a Polygon owner wallet. Arc home deposits are in [Balance](https://felix.trade/docs/api/balance). Authorization: API key with `read` scope. Error statuses: 400 Invalid request; 401 Missing or invalid API key; 403 Scope, policy, or live-trading restriction; 404 Owned resource not found; 409 State or idempotency conflict; 429 Rate limit or durable quota exceeded; 500 Internal failure; 502 Venue or provider failure; 503 Required dependency unavailable; 504 Request timeout. ## Performance ### GET /v1/portfolio Return the portfolio summary with live balances and deployed capital. Authorization: API key with `read` scope. Error statuses: 400 Invalid request; 401 Missing or invalid API key; 403 Scope, policy, or live-trading restriction; 404 Owned resource not found; 409 State or idempotency conflict; 429 Rate limit or durable quota exceeded; 500 Internal failure; 502 Venue or provider failure; 503 Required dependency unavailable; 504 Request timeout. ### GET /v1/fills Return every fill on the account, entries and exits, with price, size, fee, and realized PnL. Authorization: API key with `read` scope. Query parameters: - `limit` (integer, optional) [default 100] Error statuses: 400 Invalid request; 401 Missing or invalid API key; 403 Scope, policy, or live-trading restriction; 404 Owned resource not found; 409 State or idempotency conflict; 422 Request body failed schema validation; 429 Rate limit or durable quota exceeded; 500 Internal failure; 502 Venue or provider failure; 503 Required dependency unavailable; 504 Request timeout. ### GET /v1/pnl Return realized PnL on closed positions, unrealized PnL on open positions marked live, fees, net PnL, and position counts. Authorization: API key with `read` scope. Error statuses: 400 Invalid request; 401 Missing or invalid API key; 403 Scope, policy, or live-trading restriction; 404 Owned resource not found; 409 State or idempotency conflict; 429 Rate limit or durable quota exceeded; 500 Internal failure; 502 Venue or provider failure; 503 Required dependency unavailable; 504 Request timeout. ```json PnL response { "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 } ``` ### GET /v1/pnl/history Return the account's complete realized live PnL history in one bounded read. Authorization: API key with `read` scope. Error statuses: 400 Invalid request; 401 Missing or invalid API key; 403 Scope, policy, or live-trading restriction; 404 Owned resource not found; 409 State or idempotency conflict; 429 Rate limit or durable quota exceeded; 500 Internal failure; 502 Venue or provider failure; 503 Required dependency unavailable; 504 Request timeout. ### GET /v1/account/statement Return a stable, pageable trade ledger for reconciliation and exports. Authorization: API key with `read` scope. Query parameters: - `limit` (integer, optional) [default 100] - `cursor` (string, optional) [default ""] Error statuses: 400 Invalid request; 401 Missing or invalid API key; 403 Scope, policy, or live-trading restriction; 404 Owned resource not found; 409 State or idempotency conflict; 422 Request body failed schema validation; 429 Rate limit or durable quota exceeded; 500 Internal failure; 502 Venue or provider failure; 503 Required dependency unavailable; 504 Request timeout. ### GET /v1/insights Return aggregate, anonymized market and strategy insights derived from platform telemetry. Authorization: API key with `read` scope. Error statuses: 400 Invalid request; 401 Missing or invalid API key; 403 Scope, policy, or live-trading restriction; 404 Owned resource not found; 409 State or idempotency conflict; 429 Rate limit or durable quota exceeded; 500 Internal failure; 502 Venue or provider failure; 503 Required dependency unavailable; 504 Request timeout. For the one-call operating snapshot that combines agents, positions, money, and pending operations, see `GET /v1/situation` in [Agents](https://felix.trade/docs/api/agents). --- # API reference: Balance Source: https://felix.trade/docs/api/balance > Set up the Arc home, read its balances, deposit into it, withdraw from it, and track or recover each operation. An account's balance is USDC on the Arc network, held in a Safe whose only owner is the account's owner key. This Safe is the Arc home. Felix never signs for it: every route here prepares an exact transaction or message, the owner signs it on the client, and Felix relays it and pays the gas. Money workflows on this page need the `transfer` scope and an `Idempotency-Key`. Setup needs `manage`. During a release, new Arc home money workflows can be paused for a few minutes and return `409 arc_admission_frozen`; reads and recovery keep working. ## Set up the Arc home The Safe address is derived from the owner address, so it is the same on every device and can be computed before it exists. ### POST /v1/arc-home/onboarding/init Start Arc home setup from the owner address and return the proof the owner must sign. Authorization: API key with `manage` scope. Rate-limit bucket: `manage`. Request body (JSON, required): - `account_id` (string, optional): Target isolated account UUID. Omit to use the key's own account. [matches ^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$] - `owner_address` (string, required): The account's client-held owner EOA. [matches ^0x[0-9a-fA-F]{40}$] - `home_address` (string, optional): Agent sweep home; must equal owner_address. [matches ^0x[0-9a-fA-F]{40}$] - `max_operation_usd` (string, optional): Exact USDC amount with at most six decimals. [matches ^(0|[1-9][0-9]{0,12})(\.[0-9]{1,6})?$] - `daily_limit_usd` (string, optional): Exact USDC amount with at most six decimals. [matches ^(0|[1-9][0-9]{0,12})(\.[0-9]{1,6})?$] - `lifetime_limit_usd` (string, optional): Exact USDC amount with at most six decimals. [matches ^(0|[1-9][0-9]{0,12})(\.[0-9]{1,6})?$] - `delegation_days` (integer, optional): Delegation window in days. [minimum 1; maximum 90] Error statuses: 400 Invalid request; 401 Missing or invalid API key; 403 Scope, policy, or live-trading restriction; 404 Owned resource not found; 409 State or idempotency conflict; 422 Request body failed schema validation; 429 Rate limit or durable quota exceeded; 500 Internal failure; 502 Venue or provider failure; 503 Required dependency unavailable; 504 Request timeout. ### POST /v1/arc-home/onboarding/deploy Verify the owner proof and deploy the Safe. Retry the identical call while the status is pending. Authorization: API key with `manage` scope. Rate-limit bucket: `transfer`. Request body (JSON, required): - `account_id` (string, optional): Target isolated account UUID. Omit to use the key's own account. [matches ^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$] - `challenge_token` (string, required): Sealed challenge from onboarding/init. [at most 8192 characters] - `proof_signature` (string, required): Owner's personal_sign signature over proof_message. [matches ^0x[0-9a-fA-F]{130}$] Error statuses: 400 Invalid request; 401 Missing or invalid API key; 403 Scope, policy, or live-trading restriction; 404 Owned resource not found; 409 State or idempotency conflict; 422 Request body failed schema validation; 429 Rate limit or durable quota exceeded; 500 Internal failure; 502 Venue or provider failure; 503 Required dependency unavailable; 504 Request timeout. ### POST /v1/arc-home/onboarding/complete Finish activation with the owner's signatures. Retry the identical call while the status is pending. Authorization: API key with `manage` scope. Rate-limit bucket: `transfer`. Request body (JSON, required): - `account_id` (string, optional): Target isolated account UUID. Omit to use the key's own account. [matches ^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$] - `activation_token` (string, required): Sealed activation from onboarding/deploy. [at most 8192 characters] - `signature` (string, required): Owner's EIP-712 SafeTx signature over typed_data. [matches ^0x[0-9a-fA-F]{130}$] Error statuses: 400 Invalid request; 401 Missing or invalid API key; 403 Scope, policy, or live-trading restriction; 404 Owned resource not found; 409 State or idempotency conflict; 422 Request body failed schema validation; 429 Rate limit or durable quota exceeded; 500 Internal failure; 502 Venue or provider failure; 503 Required dependency unavailable; 504 Request timeout. ### GET /v1/arc-home/capabilities Report which Arc home workflows this account can use and its setup stage. Authorization: API key with `read` scope. Rate-limit bucket: `read`. Error statuses: 400 Invalid request; 401 Missing or invalid API key; 403 Scope, policy, or live-trading restriction; 404 Owned resource not found; 409 State or idempotency conflict; 429 Rate limit or durable quota exceeded; 500 Internal failure; 502 Venue or provider failure; 503 Required dependency unavailable; 504 Request timeout. ### GET /v1/arc-home/account Return the account's Arc home Safe, owner, and setup state. Authorization: API key with `read` scope. Rate-limit bucket: `read`. Query parameters: - `account_id` (string, nullable, optional) Error statuses: 400 Invalid request; 401 Missing or invalid API key; 403 Scope, policy, or live-trading restriction; 404 Owned resource not found; 409 State or idempotency conflict; 422 Request body failed schema validation; 429 Rate limit or durable quota exceeded; 500 Internal failure; 502 Venue or provider failure; 503 Required dependency unavailable; 504 Request timeout. ## Read balances ### GET /v1/arc-home/balances Return the Safe's balances, read at one finalized block. Authorization: API key with `read` scope. Rate-limit bucket: `read`. Query parameters: - `account_id` (string, nullable, optional) Error statuses: 400 Invalid request; 401 Missing or invalid API key; 403 Scope, policy, or live-trading restriction; 404 Owned resource not found; 409 State or idempotency conflict; 422 Request body failed schema validation; 429 Rate limit or durable quota exceeded; 500 Internal failure; 502 Venue or provider failure; 503 Required dependency unavailable; 504 Request timeout. For every location an account's money can sit, including agent capital and venues, use `GET /v1/money` in [Reporting](https://felix.trade/docs/api/reporting). ## Deposit The simplest deposit is a plain USDC transfer on Arc to the Arc home address. It needs no Felix workflow. From an owner wallet on Ethereum, Arbitrum, Base, or Polygon, use the deposit workflow below. It moves native USDC through Circle's cross-chain transfer and mints it into the Arc home. The Felix app also offers a deposit address that accepts many tokens on many chains through Relay; that address is valid for 30 minutes and is described in [Deposits and withdrawals](https://felix.trade/docs/guides/deposits-and-withdrawals). ### GET /v1/deposit-assets Public list of settlement assets and deposit support. No key required, and nothing is created. Authorization: No API key. Error statuses: 400 Invalid request; 401 Missing or invalid API key; 403 Scope, policy, or live-trading restriction; 404 Owned resource not found; 409 State or idempotency conflict; 429 Rate limit or durable quota exceeded; 500 Internal failure; 502 Venue or provider failure; 503 Required dependency unavailable; 504 Request timeout. ### POST /v1/arc-home/deposits/prepare Prepare a deposit from an owner wallet on Ethereum, Arbitrum, Base, or Polygon, with the source transactions to sign and a fee ceiling. Authorization: API key with `transfer` scope. Rate-limit bucket: `transfer`. `Idempotency-Key` header: required. Request body (JSON, required): - `account_id` (string, optional): Target isolated account UUID. Omit to use the key's own account. [matches ^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$] - `source_chain` (string, required): Source chain. [one of "arbitrum", "base", "ethereum", "polygon"] - `amount` (string, required): Exact USDC amount with at most six decimals. [matches ^(0|[1-9][0-9]{0,12})(\.[0-9]{1,6})?$] - `max_fee_units` (string, optional): Gateway fee ceiling in six-decimal USDC integer units. [matches ^[0-9]{1,8}$] Error statuses: 400 Invalid request; 401 Missing or invalid API key; 403 Scope, policy, or live-trading restriction; 404 Owned resource not found; 409 State or idempotency conflict; 422 Request body failed schema validation; 429 Rate limit or durable quota exceeded; 500 Internal failure; 502 Venue or provider failure; 503 Required dependency unavailable; 504 Request timeout. ### POST /v1/arc-home/operations/{operation_id}/source-authorize Return a short-lived token that lets the client relay this deposit's source-chain calls through Felix. Authorization: API key with `transfer` scope. Rate-limit bucket: `transfer`. Path parameters: - `operation_id` (string, required) Request body (JSON, required): - `account_id` (string, optional): Target isolated account UUID. Omit to use the key's own account. [matches ^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$] Error statuses: 400 Invalid request; 401 Missing or invalid API key; 403 Scope, policy, or live-trading restriction; 404 Owned resource not found; 409 State or idempotency conflict; 422 Request body failed schema validation; 429 Rate limit or durable quota exceeded; 500 Internal failure; 502 Venue or provider failure; 503 Required dependency unavailable; 504 Request timeout. ### POST /v1/arc-home/deposits/{operation_id}/source-submitted Record the owner's source-chain transaction hash. Authorization: API key with `transfer` scope. Rate-limit bucket: `transfer`. Path parameters: - `operation_id` (string, required) Request body (JSON, required): - `account_id` (string, optional): Target isolated account UUID. Omit to use the key's own account. [matches ^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$] - `source_tx_hash` (string, optional): Owner's source-chain GatewayWallet.deposit transaction hash. Omit when source_calls is empty and existing Gateway balance covers the transfer. [matches ^0x[0-9a-fA-F]{64}$] - `burn_intent_signature` (string, required): Owner's EIP-712 burn-intent signature. [matches ^0x[0-9a-fA-F]{130}$] Error statuses: 400 Invalid request; 401 Missing or invalid API key; 403 Scope, policy, or live-trading restriction; 404 Owned resource not found; 409 State or idempotency conflict; 422 Request body failed schema validation; 429 Rate limit or durable quota exceeded; 500 Internal failure; 502 Venue or provider failure; 503 Required dependency unavailable; 504 Request timeout. ### POST /v1/arc-home/operations/{operation_id}/mint-authorize Return a short-lived token for this operation's stored mint call. Authorization: API key with `transfer` scope. Rate-limit bucket: `transfer`. Path parameters: - `operation_id` (string, required) Request body (JSON, required): - `account_id` (string, optional): Target isolated account UUID. Omit to use the key's own account. [matches ^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$] - `revision` (integer, required): Exact current operation revision. Stale revisions are refused before a relay capability is issued. [minimum 0] Error statuses: 400 Invalid request; 401 Missing or invalid API key; 403 Scope, policy, or live-trading restriction; 404 Owned resource not found; 409 State or idempotency conflict; 422 Request body failed schema validation; 429 Rate limit or durable quota exceeded; 500 Internal failure; 502 Venue or provider failure; 503 Required dependency unavailable; 504 Request timeout. ### POST /v1/arc-home/operations/{operation_id}/mint-signature Submit the owner's signature for the Arc mint into the Safe. Felix pays the gas. Authorization: API key with `transfer` scope. Rate-limit bucket: `transfer`. Path parameters: - `operation_id` (string, required) Request body (JSON, required): - `account_id` (string, optional): Target isolated account UUID. Omit to use the key's own account. [matches ^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$] - `signature` (string, required): Owner's EIP-712 signature over mint_safe_transaction. [matches ^0x[0-9a-fA-F]{130}$] Error statuses: 400 Invalid request; 401 Missing or invalid API key; 403 Scope, policy, or live-trading restriction; 404 Owned resource not found; 409 State or idempotency conflict; 422 Request body failed schema validation; 429 Rate limit or durable quota exceeded; 500 Internal failure; 502 Venue or provider failure; 503 Required dependency unavailable; 504 Request timeout. ### POST /v1/arc-home/operations/{operation_id}/mint-submitted Record the mint transaction hash. Authorization: API key with `transfer` scope. Rate-limit bucket: `transfer`. Path parameters: - `operation_id` (string, required) Request body (JSON, required): - `account_id` (string, optional): Target isolated account UUID. Omit to use the key's own account. [matches ^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$] - `mint_tx_hash` (string, required): Destination-chain gatewayMint transaction hash. [matches ^0x[0-9a-fA-F]{64}$] Error statuses: 400 Invalid request; 401 Missing or invalid API key; 403 Scope, policy, or live-trading restriction; 404 Owned resource not found; 409 State or idempotency conflict; 422 Request body failed schema validation; 429 Rate limit or durable quota exceeded; 500 Internal failure; 502 Venue or provider failure; 503 Required dependency unavailable; 504 Request timeout. ### GET /v1/arc-home/operations/{operation_id}/arc-credit Read-only proof that the deposit's finalized credit reached the Safe. Authorization: API key with `read` scope. Rate-limit bucket: `read`. Path parameters: - `operation_id` (string, required) Query parameters: - `account_id` (string, nullable, optional) Error statuses: 400 Invalid request; 401 Missing or invalid API key; 403 Scope, policy, or live-trading restriction; 404 Owned resource not found; 409 State or idempotency conflict; 422 Request body failed schema validation; 429 Rate limit or durable quota exceeded; 500 Internal failure; 502 Venue or provider failure; 503 Required dependency unavailable; 504 Request timeout. ## Withdraw A withdrawal goes to an approved destination (see [Withdrawals](https://felix.trade/docs/api/withdrawals)) or to the owner's own address. There are two routes: | Route | Destination | Limits | | --- | --- | --- | | `POST /v1/arc-home/withdrawals/prepare` | Arc, Ethereum, Arbitrum, Base, or Polygon, through Circle's cross-chain transfer | A fee ceiling you set with `max_fee_units`. | | `POST /v1/arc-home/withdrawals/prepare-relay` | Native USDC on Base, Arbitrum, Ethereum, or Polygon, through Relay | $5 to $10,000 per withdrawal. Refused if the quote would deliver less than 99% of the amount. The quote is valid for 5 minutes. | Both return one unsigned Safe transaction. The owner signs it and you submit it with `POST /v1/arc-home/withdrawals/{operation_id}/submit`. ```json withdrawal request body { "chain": "base", "to": "0xYourApprovedAddress", "amount": "25.00" } ``` ### POST /v1/arc-home/withdrawals/prepare Prepare a withdrawal to an approved destination or the owner's own address on Arc, Ethereum, Arbitrum, Base, or Polygon. Authorization: API key with `transfer` scope. Rate-limit bucket: `transfer`. `Idempotency-Key` header: required. Request body (JSON, required): - `account_id` (string, optional): Target isolated account UUID. Omit to use the key's own account. [matches ^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$] - `chain` (string, required): Destination chain. [one of "arc", "arbitrum", "base", "ethereum", "polygon"] - `to` (string, required): Exact owner-signed allowlisted destination for this chain. [matches ^0x[0-9a-fA-F]{40}$] - `amount` (string, required): Exact USDC amount with at most six decimals. [matches ^(0|[1-9][0-9]{0,12})(\.[0-9]{1,6})?$] - `max_fee_units` (string, optional): Gateway fee ceiling in six-decimal USDC integer units. [matches ^[0-9]{1,8}$] Error statuses: 400 Invalid request; 401 Missing or invalid API key; 403 Scope, policy, or live-trading restriction; 404 Owned resource not found; 409 State or idempotency conflict; 422 Request body failed schema validation; 429 Rate limit or durable quota exceeded; 500 Internal failure; 502 Venue or provider failure; 503 Required dependency unavailable; 504 Request timeout. ### POST /v1/arc-home/withdrawals/prepare-relay Quote, verify, and record one Relay withdrawal to native USDC, and return the one unsigned Safe transaction. Authorization: API key with `transfer` scope. Rate-limit bucket: `transfer`. `Idempotency-Key` header: required. Request body (JSON, required): - `account_id` (string, optional): Target isolated account UUID. Omit to use the key's own account. [matches ^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$] - `chain` (string, required): Destination chain. [one of "arbitrum", "base", "ethereum", "polygon"] - `to` (string, required): The account's own wallet or an active allowlisted address on that chain. [matches ^0x[0-9a-fA-F]{40}$] - `amount` (string, required): Exact USDC amount with at most six decimals. [matches ^(0|[1-9][0-9]{0,12})(\.[0-9]{1,6})?$] Error statuses: 400 Invalid request; 401 Missing or invalid API key; 403 Scope, policy, or live-trading restriction; 404 Owned resource not found; 409 State or idempotency conflict; 422 Request body failed schema validation; 429 Rate limit or durable quota exceeded; 500 Internal failure; 502 Venue or provider failure; 503 Required dependency unavailable; 504 Request timeout. ### POST /v1/arc-home/withdrawals/{operation_id}/submit Submit the owner's signature for a prepared withdrawal. Felix relays it and pays the gas. Authorization: API key with `transfer` scope. Rate-limit bucket: `transfer`. `Idempotency-Key` header: required. Path parameters: - `operation_id` (string, required) Request body (JSON, required): - `account_id` (string, optional): Target isolated account UUID. Omit to use the key's own account. [matches ^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$] - `safe_signatures` (object, required): Map of safe_tx_hash to the owner's 65-byte EIP-712 SafeTx signature. - `burn_intent_signature` (string, optional): Owner's EIP-712 burn-intent signature (cross-chain only). [matches ^0x[0-9a-fA-F]{130}$] Error statuses: 400 Invalid request; 401 Missing or invalid API key; 403 Scope, policy, or live-trading restriction; 404 Owned resource not found; 409 State or idempotency conflict; 422 Request body failed schema validation; 429 Rate limit or durable quota exceeded; 500 Internal failure; 502 Venue or provider failure; 503 Required dependency unavailable; 504 Request timeout. ### GET /v1/arc-home/withdrawals/{operation_id}/relay-status Read Relay's delivery status for an executed Relay withdrawal. Advisory; the chain is the final record. Authorization: API key with `read` scope. Rate-limit bucket: `read`. Path parameters: - `operation_id` (string, required) Query parameters: - `account_id` (string, nullable, optional) Error statuses: 400 Invalid request; 401 Missing or invalid API key; 403 Scope, policy, or live-trading restriction; 404 Owned resource not found; 409 State or idempotency conflict; 422 Request body failed schema validation; 429 Rate limit or durable quota exceeded; 500 Internal failure; 502 Venue or provider failure; 503 Required dependency unavailable; 504 Request timeout. ## Track and recover operations Every deposit, withdrawal, and funding is an operation with an id. If a response is lost, list the operations and read the one you need before doing anything else. ### GET /v1/arc-home/operations List this account's Arc home operations, newest first. Authorization: API key with `read` scope. Rate-limit bucket: `read`. Query parameters: - `account_id` (string, nullable, optional) - `limit` (integer, optional) [minimum 1; maximum 50; default 20] Error statuses: 400 Invalid request; 401 Missing or invalid API key; 403 Scope, policy, or live-trading restriction; 404 Owned resource not found; 409 State or idempotency conflict; 422 Request body failed schema validation; 429 Rate limit or durable quota exceeded; 500 Internal failure; 502 Venue or provider failure; 503 Required dependency unavailable; 504 Request timeout. ### GET /v1/arc-home/operations/{operation_id} Read one operation and its current phase. Authorization: API key with `read` scope. Rate-limit bucket: `read`. Path parameters: - `operation_id` (string, required) Query parameters: - `account_id` (string, nullable, optional) Error statuses: 400 Invalid request; 401 Missing or invalid API key; 403 Scope, policy, or live-trading restriction; 404 Owned resource not found; 409 State or idempotency conflict; 422 Request body failed schema validation; 429 Rate limit or durable quota exceeded; 500 Internal failure; 502 Venue or provider failure; 503 Required dependency unavailable; 504 Request timeout. ### POST /v1/arc-home/operations/{operation_id}/reconcile Advance an in-flight operation from chain and transfer evidence. Sends nothing new. Authorization: API key with `transfer` scope. Rate-limit bucket: `transfer`. Path parameters: - `operation_id` (string, required) Request body (JSON): - `account_id` (string, optional): Target isolated account UUID. Omit to use the key's own account. [matches ^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$] Error statuses: 400 Invalid request; 401 Missing or invalid API key; 403 Scope, policy, or live-trading restriction; 404 Owned resource not found; 409 State or idempotency conflict; 422 Request body failed schema validation; 429 Rate limit or durable quota exceeded; 500 Internal failure; 502 Venue or provider failure; 503 Required dependency unavailable; 504 Request timeout. ### POST /v1/arc-home/operations/{operation_id}/cancel Cancel an operation that has not moved money yet. Authorization: API key with `transfer` scope. Rate-limit bucket: `transfer`. Path parameters: - `operation_id` (string, required) Request body (JSON): - `account_id` (string, optional): Target isolated account UUID. Omit to use the key's own account. [matches ^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$] Error statuses: 400 Invalid request; 401 Missing or invalid API key; 403 Scope, policy, or live-trading restriction; 404 Owned resource not found; 409 State or idempotency conflict; 422 Request body failed schema validation; 429 Rate limit or durable quota exceeded; 500 Internal failure; 502 Venue or provider failure; 503 Required dependency unavailable; 504 Request timeout. ## Cancel a signed transaction If the owner signed a Safe transaction that was never executed, you can invalidate it so it can never run later. Felix prepares a transaction that uses up its nonce; the owner signs it, and Felix relays it. ### POST /v1/arc-home/safe-invalidations/prepare Prepare the owner-signable transaction that invalidates one earlier signed but unexecuted Safe transaction. Authorization: API key with `manage` and `transfer` scope. Rate-limit bucket: `transfer`. `Idempotency-Key` header: required. Request body (JSON, required): - `account_id` (string, nullable, optional) - `original_writer` (string, required) [one of "withdrawal_source", "withdrawal_mint", "hypercore", "polygon", "hub_activation"] - `original_operation_id` (string, nullable, optional) - `original_journey_digest` (string, nullable, optional) [matches ^0x[0-9a-fA-F]{64}$] - `original_typed_data` (object, nullable, optional) Error statuses: 400 Invalid request; 401 Missing or invalid API key; 403 Scope, policy, or live-trading restriction; 404 Owned resource not found; 409 State or idempotency conflict; 422 Request body failed schema validation; 429 Rate limit or durable quota exceeded; 500 Internal failure; 502 Venue or provider failure; 503 Required dependency unavailable; 504 Request timeout. ### POST /v1/arc-home/safe-invalidations/{operation_id}/submit Submit the owner's signature and relay the invalidation. Authorization: API key with `manage` and `transfer` scope. Rate-limit bucket: `transfer`. Path parameters: - `operation_id` (string, required) Request body (JSON, required): - `account_id` (string, nullable, optional) - `signature` (string, required) [matches ^0x[0-9a-fA-F]{130}$] Error statuses: 400 Invalid request; 401 Missing or invalid API key; 403 Scope, policy, or live-trading restriction; 404 Owned resource not found; 409 State or idempotency conflict; 422 Request body failed schema validation; 429 Rate limit or durable quota exceeded; 500 Internal failure; 502 Venue or provider failure; 503 Required dependency unavailable; 504 Request timeout. ### POST /v1/arc-home/safe-invalidations/{operation_id}/reconcile Prove from the chain whether the invalidation or the original transaction executed. Authorization: API key with `manage` and `transfer` scope. Rate-limit bucket: `read`. Path parameters: - `operation_id` (string, required) Request body (JSON, required): - `account_id` (string, nullable, optional) - `transaction_hash` (string, nullable, optional) [matches ^0x[0-9a-fA-F]{64}$] - `original` (boolean, optional) [default false] Error statuses: 400 Invalid request; 401 Missing or invalid API key; 403 Scope, policy, or live-trading restriction; 404 Owned resource not found; 409 State or idempotency conflict; 422 Request body failed schema validation; 429 Rate limit or durable quota exceeded; 500 Internal failure; 502 Venue or provider failure; 503 Required dependency unavailable; 504 Request timeout. ### POST /v1/arc-home/safe-invalidations/{operation_id}/close-withdrawal Close the original withdrawal once the invalidation is proven. Authorization: API key with `manage` and `transfer` scope. Rate-limit bucket: `read`. Path parameters: - `operation_id` (string, required) Request body (JSON, required): - `account_id` (string, nullable, optional) - `operation_id` (string, required) - `transaction_hash` (string, required) [matches ^0x[0-9a-fA-F]{64}$] - `outcome` (string, required) [one of "invalidated", "original_success", "original_failure"] Error statuses: 400 Invalid request; 401 Missing or invalid API key; 403 Scope, policy, or live-trading restriction; 404 Owned resource not found; 409 State or idempotency conflict; 422 Request body failed schema validation; 429 Rate limit or durable quota exceeded; 500 Internal failure; 502 Venue or provider failure; 503 Required dependency unavailable; 504 Request timeout. ### POST /v1/arc-home/safe-invalidations/{operation_id}/close-relay Close the original relayed operation once the invalidation is proven. Authorization: API key with `manage` and `transfer` scope. Rate-limit bucket: `read`. Path parameters: - `operation_id` (string, required) Request body (JSON, required): - `account_id` (string, nullable, optional) - `writer` (string, required) [one of "hypercore", "polygon"] - `funding_id` (string, required) - `transaction_hash` (string, required) [matches ^0x[0-9a-fA-F]{64}$] - `outcome` (string, required) [one of "invalidated", "original_failure"] Error statuses: 400 Invalid request; 401 Missing or invalid API key; 403 Scope, policy, or live-trading restriction; 404 Owned resource not found; 409 State or idempotency conflict; 422 Request body failed schema validation; 429 Rate limit or durable quota exceeded; 500 Internal failure; 502 Venue or provider failure; 503 Required dependency unavailable; 504 Request timeout. ### GET /v1/arc-home/safe-invalidations List this account's invalidation operations. Authorization: API key with `read` scope. Rate-limit bucket: `read`. Query parameters: - `account_id` (string, nullable, optional) - `after` (string, nullable, optional) - `limit` (integer, optional) [minimum 1; maximum 50; default 20] Error statuses: 400 Invalid request; 401 Missing or invalid API key; 403 Scope, policy, or live-trading restriction; 404 Owned resource not found; 409 State or idempotency conflict; 422 Request body failed schema validation; 429 Rate limit or durable quota exceeded; 500 Internal failure; 502 Venue or provider failure; 503 Required dependency unavailable; 504 Request timeout. ### GET /v1/arc-home/safe-invalidations/{operation_id} Read one invalidation operation. Authorization: API key with `read` scope. Rate-limit bucket: `read`. Path parameters: - `operation_id` (string, required) Query parameters: - `account_id` (string, nullable, optional) Error statuses: 400 Invalid request; 401 Missing or invalid API key; 403 Scope, policy, or live-trading restriction; 404 Owned resource not found; 409 State or idempotency conflict; 422 Request body failed schema validation; 429 Rate limit or durable quota exceeded; 500 Internal failure; 502 Venue or provider failure; 503 Required dependency unavailable; 504 Request timeout. --- # API reference: Agent capital Source: https://felix.trade/docs/api/agent-capital > Allocate money from the Arc home to the accounts your agents trade from, and move it between those accounts. Agents never spend from the Arc home directly. You allocate an amount to **agent capital**: an agent treasury on Arc plus an account on each venue your agents use. Those accounts belong to your account alone, and their keys are held in Felix's signing enclave. No request can name a recipient: every address is derived for your account. After the allocation, Felix moves money between the treasury and your venue accounts on its own to keep agents funded, returns money that is not being used, and pays the Felix fees your agents owe. You can also move money yourself with the routes below. How agents use this money is in [Run agents](https://felix.trade/docs/guides/run-agents). ## Read ### GET /v1/agent-capital Return the agent capital accounts, balances on the treasury and each venue, the capital state, and recent moves. Authorization: API key with `read` scope. Rate-limit bucket: `read`. Query parameters: - `account_id` (string, nullable, optional) Error statuses: 400 Invalid request; 401 Missing or invalid API key; 403 Scope, policy, or live-trading restriction; 404 Owned resource not found; 409 State or idempotency conflict; 422 Request body failed schema validation; 429 Rate limit or durable quota exceeded; 500 Internal failure; 502 Venue or provider failure; 503 Required dependency unavailable; 504 Request timeout. ```json agent capital response { "ok": true, "capital_state": "active", "balances": { "home_usd": 2.11, "treasury_usd": 0.16, "hyperliquid_account_value_usd": 9.34, "hyperliquid_withdrawable_usd": 7.30, "polymarket_pusd_usd": 1.81, "lighter_account_value_usd": 11.03, "lighter_withdrawable_usd": 8.85 } } ``` `capital_state` is `not_allocated`, `pending` (the first allocation is waiting for the chain), or `active`. ## Allocate from the Arc home An allocation moves money from the Arc home to the agent treasury. It needs one owner signature. 1. Call `POST /v1/agent-capital/allocations/prepare` with an `amount` of at least `1` USDC. 2. The owner signs the one Safe transaction in the response. 3. Submit it with `POST /v1/arc-home/withdrawals/{operation_id}/submit` (see [Balance](https://felix.trade/docs/api/balance)). ### POST /v1/agent-capital/allocations/prepare Prepare an owner-signed transfer from the Arc home to the account's agent treasury. Authorization: API key with `transfer` scope. Rate-limit bucket: `transfer`. `Idempotency-Key` header: required. Request body (JSON, required): - `account_id` (string, optional): Target isolated account UUID. Omit to use the key's own account. [matches ^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$] - `amount` (string, required): Exact USDC amount with at most six decimals. [matches ^(0|[1-9][0-9]{0,12})(\.[0-9]{1,6})?$] Error statuses: 400 Invalid request; 401 Missing or invalid API key; 403 Scope, policy, or live-trading restriction; 404 Owned resource not found; 409 State or idempotency conflict; 422 Request body failed schema validation; 429 Rate limit or durable quota exceeded; 500 Internal failure; 502 Venue or provider failure; 503 Required dependency unavailable; 504 Request timeout. ## Move between your own accounts A move is either `fund` (treasury to a venue) or `bring_home` (a venue to the treasury, or with `destination: "home"`, to the Arc home). `venue` is `hyperliquid`, `polymarket`, `lighter`, `derive`, or `treasury`. No owner signature is needed, because the money never leaves accounts that belong to you. ```json move request body { "venue": "lighter", "direction": "bring_home", "amount_usd": 6, "destination": "home" } ``` | Rule | Value | | --- | --- | | Smallest move | $1 ($5 into Lighter) | | Largest move | $250,000 | | Lighter return | About one minute, with a $1 Lighter fast-withdrawal fee | | Open moves | One at a time per venue; a second is refused with the existing move id | ### POST /v1/agent-capital/moves Move money between the agent treasury and one of your venue accounts, or back to the Arc home. Authorization: API key with `transfer` scope. Rate-limit bucket: `transfer`. `Idempotency-Key` header: required. Request body (JSON, required): - `account_id` (string, optional): Target isolated account UUID. Omit to use the key's own account. [matches ^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$] - `venue` (string, required): Venue account to fund or return from. [one of "hyperliquid", "polymarket", "derive", "treasury"] - `direction` (string, required): fund moves treasury -> venue; bring_home moves venue -> treasury or home. [one of "fund", "bring_home"] - `amount_usd` (number, required): USDC amount, at least 1. [minimum 1] - `destination` (string, optional): Where a bring_home lands. [one of "treasury", "home"] Error statuses: 400 Invalid request; 401 Missing or invalid API key; 403 Scope, policy, or live-trading restriction; 404 Owned resource not found; 409 State or idempotency conflict; 422 Request body failed schema validation; 429 Rate limit or durable quota exceeded; 500 Internal failure; 502 Venue or provider failure; 503 Required dependency unavailable; 504 Request timeout. ### GET /v1/agent-capital/moves/{move_id} Read one move and its state: pending, running, completed, failed, or reconcile_required. Authorization: API key with `read` scope. Rate-limit bucket: `read`. Path parameters: - `move_id` (string, required) Query parameters: - `account_id` (string, nullable, optional) Error statuses: 400 Invalid request; 401 Missing or invalid API key; 403 Scope, policy, or live-trading restriction; 404 Owned resource not found; 409 State or idempotency conflict; 422 Request body failed schema validation; 429 Rate limit or durable quota exceeded; 500 Internal failure; 502 Venue or provider failure; 503 Required dependency unavailable; 504 Request timeout. --- # API reference: Venue funding and returns Source: https://felix.trade/docs/api/venue-funding > Owner-signed workflows that move money from the Arc home to a venue account you own, and from a venue back to the Arc home. These workflows move money between the Arc home and the account's own venue accounts with owner signatures. If the account has [agent capital](https://felix.trade/docs/api/agent-capital), Felix moves agent money between venues for you and you do not need these routes for it. Every workflow follows the same shape: 1. `prepare` quotes the route, records the operation under your `Idempotency-Key`, and returns the exact payloads the owner signs. Nothing moves yet. 2. `submit` records the owner's signatures and relays exactly those bytes. 3. `reconcile` proves what happened from venue and chain evidence. It sends nothing. 4. A status route reads the operation at any time. All routes here need the `manage` and `transfer` scopes unless the entry says otherwise. A returned destination is always one of your own accounts; no request can name another recipient. ## Fund a venue from the Arc home ### POST /v1/arc-home/funding/prepare Prepare an owner-signed plan that moves an amount from the Arc home to the account's own collateral wallet on one venue. Authorization: API key with `transfer` scope. Rate-limit bucket: `transfer`. `Idempotency-Key` header: required. Request body (JSON, required): - `account_id` (string, optional): Target isolated account UUID. Omit to use the key's own account. [matches ^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$] - `venue` (string, required): Venue to fund from the Arc home Safe. [one of "derive", "hyperliquid", "polymarket"] - `amount` (string, required): Exact USDC amount with at most six decimals. [matches ^(0|[1-9][0-9]{0,12})(\.[0-9]{1,6})?$] - `max_fee_units` (string, optional): Gateway fee ceiling in six-decimal USDC integer units. [matches ^[0-9]{1,8}$] - `accepts_fee_shortfall_mint` (boolean, optional): Declare that this client verifies venue_fee_plan and signs a mint of principal + fee_shortfall_units. Absent or false: a missing destination fee buffer is refused at prepare with the pre-contract *_fee_buffer_insufficient code and no operation, exactly as before the contract; only a zero-shortfall request is prepared. [default false] Error statuses: 400 Invalid request; 401 Missing or invalid API key; 403 Scope, policy, or live-trading restriction; 404 Owned resource not found; 409 State or idempotency conflict; 422 Request body failed schema validation; 429 Rate limit or durable quota exceeded; 500 Internal failure; 502 Venue or provider failure; 503 Required dependency unavailable; 504 Request timeout. ### Hyperliquid ### GET /v1/arc-home/hypercore-fundings/readiness Report whether this account can fund Hyperliquid from the Arc home right now. Reads only. Authorization: API key with `read` scope. Rate-limit bucket: `read`. Query parameters: - `account_id` (string, nullable, optional) Error statuses: 400 Invalid request; 401 Missing or invalid API key; 403 Scope, policy, or live-trading restriction; 404 Owned resource not found; 409 State or idempotency conflict; 422 Request body failed schema validation; 429 Rate limit or durable quota exceeded; 500 Internal failure; 502 Venue or provider failure; 503 Required dependency unavailable; 504 Request timeout. ### GET /v1/arc-home/hypercore-fundings/preview Return the route, cost, and any blockers for a Hyperliquid funding. Creates and signs nothing. Authorization: API key with `read` scope. Rate-limit bucket: `read`. Query parameters: - `amount_units` (integer, required) [minimum 5000000; maximum 25000000] - `minimum_credit_units` (integer, nullable, optional) [greater than 0; maximum 25000000] - `accept_activation_cost_units` (integer, nullable, optional) [greater than 0; maximum 1500000] - `account_id` (string, nullable, optional) Error statuses: 400 Invalid request; 401 Missing or invalid API key; 403 Scope, policy, or live-trading restriction; 404 Owned resource not found; 409 State or idempotency conflict; 422 Request body failed schema validation; 429 Rate limit or durable quota exceeded; 500 Internal failure; 502 Venue or provider failure; 503 Required dependency unavailable; 504 Request timeout. ### POST /v1/arc-home/hypercore-fundings/prepare Return a quote-bound Safe transaction the owner signs to fund Hyperliquid. Authorization: API key with `manage` and `transfer` scope. Rate-limit bucket: `transfer`. `Idempotency-Key` header: required. Request body (JSON, required): - `account_id` (string, nullable, optional) - `amount_units` (integer, required) [minimum 5000000; maximum 25000000] - `minimum_credit_units` (integer, nullable, optional) [greater than 0; maximum 25000000] - `accept_activation_cost_units` (integer, nullable, optional) [greater than 0; maximum 1500000] Error statuses: 400 Invalid request; 401 Missing or invalid API key; 403 Scope, policy, or live-trading restriction; 404 Owned resource not found; 409 State or idempotency conflict; 422 Request body failed schema validation; 429 Rate limit or durable quota exceeded; 500 Internal failure; 502 Venue or provider failure; 503 Required dependency unavailable; 504 Request timeout. ### POST /v1/arc-home/hypercore-fundings/{funding_id}/submit Record the owner signature and relay the funding. Authorization: API key with `manage` and `transfer` scope. Rate-limit bucket: `transfer`. Path parameters: - `funding_id` (string, required) Request body (JSON, required): - `account_id` (string, nullable, optional) - `safe_signature` (string, required) [matches ^0x[0-9a-fA-F]{130}$] Error statuses: 400 Invalid request; 401 Missing or invalid API key; 403 Scope, policy, or live-trading restriction; 404 Owned resource not found; 409 State or idempotency conflict; 422 Request body failed schema validation; 429 Rate limit or durable quota exceeded; 500 Internal failure; 502 Venue or provider failure; 503 Required dependency unavailable; 504 Request timeout. ### POST /v1/arc-home/hypercore-fundings/{funding_id}/reconcile Prove what happened to a funding from chain and venue evidence. Authorization: API key with `manage` and `transfer` scope. Rate-limit bucket: `transfer`. Path parameters: - `funding_id` (string, required) Request body (JSON, required): - `account_id` (string, nullable, optional) Error statuses: 400 Invalid request; 401 Missing or invalid API key; 403 Scope, policy, or live-trading restriction; 404 Owned resource not found; 409 State or idempotency conflict; 422 Request body failed schema validation; 429 Rate limit or durable quota exceeded; 500 Internal failure; 502 Venue or provider failure; 503 Required dependency unavailable; 504 Request timeout. ### POST /v1/arc-home/hypercore-fundings/{funding_id}/cancel Cancel a funding that was never submitted. Moves nothing. Authorization: API key with `manage` and `transfer` scope. Rate-limit bucket: `transfer`. Path parameters: - `funding_id` (string, required) Request body (JSON, required): - `account_id` (string, nullable, optional) Error statuses: 400 Invalid request; 401 Missing or invalid API key; 403 Scope, policy, or live-trading restriction; 404 Owned resource not found; 409 State or idempotency conflict; 422 Request body failed schema validation; 429 Rate limit or durable quota exceeded; 500 Internal failure; 502 Venue or provider failure; 503 Required dependency unavailable; 504 Request timeout. ### GET /v1/arc-home/hypercore-fundings/{funding_id} Read one Hyperliquid funding. Authorization: API key with `read` scope. Rate-limit bucket: `read`. Path parameters: - `funding_id` (string, required) Query parameters: - `account_id` (string, nullable, optional) Error statuses: 400 Invalid request; 401 Missing or invalid API key; 403 Scope, policy, or live-trading restriction; 404 Owned resource not found; 409 State or idempotency conflict; 422 Request body failed schema validation; 429 Rate limit or durable quota exceeded; 500 Internal failure; 502 Venue or provider failure; 503 Required dependency unavailable; 504 Request timeout. ### Polygon and Polymarket ### POST /v1/arc-home/polygon-fundings/prepare Return a quote-bound Safe transaction that moves money to the owner's Polygon wallet, with the route fee included. Authorization: API key with `manage` and `transfer` scope. Rate-limit bucket: `transfer`. `Idempotency-Key` header: required. Request body (JSON, required): - `account_id` (string, nullable, optional) - `amount_units` (integer, required) [minimum 5000000; maximum 25000000] - `minimum_credit_units` (integer, nullable, optional) [greater than 0; maximum 25000000] - `route_intent` (string, required) [one of "polymarket_funding", "owner_delivery"] Error statuses: 400 Invalid request; 401 Missing or invalid API key; 403 Scope, policy, or live-trading restriction; 404 Owned resource not found; 409 State or idempotency conflict; 422 Request body failed schema validation; 429 Rate limit or durable quota exceeded; 500 Internal failure; 502 Venue or provider failure; 503 Required dependency unavailable; 504 Request timeout. ### POST /v1/arc-home/polygon-fundings/{funding_id}/submit Record the owner signature and relay the funding. Authorization: API key with `manage` and `transfer` scope. Rate-limit bucket: `transfer`. Path parameters: - `funding_id` (string, required) Request body (JSON, required): - `account_id` (string, nullable, optional) - `safe_signature` (string, required) [matches ^0x[0-9a-fA-F]{130}$] Error statuses: 400 Invalid request; 401 Missing or invalid API key; 403 Scope, policy, or live-trading restriction; 404 Owned resource not found; 409 State or idempotency conflict; 422 Request body failed schema validation; 429 Rate limit or durable quota exceeded; 500 Internal failure; 502 Venue or provider failure; 503 Required dependency unavailable; 504 Request timeout. ### POST /v1/arc-home/polygon-fundings/{funding_id}/reconcile Prove what happened from chain and Relay evidence. Never relays or signs. Authorization: API key with `manage` and `transfer` scope. Rate-limit bucket: `read`. Path parameters: - `funding_id` (string, required) Request body (JSON, required): - `account_id` (string, nullable, optional) Error statuses: 400 Invalid request; 401 Missing or invalid API key; 403 Scope, policy, or live-trading restriction; 404 Owned resource not found; 409 State or idempotency conflict; 422 Request body failed schema validation; 429 Rate limit or durable quota exceeded; 500 Internal failure; 502 Venue or provider failure; 503 Required dependency unavailable; 504 Request timeout. ### GET /v1/arc-home/polygon-fundings/{funding_id} Read one Polygon funding. Authorization: API key with `read` scope. Rate-limit bucket: `read`. Path parameters: - `funding_id` (string, required) Query parameters: - `account_id` (string, nullable, optional) Error statuses: 400 Invalid request; 401 Missing or invalid API key; 403 Scope, policy, or live-trading restriction; 404 Owned resource not found; 409 State or idempotency conflict; 422 Request body failed schema validation; 429 Rate limit or durable quota exceeded; 500 Internal failure; 502 Venue or provider failure; 503 Required dependency unavailable; 504 Request timeout. ### GET /v1/arc-home/polygon-fundings/lookup Find the existing funding for the original `Idempotency-Key` after a lost response. Authorization: API key with `read` scope. Rate-limit bucket: `read`. `Idempotency-Key` header: required. Query parameters: - `account_id` (string, nullable, optional) Error statuses: 400 Invalid request; 401 Missing or invalid API key; 403 Scope, policy, or live-trading restriction; 404 Owned resource not found; 409 State or idempotency conflict; 422 Request body failed schema validation; 429 Rate limit or durable quota exceeded; 500 Internal failure; 502 Venue or provider failure; 503 Required dependency unavailable; 504 Request timeout. ### POST /v1/arc-home/polygon-fundings/{funding_id}/polymarket/prepare Prepare the one owner-signed transfer that moves a credited Polygon funding into the Polymarket wallet. Replays the original if called again. Authorization: API key with `manage` and `transfer` scope. Rate-limit bucket: `transfer`. Path parameters: - `funding_id` (string, required) Request body (JSON, required): - `account_id` (string, nullable, optional) - `gas_grant` (object, nullable, optional) Error statuses: 400 Invalid request; 401 Missing or invalid API key; 403 Scope, policy, or live-trading restriction; 404 Owned resource not found; 409 State or idempotency conflict; 422 Request body failed schema validation; 429 Rate limit or durable quota exceeded; 500 Internal failure; 502 Venue or provider failure; 503 Required dependency unavailable; 504 Request timeout. ### POST /v1/arc-home/polygon-fundings/{funding_id}/polymarket/evidence Confirm the Polymarket wallet holds spendable pUSD. Read-only. Authorization: API key with `manage` and `transfer` scope. Rate-limit bucket: `read`. Path parameters: - `funding_id` (string, required) Request body (JSON, required): - `account_id` (string, nullable, optional) - `transaction_hashes` (array of string, required) [at least 1 item; at most 5 items] Error statuses: 400 Invalid request; 401 Missing or invalid API key; 403 Scope, policy, or live-trading restriction; 404 Owned resource not found; 409 State or idempotency conflict; 422 Request body failed schema validation; 429 Rate limit or durable quota exceeded; 500 Internal failure; 502 Venue or provider failure; 503 Required dependency unavailable; 504 Request timeout. ### Continuations after a cross-chain transfer When an Arc home operation has delivered USDC to Polygon or Arbitrum, these routes take it the rest of the way to the venue. ### POST /v1/arc-home/operations/{operation_id}/polymarket-continuation/prepare Prepare the next owner-signed step toward Polymarket after the Polygon delivery completed. Authorization: API key with `manage` and `transfer` scope. Rate-limit bucket: `transfer`. Path parameters: - `operation_id` (string, required) Request body (JSON, required): - `account_id` (string, optional): Target isolated account UUID. Omit to use the key's own account. [matches ^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$] - `revision` (integer, required): Exact current parent operation revision. Stale revisions are refused before any continuation intent is issued. [minimum 0] - `gas_grant` (object, optional): Optional owner-signed gas grant for the prepared Polygon owner action. Error statuses: 400 Invalid request; 401 Missing or invalid API key; 403 Scope, policy, or live-trading restriction; 404 Owned resource not found; 409 State or idempotency conflict; 422 Request body failed schema validation; 429 Rate limit or durable quota exceeded; 500 Internal failure; 502 Venue or provider failure; 503 Required dependency unavailable; 504 Request timeout. ### POST /v1/arc-home/operations/{operation_id}/polymarket-continuation/evidence Attach proof for one completed Polymarket step. Authorization: API key with `manage` and `transfer` scope. Rate-limit bucket: `transfer`. Path parameters: - `operation_id` (string, required) Request body (JSON, required): - `account_id` (string, optional): Target isolated account UUID. Omit to use the key's own account. [matches ^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$] - `revision` (integer, required): Exact current parent operation revision. Stale revisions are refused before evidence is consumed. [minimum 0] - `step` (string, required): Continuation leg being proven. [one of "native_usdc_swap", "prediction_fund"] - `transaction_hashes` (array of string, required): One to five owner-signed transaction hashes for the stored continuation leg. [at least 1 item; at most 5 items] Error statuses: 400 Invalid request; 401 Missing or invalid API key; 403 Scope, policy, or live-trading restriction; 404 Owned resource not found; 409 State or idempotency conflict; 422 Request body failed schema validation; 429 Rate limit or durable quota exceeded; 500 Internal failure; 502 Venue or provider failure; 503 Required dependency unavailable; 504 Request timeout. ### POST /v1/arc-home/operations/{operation_id}/hyperliquid-continuation/prepare Prepare the owner-signed Hyperliquid bridge deposit after the Arbitrum delivery completed. Authorization: API key with `manage` and `transfer` scope. Rate-limit bucket: `transfer`. Path parameters: - `operation_id` (string, required) Request body (JSON, required): - `account_id` (string, optional): Target isolated account UUID. Omit to use the key's own account. [matches ^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$] - `revision` (integer, required): Exact current parent operation revision. Stale revisions are refused before any continuation intent is issued. [minimum 0] - `gas_grant` (object, optional): Optional owner-signed gas grant for the Arbitrum action. Error statuses: 400 Invalid request; 401 Missing or invalid API key; 403 Scope, policy, or live-trading restriction; 404 Owned resource not found; 409 State or idempotency conflict; 422 Request body failed schema validation; 429 Rate limit or durable quota exceeded; 500 Internal failure; 502 Venue or provider failure; 503 Required dependency unavailable; 504 Request timeout. ### POST /v1/arc-home/operations/{operation_id}/hyperliquid-continuation/evidence Attach the owner's bridge deposit hash and verify the Hyperliquid credit. Authorization: API key with `manage` and `transfer` scope. Rate-limit bucket: `transfer`. Path parameters: - `operation_id` (string, required) Request body (JSON, required): - `account_id` (string, optional): Target isolated account UUID. Omit to use the key's own account. [matches ^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$] - `revision` (integer, required): Exact current parent operation revision. Stale revisions are refused before evidence is consumed. [minimum 0] - `step` (string, required): Continuation leg being proven. [one of "crypto_deposit"] - `transaction_hashes` (array of string, required): The exact owner-signed Bridge2 transaction hash. [at least 1 item; at most 1 item] Error statuses: 400 Invalid request; 401 Missing or invalid API key; 403 Scope, policy, or live-trading restriction; 404 Owned resource not found; 409 State or idempotency conflict; 422 Request body failed schema validation; 429 Rate limit or durable quota exceeded; 500 Internal failure; 502 Venue or provider failure; 503 Required dependency unavailable; 504 Request timeout. ### POST /v1/arc-home/operations/{operation_id}/derive-continuation/prepare Prepare the next owner-signed Derive step after the Arbitrum delivery completed. Authorization: API key with `manage` and `transfer` scope. Rate-limit bucket: `transfer`. Path parameters: - `operation_id` (string, required) Request body (JSON, required): - `account_id` (string, optional): Target isolated account UUID. Omit to use the key's own account. [matches ^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$] - `revision` (integer, required): Exact current parent operation revision. Stale revisions are refused before any continuation intent is issued. [minimum 0] - `gas_grant` (object, optional): Optional owner-signed gas grant for the prepared owner action. Error statuses: 400 Invalid request; 401 Missing or invalid API key; 403 Scope, policy, or live-trading restriction; 404 Owned resource not found; 409 State or idempotency conflict; 422 Request body failed schema validation; 429 Rate limit or durable quota exceeded; 500 Internal failure; 502 Venue or provider failure; 503 Required dependency unavailable; 504 Request timeout. ### POST /v1/arc-home/operations/{operation_id}/derive-continuation/evidence Attach proof for a client-signed Derive bridge or approval step. Authorization: API key with `manage` and `transfer` scope. Rate-limit bucket: `transfer`. Path parameters: - `operation_id` (string, required) Request body (JSON, required): - `account_id` (string, optional): Target isolated account UUID. Omit to use the key's own account. [matches ^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$] - `revision` (integer, required): Exact current parent operation revision. Stale revisions are refused before evidence is consumed. [minimum 0] - `step` (string, required): Continuation leg being proven. [one of "derive_bridge", "derive_approval"] - `transaction_hashes` (array of string, required): One to five owner-signed transaction hashes for the stored continuation leg. [at least 1 item; at most 5 items] Error statuses: 400 Invalid request; 401 Missing or invalid API key; 403 Scope, policy, or live-trading restriction; 404 Owned resource not found; 409 State or idempotency conflict; 422 Request body failed schema validation; 429 Rate limit or durable quota exceeded; 500 Internal failure; 502 Venue or provider failure; 503 Required dependency unavailable; 504 Request timeout. ### POST /v1/arc-home/operations/{operation_id}/derive-continuation/deposit Run the Derive subaccount deposit and prove the collateral is usable. Authorization: API key with `manage` and `transfer` scope. Rate-limit bucket: `transfer`. Path parameters: - `operation_id` (string, required) Request body (JSON, required): - `account_id` (string, optional): Target isolated account UUID. Omit to use the key's own account. [matches ^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$] - `revision` (integer, required): Exact current parent operation revision. Stale revisions are refused before the deposit is attempted. [minimum 0] Error statuses: 400 Invalid request; 401 Missing or invalid API key; 403 Scope, policy, or live-trading restriction; 404 Owned resource not found; 409 State or idempotency conflict; 422 Request body failed schema validation; 429 Rate limit or durable quota exceeded; 500 Internal failure; 502 Venue or provider failure; 503 Required dependency unavailable; 504 Request timeout. ## Return from a venue to the Arc home ### Hyperliquid through Arbitrum and Relay The Hyperliquid withdrawal lands on the owner's Arbitrum address, and Relay carries it to the Arc home. ### GET /v1/arc-home/hl-relay-returns/readiness Report whether a Hyperliquid return through Relay can start, and its cost. Advisory. Authorization: API key with `read` scope. Rate-limit bucket: `read`. Query parameters: - `account_id` (string, nullable, optional) - `intent_id` (string, nullable, optional) Error statuses: 400 Invalid request; 401 Missing or invalid API key; 403 Scope, policy, or live-trading restriction; 404 Owned resource not found; 409 State or idempotency conflict; 422 Request body failed schema validation; 429 Rate limit or durable quota exceeded; 500 Internal failure; 502 Venue or provider failure; 503 Required dependency unavailable; 504 Request timeout. ### POST /v1/arc-home/hl-relay-returns/prepare Quote and record one Hyperliquid return through Relay. Authorization: API key with `manage` and `transfer` scope. Rate-limit bucket: `transfer`. `Idempotency-Key` header: required. Request body (JSON, required): - `account_id` (string, optional): Target isolated account UUID. Omit to use the key's own account. [matches ^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$] - `amount` (string, required): Exact USDC amount with at most six decimals. [matches ^(0|[1-9][0-9]{0,12})(\.[0-9]{1,6})?$] - `max_total_fee_units` (integer or string, optional) [minimum 1; maximum 1500000] Error statuses: 400 Invalid request; 401 Missing or invalid API key; 403 Scope, policy, or live-trading restriction; 404 Owned resource not found; 409 State or idempotency conflict; 422 Request body failed schema validation; 429 Rate limit or durable quota exceeded; 500 Internal failure; 502 Venue or provider failure; 503 Required dependency unavailable; 504 Request timeout. ### POST /v1/arc-home/hl-relay-returns/{intent_id}/submit Record the owner-signed Hyperliquid withdrawal and submit it. Authorization: API key with `manage` and `transfer` scope. Rate-limit bucket: `transfer`. Path parameters: - `intent_id` (string, required) Request body (JSON, required): - `account_id` (string, optional): Target isolated account UUID. Omit to use the key's own account. [matches ^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$] - `signed_approve_transaction` (string, required): Exact owner-signed Arbitrum approve returned by prepare. [at most 4096 characters; matches ^0x[0-9a-fA-F]+$] - `signed_deposit_transaction` (string, required): Exact owner-signed Arbitrum Relay deposit returned by prepare. [at most 4096 characters; matches ^0x[0-9a-fA-F]+$] Error statuses: 400 Invalid request; 401 Missing or invalid API key; 403 Scope, policy, or live-trading restriction; 404 Owned resource not found; 409 State or idempotency conflict; 422 Request body failed schema validation; 429 Rate limit or durable quota exceeded; 500 Internal failure; 502 Venue or provider failure; 503 Required dependency unavailable; 504 Request timeout. ### POST /v1/arc-home/hl-relay-returns/{intent_id}/relay Open the Relay leg once the Hyperliquid withdrawal is proven. Authorization: API key with `manage` and `transfer` scope. Rate-limit bucket: `transfer`. Path parameters: - `intent_id` (string, required) Request body (JSON): - `account_id` (string, optional): Target isolated account UUID. Omit to use the key's own account. [matches ^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$] Error statuses: 400 Invalid request; 401 Missing or invalid API key; 403 Scope, policy, or live-trading restriction; 404 Owned resource not found; 409 State or idempotency conflict; 422 Request body failed schema validation; 429 Rate limit or durable quota exceeded; 500 Internal failure; 502 Venue or provider failure; 503 Required dependency unavailable; 504 Request timeout. ### POST /v1/arc-home/hl-relay-returns/{intent_id}/reconcile Prove each leg and the Arc home credit. Sends nothing. Authorization: API key with `manage` and `transfer` scope. Rate-limit bucket: `transfer`. Path parameters: - `intent_id` (string, required) Request body (JSON): - `account_id` (string, optional): Target isolated account UUID. Omit to use the key's own account. [matches ^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$] Error statuses: 400 Invalid request; 401 Missing or invalid API key; 403 Scope, policy, or live-trading restriction; 404 Owned resource not found; 409 State or idempotency conflict; 422 Request body failed schema validation; 429 Rate limit or durable quota exceeded; 500 Internal failure; 502 Venue or provider failure; 503 Required dependency unavailable; 504 Request timeout. ### POST /v1/arc-home/hl-relay-returns/{intent_id}/close-unmoved Recovery only: prove a recorded leg never moved funds, then free this return's slot. Authorization: API key with `manage` and `transfer` scope. Rate-limit bucket: `transfer`. Path parameters: - `intent_id` (string, required) Request body (JSON): - `account_id` (string, optional): Target isolated account UUID. Omit to use the key's own account. [matches ^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$] Error statuses: 400 Invalid request; 401 Missing or invalid API key; 403 Scope, policy, or live-trading restriction; 404 Owned resource not found; 409 State or idempotency conflict; 422 Request body failed schema validation; 429 Rate limit or durable quota exceeded; 500 Internal failure; 502 Venue or provider failure; 503 Required dependency unavailable; 504 Request timeout. ### GET /v1/arc-home/hl-relay-returns/{intent_id} Read one Hyperliquid return through Relay. Authorization: API key with `read` scope. Rate-limit bucket: `read`. Path parameters: - `intent_id` (string, required) Query parameters: - `account_id` (string, nullable, optional) Error statuses: 400 Invalid request; 401 Missing or invalid API key; 403 Scope, policy, or live-trading restriction; 404 Owned resource not found; 409 State or idempotency conflict; 422 Request body failed schema validation; 429 Rate limit or durable quota exceeded; 500 Internal failure; 502 Venue or provider failure; 503 Required dependency unavailable; 504 Request timeout. ### Hyperliquid through Arbitrum in two stages The owner signs a Hyperliquid withdrawal to their own Arbitrum address, then Felix opens the cross-chain deposit back to the Arc home. ### GET /v1/arc-home/returns/readiness Report whether this account can bring Hyperliquid money home, and the cost. Authorization: API key with `read` scope. Rate-limit bucket: `read`. Query parameters: - `amount` (string, required) - `account_id` (string, nullable, optional) Error statuses: 400 Invalid request; 401 Missing or invalid API key; 403 Scope, policy, or live-trading restriction; 404 Owned resource not found; 409 State or idempotency conflict; 422 Request body failed schema validation; 429 Rate limit or durable quota exceeded; 500 Internal failure; 502 Venue or provider failure; 503 Required dependency unavailable; 504 Request timeout. ### POST /v1/arc-home/returns/prepare Stage 1: prepare the owner-signed Hyperliquid withdrawal to the owner's own address. Send allow_high_fee_loss: true only after accepting a fee that is large relative to the amount. Authorization: API key with `manage` and `transfer` scope. Rate-limit bucket: `transfer`. `Idempotency-Key` header: required. Request body (JSON, required): - `account_id` (string, optional): Target isolated account UUID. Omit to use the key's own account. [matches ^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$] - `amount` (string, required): Exact USDC amount with at most six decimals. [matches ^(0|[1-9][0-9]{0,12})(\.[0-9]{1,6})?$] - `allow_high_fee_loss` (boolean, optional): Explicitly accept a Hyperliquid withdrawal fee that is large relative to this amount. Error statuses: 400 Invalid request; 401 Missing or invalid API key; 403 Scope, policy, or live-trading restriction; 404 Owned resource not found; 409 State or idempotency conflict; 422 Request body failed schema validation; 429 Rate limit or durable quota exceeded; 500 Internal failure; 502 Venue or provider failure; 503 Required dependency unavailable; 504 Request timeout. ### POST /v1/arc-home/returns/venue-evidence Stage 1 proof: the Hyperliquid debit and the measured arrival on Arbitrum. Authorization: API key with `manage` and `transfer` scope. Rate-limit bucket: `transfer`. Request body (JSON, required): - `account_id` (string, optional): Target isolated account UUID. Omit to use the key's own account. [matches ^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$] - `intent_token` (string, required): Sealed stage-1 intent from returns/prepare. [at most 16000 characters] Error statuses: 400 Invalid request; 401 Missing or invalid API key; 403 Scope, policy, or live-trading restriction; 404 Owned resource not found; 409 State or idempotency conflict; 422 Request body failed schema validation; 429 Rate limit or durable quota exceeded; 500 Internal failure; 502 Venue or provider failure; 503 Required dependency unavailable; 504 Request timeout. ### POST /v1/arc-home/returns/arc-deposit Stage 2: open the one Arc deposit this proven withdrawal may open. Authorization: API key with `manage` and `transfer` scope. Rate-limit bucket: `transfer`. `Idempotency-Key` header: required. Request body (JSON, required): - `account_id` (string, optional): Target isolated account UUID. Omit to use the key's own account. [matches ^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$] - `intent_token` (string, required): Sealed stage-1 intent from returns/prepare. [at most 16000 characters] - `max_fee_units` (string, optional): Gateway fee ceiling in six-decimal USDC integer units. [matches ^[0-9]{1,8}$] Error statuses: 400 Invalid request; 401 Missing or invalid API key; 403 Scope, policy, or live-trading restriction; 404 Owned resource not found; 409 State or idempotency conflict; 422 Request body failed schema validation; 429 Rate limit or durable quota exceeded; 500 Internal failure; 502 Venue or provider failure; 503 Required dependency unavailable; 504 Request timeout. ### POST /v1/arc-home/returns/arc-deposit/recover Reopen a return's Arc deposit after its earlier deposit row expired without moving funds. Authorization: API key with `manage` and `transfer` scope. Rate-limit bucket: `transfer`. `Idempotency-Key` header: required. Request body (JSON, required): - `account_id` (string, optional): Target isolated account UUID. Omit to use the key's own account. [matches ^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$] - `intent_token` (string, required): Sealed stage-1 intent from returns/prepare. [at most 16000 characters] - `expired_operation_id` (string, required): The return's latest Arc deposit, which expired or was cancelled before any burn. [matches ^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$] - `max_fee_units` (string, optional): Gateway fee ceiling in six-decimal USDC integer units. [matches ^[0-9]{1,8}$] Error statuses: 400 Invalid request; 401 Missing or invalid API key; 403 Scope, policy, or live-trading restriction; 404 Owned resource not found; 409 State or idempotency conflict; 422 Request body failed schema validation; 429 Rate limit or durable quota exceeded; 500 Internal failure; 502 Venue or provider failure; 503 Required dependency unavailable; 504 Request timeout. ### GET /v1/arc-home/returns/{operation_id} Read a return. It is usable only once the Arc home is credited. Authorization: API key with `read` scope. Rate-limit bucket: `read`. Path parameters: - `operation_id` (string, required) Query parameters: - `account_id` (string, nullable, optional) Error statuses: 400 Invalid request; 401 Missing or invalid API key; 403 Scope, policy, or live-trading restriction; 404 Owned resource not found; 409 State or idempotency conflict; 422 Request body failed schema validation; 429 Rate limit or durable quota exceeded; 500 Internal failure; 502 Venue or provider failure; 503 Required dependency unavailable; 504 Request timeout. ### Hyperliquid directly through Relay Relay moves the Hyperliquid balance straight to the Arc home, with no Arbitrum leg. The owner signs two payloads locally, and Felix records both before submitting either. ### POST /v1/arc-home/hypercore-returns/prepare Quote and record one direct Hyperliquid return to the Arc home, and return the two unsigned owner payloads. Authorization: API key with `manage` and `transfer` scope. Rate-limit bucket: `transfer`. `Idempotency-Key` header: required. Request body (JSON, required): - `account_id` (string, optional): Target isolated account UUID. Omit to use the key's own account. [matches ^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$] - `amount` (string, required): Exact USDC amount with at most six decimals. [matches ^(0|[1-9][0-9]{0,12})(\.[0-9]{1,6})?$] - `minimum_credit` (string, optional): Exact USDC amount with at most six decimals. [matches ^(0|[1-9][0-9]{0,12})(\.[0-9]{1,6})?$] Error statuses: 400 Invalid request; 401 Missing or invalid API key; 403 Scope, policy, or live-trading restriction; 404 Owned resource not found; 409 State or idempotency conflict; 422 Request body failed schema validation; 429 Rate limit or durable quota exceeded; 500 Internal failure; 502 Venue or provider failure; 503 Required dependency unavailable; 504 Request timeout. ### POST /v1/arc-home/hypercore-returns/{return_id}/submit Verify both owner signatures, record them, and submit exactly those. Authorization: API key with `manage` and `transfer` scope. Rate-limit bucket: `transfer`. Path parameters: - `return_id` (string, required) Request body (JSON, required): - `account_id` (string, optional): Target isolated account UUID. Omit to use the key's own account. [matches ^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$] - `nonce_mapping_signature` (string, required): Owner signature over the prepared RelayNonceMapping typed data. [matches ^0x[0-9a-fA-F]{130}$] - `send_asset_signature` (string, required): Owner signature over the prepared HyperCore SendAsset typed data. [matches ^0x[0-9a-fA-F]{130}$] Error statuses: 400 Invalid request; 401 Missing or invalid API key; 403 Scope, policy, or live-trading restriction; 404 Owned resource not found; 409 State or idempotency conflict; 422 Request body failed schema validation; 429 Rate limit or durable quota exceeded; 500 Internal failure; 502 Venue or provider failure; 503 Required dependency unavailable; 504 Request timeout. ### POST /v1/arc-home/hypercore-returns/{return_id}/reconcile Prove the Hyperliquid send and the Arc home credit. Sends nothing. Authorization: API key with `manage` and `transfer` scope. Rate-limit bucket: `transfer`. Path parameters: - `return_id` (string, required) Request body (JSON): - `account_id` (string, optional): Target isolated account UUID. Omit to use the key's own account. [matches ^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$] Error statuses: 400 Invalid request; 401 Missing or invalid API key; 403 Scope, policy, or live-trading restriction; 404 Owned resource not found; 409 State or idempotency conflict; 422 Request body failed schema validation; 429 Rate limit or durable quota exceeded; 500 Internal failure; 502 Venue or provider failure; 503 Required dependency unavailable; 504 Request timeout. ### GET /v1/arc-home/hypercore-returns/{return_id} Read one direct Hyperliquid return. Authorization: API key with `read` scope. Rate-limit bucket: `read`. Path parameters: - `return_id` (string, required) Query parameters: - `account_id` (string, nullable, optional) Error statuses: 400 Invalid request; 401 Missing or invalid API key; 403 Scope, policy, or live-trading restriction; 404 Owned resource not found; 409 State or idempotency conflict; 422 Request body failed schema validation; 429 Rate limit or durable quota exceeded; 500 Internal failure; 502 Venue or provider failure; 503 Required dependency unavailable; 504 Request timeout. ### Polymarket ### POST /v1/arc-home/pm-returns/prepare Record one Polymarket return and return the owner-signable batch. Authorization: API key with `manage` and `transfer` scope. Rate-limit bucket: `transfer`. `Idempotency-Key` header: required. Request body (JSON, required): - `account_id` (string, optional): Target isolated account UUID. Omit to use the key's own account. [matches ^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$] - `amount` (string, required): Exact USDC amount with at most six decimals. [matches ^(0|[1-9][0-9]{0,12})(\.[0-9]{1,6})?$] Error statuses: 400 Invalid request; 401 Missing or invalid API key; 403 Scope, policy, or live-trading restriction; 404 Owned resource not found; 409 State or idempotency conflict; 422 Request body failed schema validation; 429 Rate limit or durable quota exceeded; 500 Internal failure; 502 Venue or provider failure; 503 Required dependency unavailable; 504 Request timeout. ### POST /v1/arc-home/pm-returns/{return_id}/submit Record the owner-signed batch, then relay exactly those bytes. Authorization: API key with `manage` and `transfer` scope. Rate-limit bucket: `transfer`. Path parameters: - `return_id` (string, required) Request body (JSON, required): - `account_id` (string, optional): Target isolated account UUID. Omit to use the key's own account. [matches ^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$] - `signed_request` (object, required): The owner-signed Polymarket relayer WALLET request for the prepared Batch, unchanged. Error statuses: 400 Invalid request; 401 Missing or invalid API key; 403 Scope, policy, or live-trading restriction; 404 Owned resource not found; 409 State or idempotency conflict; 422 Request body failed schema validation; 429 Rate limit or durable quota exceeded; 500 Internal failure; 502 Venue or provider failure; 503 Required dependency unavailable; 504 Request timeout. ### POST /v1/arc-home/pm-returns/{return_id}/relay/prepare Open, or replay, the one Relay return the proven Polymarket withdrawal may open. Authorization: API key with `manage` and `transfer` scope. Rate-limit bucket: `transfer`. Path parameters: - `return_id` (string, required) Request body (JSON): - `account_id` (string, optional): Target isolated account UUID. Omit to use the key's own account. [matches ^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$] Error statuses: 400 Invalid request; 401 Missing or invalid API key; 403 Scope, policy, or live-trading restriction; 404 Owned resource not found; 409 State or idempotency conflict; 422 Request body failed schema validation; 429 Rate limit or durable quota exceeded; 500 Internal failure; 502 Venue or provider failure; 503 Required dependency unavailable; 504 Request timeout. ### POST /v1/arc-home/pm-returns/{return_id}/relay/submit Record and broadcast the owner-signed Relay transactions. Authorization: API key with `manage` and `transfer` scope. Rate-limit bucket: `transfer`. Path parameters: - `return_id` (string, required) Request body (JSON, required): - `account_id` (string, optional): Target isolated account UUID. Omit to use the key's own account. [matches ^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$] - `signed_approve_transaction` (string, required): Owner-signed raw Polygon approve, exactly as prepared. [at most 4096 characters; matches ^0x[0-9a-fA-F]+$] - `signed_deposit_transaction` (string, required): Owner-signed raw Polygon deposit, nonce = approve nonce + 1. [at most 4096 characters; matches ^0x[0-9a-fA-F]+$] Error statuses: 400 Invalid request; 401 Missing or invalid API key; 403 Scope, policy, or live-trading restriction; 404 Owned resource not found; 409 State or idempotency conflict; 422 Request body failed schema validation; 429 Rate limit or durable quota exceeded; 500 Internal failure; 502 Venue or provider failure; 503 Required dependency unavailable; 504 Request timeout. ### POST /v1/arc-home/pm-returns/{return_id}/reconcile Prove the Polymarket withdrawal and the Arc home credit. Sends nothing. Authorization: API key with `manage` and `transfer` scope. Rate-limit bucket: `transfer`. Path parameters: - `return_id` (string, required) Request body (JSON): - `account_id` (string, optional): Target isolated account UUID. Omit to use the key's own account. [matches ^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$] - `transaction_hash` (string, optional): Optional Polygon transaction that executed the Batch; it must prove the exact pUSD debit and USDC.e credit to the owner. [matches ^0x[0-9a-fA-F]{64}$] Error statuses: 400 Invalid request; 401 Missing or invalid API key; 403 Scope, policy, or live-trading restriction; 404 Owned resource not found; 409 State or idempotency conflict; 422 Request body failed schema validation; 429 Rate limit or durable quota exceeded; 500 Internal failure; 502 Venue or provider failure; 503 Required dependency unavailable; 504 Request timeout. ### GET /v1/arc-home/pm-returns/{return_id} Read one Polymarket return. Authorization: API key with `read` scope. Rate-limit bucket: `read`. Path parameters: - `return_id` (string, required) Query parameters: - `account_id` (string, nullable, optional) Error statuses: 400 Invalid request; 401 Missing or invalid API key; 403 Scope, policy, or live-trading restriction; 404 Owned resource not found; 409 State or idempotency conflict; 422 Request body failed schema validation; 429 Rate limit or durable quota exceeded; 500 Internal failure; 502 Venue or provider failure; 503 Required dependency unavailable; 504 Request timeout. ### Owner wallet through Relay Moves USDC.e from the owner's Polygon wallet, or native USDC from the owner's Arbitrum wallet, to the Arc home. ### POST /v1/arc-home/relay-returns/prepare Quote and record one Relay return, and return the two unsigned owner transactions. Authorization: API key with `manage` and `transfer` scope. Rate-limit bucket: `transfer`. `Idempotency-Key` header: required. Request body (JSON, required): - `account_id` (string, optional): Target isolated account UUID. Omit to use the key's own account. [matches ^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$] - `amount` (string, required): Exact USDC amount with at most six decimals. [matches ^(0|[1-9][0-9]{0,12})(\.[0-9]{1,6})?$] - `minimum_credit` (string, optional): Exact USDC amount with at most six decimals. [matches ^(0|[1-9][0-9]{0,12})(\.[0-9]{1,6})?$] - `source_chain` (string, optional): Owner-wallet source: Polygon USDC.e (chain 137) or Arbitrum native USDC (chain 42161). Omitted selects Polygon. Tokens and destination are fixed; this choice is saved on the operation and cannot change during recovery. [one of "polygon", "arbitrum"; default "polygon"] - `source` (string, optional): Where the funds are: 'owner_wallet' (the owner's EOA on source_chain). 'prediction_market' is refused here: only /v1/arc-home/pm-returns may open it, with its venue proof, and that journey is not launch-enabled. [one of "owner_wallet", "prediction_market"] Error statuses: 400 Invalid request; 401 Missing or invalid API key; 403 Scope, policy, or live-trading restriction; 404 Owned resource not found; 409 State or idempotency conflict; 422 Request body failed schema validation; 429 Rate limit or durable quota exceeded; 500 Internal failure; 502 Venue or provider failure; 503 Required dependency unavailable; 504 Request timeout. ### POST /v1/arc-home/relay-returns/{return_id}/submit Record both owner-signed hashes, then broadcast exactly those bytes. Authorization: API key with `manage` and `transfer` scope. Rate-limit bucket: `transfer`. Path parameters: - `return_id` (string, required) Request body (JSON, required): - `account_id` (string, optional): Target isolated account UUID. Omit to use the key's own account. [matches ^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$] - `signed_approve_transaction` (string, required): Owner-signed raw approve on the saved source chain, exactly as prepared. [at most 4096 characters; matches ^0x[0-9a-fA-F]+$] - `signed_deposit_transaction` (string, required): Owner-signed raw deposit on the saved source chain, nonce = approve nonce + 1. [at most 4096 characters; matches ^0x[0-9a-fA-F]+$] Error statuses: 400 Invalid request; 401 Missing or invalid API key; 403 Scope, policy, or live-trading restriction; 404 Owned resource not found; 409 State or idempotency conflict; 422 Request body failed schema validation; 429 Rate limit or durable quota exceeded; 500 Internal failure; 502 Venue or provider failure; 503 Required dependency unavailable; 504 Request timeout. ### POST /v1/arc-home/relay-returns/{return_id}/reconcile Prove the source deposit and the Arc home credit. Sends nothing. Authorization: API key with `manage` and `transfer` scope. Rate-limit bucket: `transfer`. Path parameters: - `return_id` (string, required) Request body (JSON): - `account_id` (string, optional): Target isolated account UUID. Omit to use the key's own account. [matches ^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$] Error statuses: 400 Invalid request; 401 Missing or invalid API key; 403 Scope, policy, or live-trading restriction; 404 Owned resource not found; 409 State or idempotency conflict; 422 Request body failed schema validation; 429 Rate limit or durable quota exceeded; 500 Internal failure; 502 Venue or provider failure; 503 Required dependency unavailable; 504 Request timeout. ### GET /v1/arc-home/relay-returns/{return_id} Read one Relay return. Authorization: API key with `read` scope. Rate-limit bucket: `read`. Path parameters: - `return_id` (string, required) Query parameters: - `account_id` (string, nullable, optional) Error statuses: 400 Invalid request; 401 Missing or invalid API key; 403 Scope, policy, or live-trading restriction; 404 Owned resource not found; 409 State or idempotency conflict; 422 Request body failed schema validation; 429 Rate limit or durable quota exceeded; 500 Internal failure; 502 Venue or provider failure; 503 Required dependency unavailable; 504 Request timeout. ### Derive ### POST /v1/arc-home/derive-returns/prepare Start one Derive return to the Arc home. Authorization: API key with `manage` and `transfer` scope. Rate-limit bucket: `transfer`. `Idempotency-Key` header: required. Request body (JSON, required): - `account_id` (string, nullable, optional) - `amount_units` (integer, required) [greater than 0; maximum 1000000000000000] - `message_fee_cap_wei` (integer, required) [greater than 0; maximum 1000000000000000] - `minimum_credit_units` (integer, required) [greater than 0; maximum 1000000000000000] - `disclosure` (string, required) [at most 128 characters] Error statuses: 400 Invalid request; 401 Missing or invalid API key; 403 Scope, policy, or live-trading restriction; 404 Owned resource not found; 409 State or idempotency conflict; 422 Request body failed schema validation; 429 Rate limit or durable quota exceeded; 500 Internal failure; 502 Venue or provider failure; 503 Required dependency unavailable; 504 Request timeout. ### POST /v1/arc-home/derive-returns/{operation_id}/submit Submit the owner-signed Derive withdrawal. Authorization: API key with `manage` and `transfer` scope. Rate-limit bucket: `transfer`. Path parameters: - `operation_id` (string, required) Request body (JSON, required): - `account_id` (string, nullable, optional) - `revision` (integer, required) [minimum 0; maximum 65] - `signed_transaction` (string, required) [at least 4 characters; at most 8192 characters; matches ^0x[0-9a-fA-F]+$] Error statuses: 400 Invalid request; 401 Missing or invalid API key; 403 Scope, policy, or live-trading restriction; 404 Owned resource not found; 409 State or idempotency conflict; 422 Request body failed schema validation; 429 Rate limit or durable quota exceeded; 500 Internal failure; 502 Venue or provider failure; 503 Required dependency unavailable; 504 Request timeout. ### POST /v1/arc-home/derive-returns/{operation_id}/socket-prepare Prepare the bridge transfer that carries the withdrawal off the Derive chain. Authorization: API key with `manage` and `transfer` scope. Rate-limit bucket: `transfer`. Path parameters: - `operation_id` (string, required) Request body (JSON, required): - `account_id` (string, nullable, optional) - `revision` (integer, required) [minimum 0; maximum 65] Error statuses: 400 Invalid request; 401 Missing or invalid API key; 403 Scope, policy, or live-trading restriction; 404 Owned resource not found; 409 State or idempotency conflict; 422 Request body failed schema validation; 429 Rate limit or durable quota exceeded; 500 Internal failure; 502 Venue or provider failure; 503 Required dependency unavailable; 504 Request timeout. ### POST /v1/arc-home/derive-returns/{operation_id}/relay-prepare Prepare the Relay leg that delivers the funds to the Arc home. Authorization: API key with `manage` and `transfer` scope. Rate-limit bucket: `transfer`. Path parameters: - `operation_id` (string, required) Request body (JSON, required): - `account_id` (string, nullable, optional) - `revision` (integer, required) [minimum 0; maximum 65] Error statuses: 400 Invalid request; 401 Missing or invalid API key; 403 Scope, policy, or live-trading restriction; 404 Owned resource not found; 409 State or idempotency conflict; 422 Request body failed schema validation; 429 Rate limit or durable quota exceeded; 500 Internal failure; 502 Venue or provider failure; 503 Required dependency unavailable; 504 Request timeout. ### POST /v1/arc-home/derive-returns/{operation_id}/relay-submit Submit the owner-signed Relay leg. Authorization: API key with `manage` and `transfer` scope. Rate-limit bucket: `transfer`. Path parameters: - `operation_id` (string, required) Request body (JSON, required): - `account_id` (string, nullable, optional) - `signed_approve` (string, required) [at least 4 characters; at most 8192 characters; matches ^0x[0-9a-fA-F]+$] - `signed_deposit` (string, required) [at least 4 characters; at most 32768 characters; matches ^0x[0-9a-fA-F]+$] Error statuses: 400 Invalid request; 401 Missing or invalid API key; 403 Scope, policy, or live-trading restriction; 404 Owned resource not found; 409 State or idempotency conflict; 422 Request body failed schema validation; 429 Rate limit or durable quota exceeded; 500 Internal failure; 502 Venue or provider failure; 503 Required dependency unavailable; 504 Request timeout. ### POST /v1/arc-home/derive-returns/{operation_id}/relay-resume Resume the Relay leg after an interruption. Authorization: API key with `manage` and `transfer` scope. Rate-limit bucket: `transfer`. Path parameters: - `operation_id` (string, required) Request body (JSON, required): - `account_id` (string, nullable, optional) - `signed_approve` (string, required) [at least 4 characters; at most 8192 characters; matches ^0x[0-9a-fA-F]+$] - `signed_deposit` (string, required) [at least 4 characters; at most 32768 characters; matches ^0x[0-9a-fA-F]+$] Error statuses: 400 Invalid request; 401 Missing or invalid API key; 403 Scope, policy, or live-trading restriction; 404 Owned resource not found; 409 State or idempotency conflict; 422 Request body failed schema validation; 429 Rate limit or durable quota exceeded; 500 Internal failure; 502 Venue or provider failure; 503 Required dependency unavailable; 504 Request timeout. ### POST /v1/arc-home/derive-returns/{operation_id}/resume Resume the return after an interruption. Authorization: API key with `manage` and `transfer` scope. Rate-limit bucket: `transfer`. Path parameters: - `operation_id` (string, required) Request body (JSON, required): - `account_id` (string, nullable, optional) - `revision` (integer, required) [minimum 0; maximum 65] Error statuses: 400 Invalid request; 401 Missing or invalid API key; 403 Scope, policy, or live-trading restriction; 404 Owned resource not found; 409 State or idempotency conflict; 422 Request body failed schema validation; 429 Rate limit or durable quota exceeded; 500 Internal failure; 502 Venue or provider failure; 503 Required dependency unavailable; 504 Request timeout. ### POST /v1/arc-home/derive-returns/{operation_id}/reconcile Prove the return's progress from chain evidence. Authorization: API key with `manage` and `transfer` scope. Rate-limit bucket: `read`. Path parameters: - `operation_id` (string, required) Request body (JSON, required): - `account_id` (string, nullable, optional) - `revision` (integer, required) [minimum 0; maximum 65] - `destination_transaction` (string, nullable, optional) [matches ^0x[0-9a-fA-F]{64}$] Error statuses: 400 Invalid request; 401 Missing or invalid API key; 403 Scope, policy, or live-trading restriction; 404 Owned resource not found; 409 State or idempotency conflict; 422 Request body failed schema validation; 429 Rate limit or durable quota exceeded; 500 Internal failure; 502 Venue or provider failure; 503 Required dependency unavailable; 504 Request timeout. ### POST /v1/arc-home/derive-returns/{operation_id}/verify Verify the return's final credit. Needs only the read scope. Authorization: API key with `read` scope. Rate-limit bucket: `read`. Path parameters: - `operation_id` (string, required) Request body (JSON, required): - `account_id` (string, nullable, optional) Error statuses: 400 Invalid request; 401 Missing or invalid API key; 403 Scope, policy, or live-trading restriction; 404 Owned resource not found; 409 State or idempotency conflict; 422 Request body failed schema validation; 429 Rate limit or durable quota exceeded; 500 Internal failure; 502 Venue or provider failure; 503 Required dependency unavailable; 504 Request timeout. ### GET /v1/arc-home/derive-returns List this account's Derive returns. Authorization: API key with `read` scope. Rate-limit bucket: `read`. Query parameters: - `account_id` (string, nullable, optional) - `limit` (integer, optional) [default 20] Error statuses: 400 Invalid request; 401 Missing or invalid API key; 403 Scope, policy, or live-trading restriction; 404 Owned resource not found; 409 State or idempotency conflict; 422 Request body failed schema validation; 429 Rate limit or durable quota exceeded; 500 Internal failure; 502 Venue or provider failure; 503 Required dependency unavailable; 504 Request timeout. ### GET /v1/arc-home/derive-returns/{operation_id} Read one Derive return. Authorization: API key with `read` scope. Rate-limit bucket: `read`. Path parameters: - `operation_id` (string, required) Query parameters: - `account_id` (string, nullable, optional) Error statuses: 400 Invalid request; 401 Missing or invalid API key; 403 Scope, policy, or live-trading restriction; 404 Owned resource not found; 409 State or idempotency conflict; 422 Request body failed schema validation; 429 Rate limit or durable quota exceeded; 500 Internal failure; 502 Venue or provider failure; 503 Required dependency unavailable; 504 Request timeout. --- # API reference: Wallet Source: https://felix.trade/docs/api/wallet > The retired Polygon Safe routes, and the custody proof that verifies a wallet against chain state. Every Felix account's wallet is now its Arc home: a Safe on the Arc network whose only owner is the account's owner key. Set it up and use it through [Balance](https://felix.trade/docs/api/balance). ## Retired Polygon Safe routes The Polygon Safe onboarding, migration, and policy routes are retired. Each returns `410 polygon_safe_hub_retired` with a hint that points to the Arc home routes. They stay in the reference so existing integrations can recognize the response. ### POST /v1/wallet/onboarding/init Retired. Returns 410 polygon_safe_hub_retired; use POST /v1/arc-home/onboarding/init. Authorization: API key with `manage` scope. Rate-limit bucket: `manage`. `Idempotency-Key` header: required. Request body (JSON, required): - `account_id` (string, optional): Target isolated account UUID. Omit to use the key's own account. [matches ^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$] - `owner_address` (string, required): Client-held owner EOA. [matches ^0x[0-9a-fA-F]{40}$] - `home_address` (string, optional): Fixed bring-home EOA; defaults to owner_address. [matches ^0x[0-9a-fA-F]{40}$] - `max_operation_usd` (number, optional): Optional owner-selected per-operation safety ceiling; defaults to the attested policy limit. [greater than 0; maximum 10000000; default 10000000] - `daily_limit_usd` (number, optional): Optional owner-selected daily safety ceiling; defaults to the attested policy limit. [greater than 0; maximum 100000000; default 100000000] - `lifetime_limit_usd` (number, optional): Optional cumulative autonomous safety ceiling; defaults to $1B. [greater than 0; maximum 1000000000; default 1000000000] - `delegation_days` (integer, optional): Owner-signed agent delegation lifetime in days. [minimum 1; maximum 90; default 30] Error statuses: 400 Invalid request; 401 Missing or invalid API key; 403 Scope, policy, or live-trading restriction; 404 Owned resource not found; 409 State or idempotency conflict; 422 Request body failed schema validation; 429 Rate limit or durable quota exceeded; 500 Internal failure; 502 Venue or provider failure; 503 Required dependency unavailable; 504 Request timeout. ### POST /v1/wallet/onboarding/deploy Retired. Returns 410 polygon_safe_hub_retired; use POST /v1/arc-home/onboarding/deploy. Authorization: API key with `manage` scope. Rate-limit bucket: `transfer`. `Idempotency-Key` header: required. Request body (JSON, required): - `account_id` (string, optional): Target isolated account UUID. Omit to use the key's own account. [matches ^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$] - `onboarding_id` (string, required): Wallet onboarding UUID. [matches ^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$] - `proof_signature` (string, required): Owner proof signature over the prepared deployment. [matches ^0x[0-9a-fA-F]{130}$] Error statuses: 400 Invalid request; 401 Missing or invalid API key; 403 Scope, policy, or live-trading restriction; 404 Owned resource not found; 409 State or idempotency conflict; 422 Request body failed schema validation; 429 Rate limit or durable quota exceeded; 500 Internal failure; 502 Venue or provider failure; 503 Required dependency unavailable; 504 Request timeout. ### POST /v1/wallet/onboarding/complete Retired. Returns 410 polygon_safe_hub_retired; use POST /v1/arc-home/onboarding/complete. Authorization: API key with `manage` scope. Rate-limit bucket: `transfer`. `Idempotency-Key` header: required. Request body (JSON, required): - `account_id` (string, optional): Target isolated account UUID. Omit to use the key's own account. [matches ^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$] - `onboarding_id` (string, required): Wallet onboarding UUID. [matches ^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$] - `enable_signature` (string, required): Owner signature enabling the scoped module. [matches ^0x[0-9a-fA-F]{130}$] - `fallback_signature` (string, required): Owner signature binding the fallback/home policy. [matches ^0x[0-9a-fA-F]{130}$] Error statuses: 400 Invalid request; 401 Missing or invalid API key; 403 Scope, policy, or live-trading restriction; 404 Owned resource not found; 409 State or idempotency conflict; 422 Request body failed schema validation; 429 Rate limit or durable quota exceeded; 500 Internal failure; 502 Venue or provider failure; 503 Required dependency unavailable; 504 Request timeout. ### GET /v1/wallet/onboarding/{onboarding_id} Read the status of one earlier Polygon onboarding request. Read-only. Authorization: API key with `read` scope. Path parameters: - `onboarding_id` (string, required) Query parameters: - `account_id` (string, nullable, optional) Error statuses: 400 Invalid request; 401 Missing or invalid API key; 403 Scope, policy, or live-trading restriction; 404 Owned resource not found; 409 State or idempotency conflict; 422 Request body failed schema validation; 429 Rate limit or durable quota exceeded; 500 Internal failure; 502 Venue or provider failure; 503 Required dependency unavailable; 504 Request timeout. ### POST /v1/wallet/migration/init Retired. Returns 410 polygon_safe_hub_retired. Authorization: API key with `manage` scope. Rate-limit bucket: `manage`. `Idempotency-Key` header: required. Request body (JSON, required): - `account_id` (string, optional): Target isolated account UUID. Omit to use the key's own account. [matches ^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$] - `owner_address` (string, required): Client-held owner of the existing legacy Safe. [matches ^0x[0-9a-fA-F]{40}$] - `max_operation_usd` (number, optional): V3 per-operation module ceiling; defaults to the legacy value. [greater than 0] - `daily_limit_usd` (number, optional): V3 daily module ceiling; defaults to the legacy value. [greater than 0] - `lifetime_limit_usd` (number, optional): V3 cumulative autonomous ceiling. [greater than 0] - `delegation_days` (integer, optional): V3 agent delegation lifetime in days. [minimum 1; maximum 90; default 30] Error statuses: 400 Invalid request; 401 Missing or invalid API key; 403 Scope, policy, or live-trading restriction; 404 Owned resource not found; 409 State or idempotency conflict; 422 Request body failed schema validation; 429 Rate limit or durable quota exceeded; 500 Internal failure; 502 Venue or provider failure; 503 Required dependency unavailable; 504 Request timeout. ### POST /v1/wallet/migration/deploy Retired. Returns 410 polygon_safe_hub_retired. Authorization: API key with `manage` scope. Rate-limit bucket: `transfer`. `Idempotency-Key` header: required. Request body (JSON, required): - `account_id` (string, optional): Target isolated account UUID. Omit to use the key's own account. [matches ^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$] - `onboarding_id` (string, required): Safe migration UUID. [matches ^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$] - `proof_signature` (string, required): Owner personal-sign proof for this exact migration policy. [matches ^0x[0-9a-fA-F]{130}$] Error statuses: 400 Invalid request; 401 Missing or invalid API key; 403 Scope, policy, or live-trading restriction; 404 Owned resource not found; 409 State or idempotency conflict; 422 Request body failed schema validation; 429 Rate limit or durable quota exceeded; 500 Internal failure; 502 Venue or provider failure; 503 Required dependency unavailable; 504 Request timeout. ### POST /v1/wallet/migration/gas Retired. Returns 410 polygon_safe_hub_retired. Authorization: API key with `manage` scope. Rate-limit bucket: `transfer`. `Idempotency-Key` header: required. Request body (JSON, required): - `account_id` (string, optional): Target isolated account UUID. Omit to use the key's own account. [matches ^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$] - `onboarding_id` (string, required): Safe migration UUID after V3 module deployment. [matches ^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$] - `gas_grant` (object, optional): Optional exact owner-signed gas sponsorship grant. Error statuses: 400 Invalid request; 401 Missing or invalid API key; 403 Scope, policy, or live-trading restriction; 404 Owned resource not found; 409 State or idempotency conflict; 422 Request body failed schema validation; 429 Rate limit or durable quota exceeded; 500 Internal failure; 502 Venue or provider failure; 503 Required dependency unavailable; 504 Request timeout. ### POST /v1/wallet/migration/confirm Retired. Returns 410 polygon_safe_hub_retired. Authorization: API key with `manage` scope. Rate-limit bucket: `transfer`. `Idempotency-Key` header: required. Request body (JSON, required): - `account_id` (string, optional): Target isolated account UUID. Omit to use the key's own account. [matches ^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$] - `onboarding_id` (string, required): Safe migration UUID after all three owner transactions are confirmed. [matches ^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$] Error statuses: 400 Invalid request; 401 Missing or invalid API key; 403 Scope, policy, or live-trading restriction; 404 Owned resource not found; 409 State or idempotency conflict; 422 Request body failed schema validation; 429 Rate limit or durable quota exceeded; 500 Internal failure; 502 Venue or provider failure; 503 Required dependency unavailable; 504 Request timeout. ### POST /v1/wallet/policy/prepare Retired. Returns 410 polygon_safe_hub_retired. Authorization: API key with `manage` scope. Rate-limit bucket: `transfer`. `Idempotency-Key` header: required. Request body (JSON, required): - `account_id` (string, optional): Target isolated account UUID. Omit to use the key's own account. [matches ^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$] - `action` (string, required): Owner-controlled policy operation. Lockdown atomically pauses the agent and revokes fixed Polymarket token approvals. [one of "pause", "resume", "renew", "lockdown"] - `delegation_days` (integer, optional): Required only for renew; maximum 90 days. [minimum 1; maximum 90; default 30] Error statuses: 400 Invalid request; 401 Missing or invalid API key; 403 Scope, policy, or live-trading restriction; 404 Owned resource not found; 409 State or idempotency conflict; 422 Request body failed schema validation; 429 Rate limit or durable quota exceeded; 500 Internal failure; 502 Venue or provider failure; 503 Required dependency unavailable; 504 Request timeout. ### POST /v1/wallet/policy/submit Retired. Returns 410 polygon_safe_hub_retired. Authorization: API key with `manage` scope. Rate-limit bucket: `transfer`. `Idempotency-Key` header: required. Request body (JSON, required): - `account_id` (string, optional): Target isolated account UUID. Omit to use the key's own account. [matches ^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$] - `policy_token` (string, required): Opaque sealed policy intent. [at least 1 character; at most 16000 characters] - `owner_signature` (string, required): Owner's canonical 65-byte EIP-712 Safe signature. [matches ^0x[0-9a-fA-F]{130}$] Error statuses: 400 Invalid request; 401 Missing or invalid API key; 403 Scope, policy, or live-trading restriction; 404 Owned resource not found; 409 State or idempotency conflict; 422 Request body failed schema validation; 429 Rate limit or durable quota exceeded; 500 Internal failure; 502 Venue or provider failure; 503 Required dependency unavailable; 504 Request timeout. ## Custody proof ### GET /v1/wallet/custody-proof Return an authenticated, live-chain proof of the custody model: Safe owner, threshold, enabled module, bindings, ceilings, expiry, and spend state. Authorization: API key with `read` scope. Rate-limit bucket: `read`. Query parameters: - `account_id` (string, nullable, optional) Error statuses: 400 Invalid request; 401 Missing or invalid API key; 403 Scope, policy, or live-trading restriction; 404 Owned resource not found; 409 State or idempotency conflict; 422 Request body failed schema validation; 429 Rate limit or durable quota exceeded; 500 Internal failure; 502 Venue or provider failure; 503 Required dependency unavailable; 504 Request timeout. --- # API reference: Funding Source: https://felix.trade/docs/api/funding > Owner-wallet funding workflows that move money between an owner wallet and a venue, network fees, execution-fee credit, and the compatibility routes. These workflows move money between an owner wallet on Polygon or Arbitrum and a venue. Felix prepares exact transactions and an intent token, the owner signs or sends them on the client, and Felix confirms them against the exact transaction hashes. To move money from the Arc home instead, use [Venue funding and returns](https://felix.trade/docs/api/venue-funding). ## Quotes and balances ### POST /v1/wallet/funding/preview Return one bounded, server-selected funding quote with conversion, network fee, provider cost, destination credit, and timing. Creates nothing. Authorization: API key with `read` scope. Rate-limit bucket: `market`. Request body (JSON, required): - `account_id` (string, optional): Target isolated account UUID. Omit to use the key's own account. [matches ^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$] - `venue` (string, required): Funding destination: crypto/hyperliquid, or options/derive. [one of "crypto", "hyperliquid", "options", "derive"] - `amount_usd` (number, required): Exact principal in USDC, with at most six decimals. For Hyperliquid this is the Polygon USDC/USDC.e source budget; for Derive it is the principal deposited, with the flat network fee charged on top. [minimum 5; maximum 200] Error statuses: 400 Invalid request; 401 Missing or invalid API key; 403 Scope, policy, or live-trading restriction; 404 Owned resource not found; 409 State or idempotency conflict; 422 Request body failed schema validation; 429 Rate limit or durable quota exceeded; 500 Internal failure; 502 Venue or provider failure; 503 Required dependency unavailable; 504 Request timeout. ### POST /v1/wallet/funding/return/preview Return one bounded Hyperliquid-to-Polygon return quote without creating any state. Authorization: API key with `read` scope. Rate-limit bucket: `market`. Request body (JSON, required): - `account_id` (string, optional): Target isolated account UUID. Omit to use the key's own account. [matches ^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$] - `venue` (string, required): Hyperliquid return source. [one of "crypto", "hyperliquid"] - `amount_usd` (number, required): Exact Hyperliquid USDC amount to quote, with at most six decimals. [minimum 1; maximum 200] Error statuses: 400 Invalid request; 401 Missing or invalid API key; 403 Scope, policy, or live-trading restriction; 404 Owned resource not found; 409 State or idempotency conflict; 422 Request body failed schema validation; 429 Rate limit or durable quota exceeded; 500 Internal failure; 502 Venue or provider failure; 503 Required dependency unavailable; 504 Request timeout. ### GET /v1/wallet/funding/balances Return the owner wallets across chains before routing funds. Authorization: API key with `read` scope. Rate-limit bucket: `market`. Error statuses: 400 Invalid request; 401 Missing or invalid API key; 403 Scope, policy, or live-trading restriction; 404 Owned resource not found; 409 State or idempotency conflict; 429 Rate limit or durable quota exceeded; 500 Internal failure; 502 Venue or provider failure; 503 Required dependency unavailable; 504 Request timeout. ## Fund a venue ### POST /v1/wallet/funding/prepare Prepare the exact owner-signed transactions, any gas sponsorship, and the network-fee instruction for moving an amount to one venue, and return the intent token. Authorization: API key with `manage` and `transfer` scope. Rate-limit bucket: `transfer`. `Idempotency-Key` header: required. Request body (JSON, required): - `account_id` (string, optional): Target isolated account UUID. Omit to use the key's own account. [matches ^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$] - `venue` (string, required): Public market class. [one of "prediction_market", "crypto", "options"] - `amount_usd` (number, required): USD amount. Cross-chain Li.Fi routes require at least $4.00; direct same-chain routes may accept less. [greater than 0] - `gas_grant` (object, optional): Optional exact owner-signed gas sponsorship grant. - `fee_parent_intent_token` (string, optional): Prior fee-bound stage intent from the same multi-chain funding workflow. [at least 1 character; at most 16000 characters] Error statuses: 400 Invalid request; 401 Missing or invalid API key; 403 Scope, policy, or live-trading restriction; 404 Owned resource not found; 409 State or idempotency conflict; 422 Request body failed schema validation; 429 Rate limit or durable quota exceeded; 500 Internal failure; 502 Venue or provider failure; 503 Required dependency unavailable; 504 Request timeout. ### POST /v1/wallet/funding/rpc/{chain} Intent-scoped JSON-RPC relay for locally signed funding transactions. Every call is checked against the encrypted intent. Authorization: API key with `manage` and `transfer` scope. Rate-limit bucket: `wallet_rpc`. Path parameters: - `chain` (string, required) Query parameters: - `account_id` (string, nullable, optional) Request body (JSON, required): - `jsonrpc` (constant "2.0", required): JSON-RPC protocol version. [must be "2.0"] - `id` (string or integer, required): Caller-selected bounded JSON-RPC correlation ID. - `method` (string, required): Allowlisted chain method needed by the locally signing funding client. [one of "eth_blockNumber", "eth_call", "eth_chainId", "eth_estimateGas", "eth_feeHistory", "eth_gasPrice", "eth_getBalance", "eth_getBlockByNumber", "eth_getTransactionByHash", "eth_getTransactionCount", "eth_getTransactionReceipt", "eth_maxPriorityFeePerGas", "eth_sendRawTransaction"] - `params` (array of any, required): At most three method parameters. Addresses, calls, and signed transactions are checked against the encrypted funding intent. [at most 3 items] Error statuses: 400 Invalid request; 401 Missing or invalid API key; 403 Scope, policy, or live-trading restriction; 404 Owned resource not found; 409 State or idempotency conflict; 422 Request body failed schema validation; 429 Rate limit or durable quota exceeded; 500 Internal failure; 502 Venue or provider failure; 503 Required dependency unavailable; 504 Request timeout. ### POST /v1/wallet/funding/confirm Confirm a prepared funding with its intent token and the exact transaction hashes that were broadcast. Authorization: API key with `manage` and `transfer` scope. Rate-limit bucket: `transfer`. Request body (JSON, required): - `account_id` (string, optional): Target isolated account UUID. Omit to use the key's own account. [matches ^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$] - `intent_token` (string, required): Opaque, bounded Felix funding intent returned by the matching prepare call. [at least 1 character; at most 16000 characters] - `transaction_hashes` (array of string, required): Transactions executed for the prepared intent. [at least 1 item; at most 5 items] Error statuses: 400 Invalid request; 401 Missing or invalid API key; 403 Scope, policy, or live-trading restriction; 404 Owned resource not found; 409 State or idempotency conflict; 422 Request body failed schema validation; 429 Rate limit or durable quota exceeded; 500 Internal failure; 502 Venue or provider failure; 503 Required dependency unavailable; 504 Request timeout. ### POST /v1/wallet/funding/swap-native-usdc/prepare Prepare an owner-signed same-chain swap of native USDC into the bridged USDC.e that funding spends. Authorization: API key with `manage` and `transfer` scope. Rate-limit bucket: `transfer`. Request body (JSON): - `account_id` (string, optional): Target isolated account UUID. Omit to use the key's own account. [matches ^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$] - `amount_usd` (number, optional): USD notional. [greater than 0] - `gas_grant` (object, optional): Optional exact owner-signed gas sponsorship grant. Error statuses: 400 Invalid request; 401 Missing or invalid API key; 403 Scope, policy, or live-trading restriction; 404 Owned resource not found; 409 State or idempotency conflict; 422 Request body failed schema validation; 429 Rate limit or durable quota exceeded; 500 Internal failure; 502 Venue or provider failure; 503 Required dependency unavailable; 504 Request timeout. ## Network fee Each venue funding carries a flat network fee, paid on top of the amount with a separate owner-signed transfer. The fee is released without payment when Felix proves no owner funds moved. | Destination | Network fee | | --- | --- | | Polygon | $0.50 | | Arbitrum | $1.00 | | Derive | $0.75 | | Hyperliquid | $1.00 | ### GET /v1/wallet/funding/network-fee Return any active funding network-fee obligation, whether owner funds moved, and whether it can be released without payment. Authorization: API key with `read` scope. Rate-limit bucket: `market`. Query parameters: - `account_id` (string, nullable, optional) - `include_recovery_details` (boolean, optional): Recovery-only transaction details. Requires both manage and transfer scopes; ordinary status responses omit sealed intent data and fee-recipient addresses. [default false] Error statuses: 400 Invalid request; 401 Missing or invalid API key; 403 Scope, policy, or live-trading restriction; 404 Owned resource not found; 409 State or idempotency conflict; 422 Request body failed schema validation; 429 Rate limit or durable quota exceeded; 500 Internal failure; 502 Venue or provider failure; 503 Required dependency unavailable; 504 Request timeout. ### POST /v1/wallet/funding/network-fee/confirm Confirm the fee transfer for a prepared funding with its intent token and transaction hash. Authorization: API key with `manage` and `transfer` scope. Rate-limit bucket: `transfer`. `Idempotency-Key` header: required. Request body (JSON, required): - `account_id` (string, optional): Target isolated account UUID. Omit to use the key's own account. [matches ^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$] - `intent_token` (string, required): Opaque, bounded Felix funding intent returned by the matching prepare call. [at least 1 character; at most 16000 characters] - `transaction_hash` (string, required): 0x-prefixed 32-byte transaction hash. [matches ^0x[0-9a-fA-F]{64}$] Error statuses: 400 Invalid request; 401 Missing or invalid API key; 403 Scope, policy, or live-trading restriction; 404 Owned resource not found; 409 State or idempotency conflict; 422 Request body failed schema validation; 429 Rate limit or durable quota exceeded; 500 Internal failure; 502 Venue or provider failure; 503 Required dependency unavailable; 504 Request timeout. ### POST /v1/wallet/funding/network-fee/resolve Resolve one exact obligation: release it when no owner funds moved, or pay it after a verified funding transaction. Authorization: API key with `manage` and `transfer` scope. Rate-limit bucket: `transfer`. `Idempotency-Key` header: required. Request body (JSON, required): - `account_id` (string, optional): Target isolated account UUID. Omit to use the key's own account. [matches ^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$] - `fee_obligation_id` (string, required): Active funding-fee obligation UUID. [matches ^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$] - `confirm_no_owner_funds_moved` (constant true, required): Must be true after GET /v1/wallet/funding/network-fee reports can_release_without_payment. [must be true] Error statuses: 400 Invalid request; 401 Missing or invalid API key; 403 Scope, policy, or live-trading restriction; 404 Owned resource not found; 409 State or idempotency conflict; 422 Request body failed schema validation; 429 Rate limit or durable quota exceeded; 500 Internal failure; 502 Venue or provider failure; 503 Required dependency unavailable; 504 Request timeout. ## Return to the owner wallet ### POST /v1/wallet/funding/return/prepare Prepare an owner-signed return of venue collateral to the original owner wallet. Authorization: API key with `manage` and `transfer` scope. Rate-limit bucket: `transfer`. `Idempotency-Key` header: required. Request body (JSON, required): - `account_id` (string, optional): Target isolated account UUID. Omit to use the key's own account. [matches ^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$] - `venue` (string, required): Return market class. [one of "prediction_market", "crypto"] - `amount_usd` (number, optional): USD notional. [greater than 0] - `stage` (string, optional): Optional bridge stage. [one of "bridge"] - `allow_high_fee_loss` (boolean, optional): Explicitly accept Hyperliquid's fixed withdrawal fee when returning less than $10. [default false] - `gas_grant` (object, optional): Optional exact owner-signed gas sponsorship grant. Error statuses: 400 Invalid request; 401 Missing or invalid API key; 403 Scope, policy, or live-trading restriction; 404 Owned resource not found; 409 State or idempotency conflict; 422 Request body failed schema validation; 429 Rate limit or durable quota exceeded; 500 Internal failure; 502 Venue or provider failure; 503 Required dependency unavailable; 504 Request timeout. ### POST /v1/wallet/funding/return/submit Relay the owner-signed return request for its intent token. Authorization: API key with `manage` and `transfer` scope. Rate-limit bucket: `transfer`. `Idempotency-Key` header: required. Request body (JSON, required): - `account_id` (string, optional): Target isolated account UUID. Omit to use the key's own account. [matches ^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$] - `intent_token` (string, required): Opaque, bounded Felix funding intent returned by the matching prepare call. [at least 1 character; at most 16000 characters] - `signed_request` (object, required): Exact owner-signed request returned by the matching prepare call. Error statuses: 400 Invalid request; 401 Missing or invalid API key; 403 Scope, policy, or live-trading restriction; 404 Owned resource not found; 409 State or idempotency conflict; 422 Request body failed schema validation; 429 Rate limit or durable quota exceeded; 500 Internal failure; 502 Venue or provider failure; 503 Required dependency unavailable; 504 Request timeout. ### POST /v1/wallet/funding/return/confirm Confirm a return with its intent token and the exact transaction hashes. Authorization: API key with `manage` and `transfer` scope. Rate-limit bucket: `transfer`. Request body (JSON, required): - `account_id` (string, optional): Target isolated account UUID. Omit to use the key's own account. [matches ^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$] - `intent_token` (string, required): Opaque, bounded Felix funding intent returned by the matching prepare call. [at least 1 character; at most 16000 characters] - `transaction_hashes` (array of string, optional): Return transaction hashes when required by the prepared route. [at least 1 item; at most 3 items] Error statuses: 400 Invalid request; 401 Missing or invalid API key; 403 Scope, policy, or live-trading restriction; 404 Owned resource not found; 409 State or idempotency conflict; 422 Request body failed schema validation; 429 Rate limit or durable quota exceeded; 500 Internal failure; 502 Venue or provider failure; 503 Required dependency unavailable; 504 Request timeout. ### POST /v1/wallet/funding/gas/prepare Prepare or submit a bounded owner-authorized gas grant for a venue return. Authorization: API key with `manage` scope. Rate-limit bucket: `transfer`. `Idempotency-Key` header: required. Request body (JSON, required): - `account_id` (string, optional): Target isolated account UUID. Omit to use the key's own account. [matches ^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$] - `operation` (string, required): Bounded venue-return gas operation. [one of "derive_return"] - `gas_grant` (object, optional): Optional exact owner-signed gas sponsorship grant. Error statuses: 400 Invalid request; 401 Missing or invalid API key; 403 Scope, policy, or live-trading restriction; 404 Owned resource not found; 409 State or idempotency conflict; 422 Request body failed schema validation; 429 Rate limit or durable quota exceeded; 500 Internal failure; 502 Venue or provider failure; 503 Required dependency unavailable; 504 Request timeout. ## Options returns ### POST /v1/wallet/funding/options-return/prepare Prepare the owner's two Derive-chain calls for an options return. Sends nothing. Authorization: API key with `manage` and `transfer` scope. Rate-limit bucket: `transfer`. Request body (JSON, required): - `account_id` (string, optional): Target isolated account UUID. Omit to use the key's own account. [matches ^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$] - `amount_usd` (string or number, required): USDC to return, 5 to 2000, at most 6 decimals (string or number). Error statuses: 400 Invalid request; 401 Missing or invalid API key; 403 Scope, policy, or live-trading restriction; 404 Owned resource not found; 409 State or idempotency conflict; 422 Request body failed schema validation; 429 Rate limit or durable quota exceeded; 500 Internal failure; 502 Venue or provider failure; 503 Required dependency unavailable; 504 Request timeout. ### GET /v1/wallet/funding/options-return/status Read the owner's Derive-chain and Base balances to confirm an options return. Authorization: API key with `read` scope. Rate-limit bucket: `read`. Query parameters: - `account_id` (string, nullable, optional) Error statuses: 400 Invalid request; 401 Missing or invalid API key; 403 Scope, policy, or live-trading restriction; 404 Owned resource not found; 409 State or idempotency conflict; 422 Request body failed schema validation; 429 Rate limit or durable quota exceeded; 500 Internal failure; 502 Venue or provider failure; 503 Required dependency unavailable; 504 Request timeout. ## Execution-fee credit Prediction-market and option opens placed through the client-signed flow reserve prepaid credit before submission, capture it after a confirmed fill, and release it after a confirmed no-fill. ### GET /v1/wallet/funding/fees/status Return prepaid execution-fee credit as available, reserved, and captured amounts. Authorization: API key with `read` scope. Rate-limit bucket: `read`. Query parameters: - `account_id` (string, nullable, optional) Error statuses: 400 Invalid request; 401 Missing or invalid API key; 403 Scope, policy, or live-trading restriction; 404 Owned resource not found; 409 State or idempotency conflict; 422 Request body failed schema validation; 429 Rate limit or durable quota exceeded; 500 Internal failure; 502 Venue or provider failure; 503 Required dependency unavailable; 504 Request timeout. ### POST /v1/wallet/funding/fees/prepare Prepare one bounded owner-signed USDC.e transfer that adds execution-fee credit. Authorization: API key with `manage` and `transfer` scope. Rate-limit bucket: `transfer`. `Idempotency-Key` header: required. Request body (JSON): - `account_id` (string, optional): Target isolated account UUID. Omit to use the key's own account. [matches ^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$] - `amount_usd` (number, required): USDC.e amount to prepay for future live execution fees. [minimum 0.1; maximum 10000] Error statuses: 400 Invalid request; 401 Missing or invalid API key; 403 Scope, policy, or live-trading restriction; 404 Owned resource not found; 409 State or idempotency conflict; 422 Request body failed schema validation; 429 Rate limit or durable quota exceeded; 500 Internal failure; 502 Venue or provider failure; 503 Required dependency unavailable; 504 Request timeout. ### POST /v1/wallet/funding/fees/confirm Confirm the credit transfer with its intent token and transaction hash. Authorization: API key with `manage` and `transfer` scope. Rate-limit bucket: `transfer`. `Idempotency-Key` header: required. Request body (JSON, required): - `account_id` (string, optional): Target isolated account UUID. Omit to use the key's own account. [matches ^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$] - `intent_token` (string, required): Opaque, bounded Felix funding intent returned by the matching prepare call. [at least 1 character; at most 16000 characters] - `transaction_hash` (string, required): 0x-prefixed 32-byte transaction hash. [matches ^0x[0-9a-fA-F]{64}$] Error statuses: 400 Invalid request; 401 Missing or invalid API key; 403 Scope, policy, or live-trading restriction; 404 Owned resource not found; 409 State or idempotency conflict; 422 Request body failed schema validation; 429 Rate limit or durable quota exceeded; 500 Internal failure; 502 Venue or provider failure; 503 Required dependency unavailable; 504 Request timeout. ## Compatibility routes New integrations should use the workflows above. For an options return through `POST /v1/bring-home`, read `venues.options.withdrawable_usd` from `GET /v1/balances` first; if the response is `derive_return_reconciliation_pending`, retry the identical body with the same key after `retry_after`. ### POST /v1/fund Deposit owner funds to one venue through the fixed-owner session flow. Authorization: API key with `manage` scope. Rate-limit bucket: `transfer`. `Idempotency-Key` header: required. Request body (JSON, required): - `account_id` (string, optional): Target isolated account UUID. Omit to use the key's own account. [matches ^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$] - `venue` (string, required): Public market class. [one of "prediction_market", "crypto", "options"] - `amount_usd` (number, required): USD notional. [greater than 0] Error statuses: 400 Invalid request; 401 Missing or invalid API key; 403 Scope, policy, or live-trading restriction; 404 Owned resource not found; 409 State or idempotency conflict; 422 Request body failed schema validation; 429 Rate limit or durable quota exceeded; 500 Internal failure; 502 Venue or provider failure; 503 Required dependency unavailable; 504 Request timeout. ### POST /v1/bring-home Return venue collateral to the original verified owner only. Authorization: API key with `manage` scope. Rate-limit bucket: `transfer`. `Idempotency-Key` header: required. Request body (JSON, required): - `account_id` (string, optional): Target isolated account UUID. Omit to use the key's own account. [matches ^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$] - `venue` (string, required): Public market class. [one of "prediction_market", "crypto", "options"] - `amount_usd` (number, required): USD notional. [greater than 0] Error statuses: 400 Invalid request; 401 Missing or invalid API key; 403 Scope, policy, or live-trading restriction; 404 Owned resource not found; 409 State or idempotency conflict; 422 Request body failed schema validation; 429 Rate limit or durable quota exceeded; 500 Internal failure; 502 Venue or provider failure; 503 Required dependency unavailable; 504 Request timeout. --- # API reference: Venue onboarding Source: https://felix.trade/docs/api/venue-onboarding > Enable each venue for an account with owner-signed sessions, scoped API wallets, deposit wallets, exchange approvals, and the autonomous prediction-market wallet. Each venue needs a one-time, owner-signed setup before live orders. The endpoint names identify the protocol integration in the signing contract; trading responses normalize them back into market classes. Felix is designed never to receive a session key or an owner key, and it never builds arbitrary approval calldata. ## Options Options require an owner-bound venue session. Prepare exact venue-chain transactions, broadcast or relay them, and read the state back. ### POST /v1/derive/onboarding/prepare Prepare the exact venue-chain transactions the verified owner wallet must send, bounded by a maximum deposit and expiry. Authorization: API key with `manage` scope. Rate-limit bucket: `transfer`. `Idempotency-Key` header: required. Request body (JSON, required): - `account_id` (string, optional): Target isolated account UUID. Omit to use the key's own account. [matches ^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$] - `max_deposit_usd` (number, required): Maximum owner-authorized Derive deposit. [greater than 0; maximum 1000000000] - `expiry_days` (integer, optional): Session-policy expiry in days. [minimum 1; maximum 30; default 30] - `gas_grant` (object, optional): Optional exact owner-signed gas sponsorship grant. Error statuses: 400 Invalid request; 401 Missing or invalid API key; 403 Scope, policy, or live-trading restriction; 404 Owned resource not found; 409 State or idempotency conflict; 422 Request body failed schema validation; 429 Rate limit or durable quota exceeded; 500 Internal failure; 502 Venue or provider failure; 503 Required dependency unavailable; 504 Request timeout. ### POST /v1/derive/onboarding/submit Verify the owner's exact prepared transactions after a wallet broadcasts them, or relay exact locally signed raw transactions. Authorization: API key with `manage` scope. Rate-limit bucket: `transfer`. `Idempotency-Key` header: required. Request body (JSON, required): - `account_id` (string, optional): Target isolated account UUID. Omit to use the key's own account. [matches ^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$] - `transaction_hashes` (array of string, optional): Hashes of the exact prepared transactions already broadcast by the owner. [at least 1 item; at most 3 items] - `signed_raw_transactions` (array of string, optional): Exact prepared transactions signed by the owner. [at least 1 item; at most 3 items] Error statuses: 400 Invalid request; 401 Missing or invalid API key; 403 Scope, policy, or live-trading restriction; 404 Owned resource not found; 409 State or idempotency conflict; 422 Request body failed schema validation; 429 Rate limit or durable quota exceeded; 500 Internal failure; 502 Venue or provider failure; 503 Required dependency unavailable; 504 Request timeout. ### GET /v1/derive/onboarding Read the current owner-signed options onboarding state. Never returns a private session key. Authorization: API key with `read` scope. Query parameters: - `account_id` (string, nullable, optional) Error statuses: 400 Invalid request; 401 Missing or invalid API key; 403 Scope, policy, or live-trading restriction; 404 Owned resource not found; 409 State or idempotency conflict; 422 Request body failed schema validation; 429 Rate limit or durable quota exceeded; 500 Internal failure; 502 Venue or provider failure; 503 Required dependency unavailable; 504 Request timeout. ## Crypto and equity perpetuals Perpetuals use a scoped API wallet approved by the owner's main wallet. The scoped wallet can trade but cannot withdraw or transfer funds. ### POST /v1/wallet/hyperliquid/onboarding/init Prepare the approve-agent typed data for the caller-owned main wallet. Authorization: API key with `manage` scope. Rate-limit bucket: `transfer`. `Idempotency-Key` header: required. Request body (JSON, required): - `account_id` (string, optional): Target isolated account UUID. Omit to use the key's own account. [matches ^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$] - `main_address` (string, required): User-controlled Hyperliquid main account. [matches ^0x[0-9a-fA-F]{40}$] Error statuses: 400 Invalid request; 401 Missing or invalid API key; 403 Scope, policy, or live-trading restriction; 404 Owned resource not found; 409 State or idempotency conflict; 422 Request body failed schema validation; 429 Rate limit or durable quota exceeded; 500 Internal failure; 502 Venue or provider failure; 503 Required dependency unavailable; 504 Request timeout. ### POST /v1/wallet/hyperliquid/onboarding/complete Submit the main wallet's exact approve-agent signature and verify the scoped wallet relationship on the venue. Authorization: API key with `manage` scope. Rate-limit bucket: `transfer`. `Idempotency-Key` header: required. Request body (JSON, required): - `account_id` (string, optional): Target isolated account UUID. Omit to use the key's own account. [matches ^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$] - `onboarding_id` (string, required): Hyperliquid onboarding UUID. [matches ^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$] - `signature` (string, required): Main-wallet approveAgent signature. [matches ^0x[0-9a-fA-F]{130}$] Error statuses: 400 Invalid request; 401 Missing or invalid API key; 403 Scope, policy, or live-trading restriction; 404 Owned resource not found; 409 State or idempotency conflict; 422 Request body failed schema validation; 429 Rate limit or durable quota exceeded; 500 Internal failure; 502 Venue or provider failure; 503 Required dependency unavailable; 504 Request timeout. ### GET /v1/wallet/hyperliquid/onboarding/{onboarding_id} Read and reconcile one caller-owned scoped-wallet onboarding request. Authorization: API key with `read` scope. Path parameters: - `onboarding_id` (string, required) Query parameters: - `account_id` (string, nullable, optional) Error statuses: 400 Invalid request; 401 Missing or invalid API key; 403 Scope, policy, or live-trading restriction; 404 Owned resource not found; 409 State or idempotency conflict; 422 Request body failed schema validation; 429 Rate limit or durable quota exceeded; 500 Internal failure; 502 Venue or provider failure; 503 Required dependency unavailable; 504 Request timeout. ## Prediction markets Interactive orders use the client-owned deposit wallet with a local signer. The order flow is in [Prediction-market orders](https://felix.trade/docs/api/prediction-market-orders). ### POST /v1/wallet/polymarket/deploy Deploy the caller-owned deposit wallet without sending an owner key or signature. Authorization: API key with `manage` scope. Rate-limit bucket: `transfer`. `Idempotency-Key` header: required. Request body (JSON): - `account_id` (string, optional): Target isolated account UUID. Omit to use the key's own account. [matches ^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$] Error statuses: 400 Invalid request; 401 Missing or invalid API key; 403 Scope, policy, or live-trading restriction; 404 Owned resource not found; 409 State or idempotency conflict; 422 Request body failed schema validation; 429 Rate limit or durable quota exceeded; 500 Internal failure; 502 Venue or provider failure; 503 Required dependency unavailable; 504 Request timeout. ### GET /v1/wallet/polymarket Read the caller-owned deposit wallet and its setup state without deploying, approving, signing, or spending gas. Authorization: API key with `read` scope. Rate-limit bucket: `market`. Query parameters: - `account_id` (string, nullable, optional) Error statuses: 400 Invalid request; 401 Missing or invalid API key; 403 Scope, policy, or live-trading restriction; 404 Owned resource not found; 409 State or idempotency conflict; 422 Request body failed schema validation; 429 Rate limit or durable quota exceeded; 500 Internal failure; 502 Venue or provider failure; 503 Required dependency unavailable; 504 Request timeout. ### POST /v1/wallet/polymarket/trading/enable Bind this account's prediction-market order-book read credentials. Idempotent. Authorization: API key with `manage` scope. Rate-limit bucket: `transfer`. Request body (JSON): - `account_id` (string, optional): Target isolated account UUID. Omit to use the key's own account. [matches ^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$] Error statuses: 400 Invalid request; 401 Missing or invalid API key; 403 Scope, policy, or live-trading restriction; 404 Owned resource not found; 409 State or idempotency conflict; 422 Request body failed schema validation; 429 Rate limit or durable quota exceeded; 500 Internal failure; 502 Venue or provider failure; 503 Required dependency unavailable; 504 Request timeout. ### POST /v1/wallet/polymarket/approvals/prepare Return the fixed pUSD and CTF exchange approval batch for the deposit wallet to sign locally. Authorization: API key with `manage` scope. Rate-limit bucket: `transfer`. `Idempotency-Key` header: required. Request body (JSON): - `account_id` (string, optional): Target isolated account UUID. Omit to use the key's own account. [matches ^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$] Error statuses: 400 Invalid request; 401 Missing or invalid API key; 403 Scope, policy, or live-trading restriction; 404 Owned resource not found; 409 State or idempotency conflict; 422 Request body failed schema validation; 429 Rate limit or durable quota exceeded; 500 Internal failure; 502 Venue or provider failure; 503 Required dependency unavailable; 504 Request timeout. ### POST /v1/wallet/polymarket/approvals/submit Relay the locally signed approval batch. Authorization: API key with `manage` scope. Rate-limit bucket: `transfer`. `Idempotency-Key` header: required. Request body (JSON, required): - `account_id` (string, optional): Target isolated account UUID. Omit to use the key's own account. [matches ^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$] - `signed_request` (object, required): Exact owner-signed request returned by the matching prepare call. Error statuses: 400 Invalid request; 401 Missing or invalid API key; 403 Scope, policy, or live-trading restriction; 404 Owned resource not found; 409 State or idempotency conflict; 422 Request body failed schema validation; 429 Rate limit or durable quota exceeded; 500 Internal failure; 502 Venue or provider failure; 503 Required dependency unavailable; 504 Request timeout. ## Autonomous prediction-market wallet Background agents use a separate, venue-scoped execution wallet. Felix derives it, installs its exchange approvals, and redeems resolved winnings back into it. Accounts with [agent capital](https://felix.trade/docs/api/agent-capital) use the prediction-market account created with their agent capital instead. ### GET /v1/wallet/polymarket/agent Read the distinct venue-scoped wallet used by autonomous prediction-market agents. Authorization: API key with `read` scope. Rate-limit bucket: `market`. Query parameters: - `account_id` (string, nullable, optional) Error statuses: 400 Invalid request; 401 Missing or invalid API key; 403 Scope, policy, or live-trading restriction; 404 Owned resource not found; 409 State or idempotency conflict; 422 Request body failed schema validation; 429 Rate limit or durable quota exceeded; 500 Internal failure; 502 Venue or provider failure; 503 Required dependency unavailable; 504 Request timeout. ### POST /v1/wallet/polymarket/agent/setup Deploy the deterministic venue-scoped autonomous wallet and complete its fixed exchange approvals. Authorization: API key with `trade` scope. Rate-limit bucket: `transfer`. Request body (JSON): - `account_id` (string, optional): Target isolated account UUID. Omit to use the key's own account. [matches ^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$] Error statuses: 400 Invalid request; 401 Missing or invalid API key; 403 Scope, policy, or live-trading restriction; 404 Owned resource not found; 409 State or idempotency conflict; 422 Request body failed schema validation; 429 Rate limit or durable quota exceeded; 500 Internal failure; 502 Venue or provider failure; 503 Required dependency unavailable; 504 Request timeout. ### POST /v1/wallet/polymarket/agent/funding/prepare Prepare one exact pUSD transfer from the client wallet to the server-derived autonomous wallet. Authorization: API key with `trade` scope. Rate-limit bucket: `transfer`. Request body (JSON, required): - `account_id` (string, optional): Target isolated account UUID. Omit to use the key's own account. [matches ^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$] - `amount_usd` (number, required): Exact pUSD amount to transfer from the client wallet to the autonomous wallet. [minimum 0.01; maximum 1000000000] Error statuses: 400 Invalid request; 401 Missing or invalid API key; 403 Scope, policy, or live-trading restriction; 404 Owned resource not found; 409 State or idempotency conflict; 422 Request body failed schema validation; 429 Rate limit or durable quota exceeded; 500 Internal failure; 502 Venue or provider failure; 503 Required dependency unavailable; 504 Request timeout. ### POST /v1/wallet/polymarket/agent/funding/submit Relay the locally signed transfer for the same exact amount. Authorization: API key with `trade` scope. Rate-limit bucket: `transfer`. Request body (JSON, required): - `account_id` (string, optional): Target isolated account UUID. Omit to use the key's own account. [matches ^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$] - `amount_usd` (number, required): Exact pUSD amount bound by the prepared funding request. [minimum 0.01; maximum 1000000000] - `signed_request` (object, required): Exact owner-signed request returned by the matching prepare call. Error statuses: 400 Invalid request; 401 Missing or invalid API key; 403 Scope, policy, or live-trading restriction; 404 Owned resource not found; 409 State or idempotency conflict; 422 Request body failed schema validation; 429 Rate limit or durable quota exceeded; 500 Internal failure; 502 Venue or provider failure; 503 Required dependency unavailable; 504 Request timeout. ## Withdrawal grants A fixed-home withdrawal grant names the only address prediction-market funds may be released to. Transfers out of the separate autonomous prediction-market wallet are currently refused by the signing enclave, so these grants do not move money today. ### POST /v1/wallet/polymarket/withdrawal-grant/prepare Build the exact fixed-home withdrawal message for the client-owned wallet to sign. Never signs or moves funds. Authorization: API key with `manage` scope. Rate-limit bucket: `transfer`. Request body (JSON, required): - `account_id` (string, optional): Target isolated account UUID. Omit to use the key's own account. [matches ^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$] - `max_operation_usd` (number, optional): Maximum fixed-home return amount per operation. [greater than 0; maximum 1000000000; default 1000000000] - `expires_in_seconds` (integer, optional): Grant lifetime. [minimum 120; maximum 86400] Error statuses: 400 Invalid request; 401 Missing or invalid API key; 403 Scope, policy, or live-trading restriction; 404 Owned resource not found; 409 State or idempotency conflict; 422 Request body failed schema validation; 429 Rate limit or durable quota exceeded; 500 Internal failure; 502 Venue or provider failure; 503 Required dependency unavailable; 504 Request timeout. ### POST /v1/wallet/polymarket/withdrawal-grant/submit Store the owner-signed fixed-home withdrawal grant for venue-scoped policy checks. Authorization: API key with `manage` scope. Rate-limit bucket: `transfer`. `Idempotency-Key` header: required. Request body (JSON, required): - `account_id` (string, optional): Target isolated account UUID. Omit to use the key's own account. [matches ^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$] - `message` (string, required): Exact prepared grant message. [at least 1 character; at most 1024 characters] - `signature` (string, required): Owner personal-sign signature. [matches ^0x[0-9a-fA-F]{130}$] Error statuses: 400 Invalid request; 401 Missing or invalid API key; 403 Scope, policy, or live-trading restriction; 404 Owned resource not found; 409 State or idempotency conflict; 422 Request body failed schema validation; 429 Rate limit or durable quota exceeded; 500 Internal failure; 502 Venue or provider failure; 503 Required dependency unavailable; 504 Request timeout. ### POST /v1/wallet/polymarket/withdrawal-grant/revoke Revoke the stored fixed-home withdrawal authorization for the account. Authorization: API key with `manage` scope. Rate-limit bucket: `transfer`. `Idempotency-Key` header: required. Request body (JSON, required): - `account_id` (string, optional): Target isolated account UUID. Omit to use the key's own account. [matches ^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$] Error statuses: 400 Invalid request; 401 Missing or invalid API key; 403 Scope, policy, or live-trading restriction; 404 Owned resource not found; 409 State or idempotency conflict; 422 Request body failed schema validation; 429 Rate limit or durable quota exceeded; 500 Internal failure; 502 Venue or provider failure; 503 Required dependency unavailable; 504 Request timeout. --- # API reference: Prediction-market orders Source: https://felix.trade/docs/api/prediction-market-orders > The client-signed order flow for prediction markets: prepare, checkpoint, submit, commit, reconcile, close, and redeem. Live prediction-market orders through the API are signed on the client and relayed by Felix. `POST /v1/orders` refuses prediction markets for live execution by design. Wallet setup is in [Venue onboarding](https://felix.trade/docs/api/venue-onboarding). ## Sizes and fees - An order must be at least $1 and at least the market's minimum share size, usually 5 shares. - A taker order pays Polymarket's fee: shares x rate x p x (1 - p), where p is the price. The rate depends on the category: 0.07 for crypto, 0.03 to 0.05 for sports, 0.04 for politics, and 0 for geopolitics. A maker order that rests on the book pays no Polymarket fee. - Felix's own trading fee is in [Fees](https://felix.trade/docs/overview/fees). The prepare response returns both. At a price of 0.50, a 10-share crypto taker order pays 10 x 0.07 x 0.25 = $0.175 to Polymarket. ```text order sequence prepare -> sign locally -> checkpoint -> submit -> commit -> read the intent when anything is ambiguous ``` ## Open ### POST /v1/orders/polymarket/prepare Resolve the market, check that the wallet covers the order plus its fee estimate, reserve execution-fee credit, and return the exact order to sign with an intent id. Authorization: API key with `trade` scope. Rate-limit bucket: `order`. `Idempotency-Key` header: required. Request body (JSON, required): - `instrument` (string, required): Canonical symbol or Felix instrument, for example BTC, NVDA, option:BTC-..., or pm:. [at least 1 character; at most 180 characters] - `side` (string, required): Prediction outcome. [one of "yes", "no"] - `size_usd` (number, required): USD notional. [greater than 0] - `limit_price` (number, optional): Optional exact tick-aligned limit price between zero and one. [greater than 0; less than 1] - `client_reconciliation` (string, required): Exact-reconciliation protocol version. [one of "builder_order_v1"] Error statuses: 400 Invalid request; 401 Missing or invalid API key; 403 Scope, policy, or live-trading restriction; 404 Owned resource not found; 409 State or idempotency conflict; 422 Request body failed schema validation; 429 Rate limit or durable quota exceeded; 500 Internal failure; 502 Venue or provider failure; 503 Required dependency unavailable; 504 Request timeout. ### POST /v1/orders/polymarket/checkpoint Record the deterministic order hash for an intent before anything reaches the venue. Authorization: API key with `trade` scope. Rate-limit bucket: `reconcile`. `Idempotency-Key` header: required. Request body (JSON, required): - `intent_id` (string, required): Live-order intent UUID. [matches ^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$] - `order_id` (string, required): Exact venue order hash. [matches ^0x[0-9a-fA-F]{64}$] Error statuses: 400 Invalid request; 401 Missing or invalid API key; 403 Scope, policy, or live-trading restriction; 404 Owned resource not found; 409 State or idempotency conflict; 422 Request body failed schema validation; 429 Rate limit or durable quota exceeded; 500 Internal failure; 502 Venue or provider failure; 503 Required dependency unavailable; 504 Request timeout. ### POST /v1/orders/polymarket/submit Relay the client-signed order, headers and body exactly as signed, to the venue from the server region. Authorization: API key with `trade` scope. Rate-limit bucket: `order`. `Idempotency-Key` header: required. Request body (JSON, required): - `intent_id` (string, required): Checkpointed live-order intent UUID. [matches ^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$] - `headers` (object, required) - `POLY_ADDRESS` (string, required): Owner address used by the local Polymarket L2 signature. [matches ^0x[0-9a-fA-F]{40}$] - `POLY_SIGNATURE` (string, required): Locally generated Polymarket L2 request signature. [at least 1 character; at most 512 characters] - `POLY_TIMESTAMP` (string, required): Unix timestamp bound into the local L2 signature. [matches ^\d{1,20}$] - `POLY_API_KEY` (string, required): Polymarket L2 credential identifier. [at least 1 character; at most 512 characters] - `POLY_PASSPHRASE` (string, required): Polymarket L2 credential passphrase. [at least 1 character; at most 512 characters] - `body` (string, required): Exact serialized FOK order envelope signed locally by the account owner. [at least 1 character; at most 20000 characters] Error statuses: 400 Invalid request; 401 Missing or invalid API key; 403 Scope, policy, or live-trading restriction; 404 Owned resource not found; 409 State or idempotency conflict; 422 Request body failed schema validation; 429 Rate limit or durable quota exceeded; 500 Internal failure; 502 Venue or provider failure; 503 Required dependency unavailable; 504 Request timeout. ### POST /v1/orders/polymarket/commit Let Felix reconcile the fill independently and record the position for an intent. Authorization: API key with `trade` scope. Rate-limit bucket: `reconcile`. `Idempotency-Key` header: required. Request body (JSON, required): - `intent_id` (string, required): Live-order intent UUID. [matches ^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$] - `order_id` (string, required): Exact venue order hash. [matches ^0x[0-9a-fA-F]{64}$] Error statuses: 400 Invalid request; 401 Missing or invalid API key; 403 Scope, policy, or live-trading restriction; 404 Owned resource not found; 409 State or idempotency conflict; 422 Request body failed schema validation; 429 Rate limit or durable quota exceeded; 500 Internal failure; 502 Venue or provider failure; 503 Required dependency unavailable; 504 Request timeout. ## Reconcile ### GET /v1/orders/polymarket/intents/{intent_id} Return the reconciled state of one client-signed intent after an uncertain or delayed venue response. Authorization: API key with `read` scope. Rate-limit bucket: `market`. Path parameters: - `intent_id` (string, required) Error statuses: 400 Invalid request; 401 Missing or invalid API key; 403 Scope, policy, or live-trading restriction; 404 Owned resource not found; 409 State or idempotency conflict; 422 Request body failed schema validation; 429 Rate limit or durable quota exceeded; 500 Internal failure; 502 Venue or provider failure; 503 Required dependency unavailable; 504 Request timeout. ## Close and redeem ### POST /v1/positions/{position_id}/polymarket/prepare Prepare a client-signed close for one owned position through the same checkpoint, submit, and commit steps. Authorization: API key with `trade` scope. Rate-limit bucket: `safety`. `Idempotency-Key` header: required. Path parameters: - `position_id` (string, required) Request body (JSON): - `client_reconciliation` (string, required): Exact-reconciliation protocol version. [one of "builder_order_v1"] Error statuses: 400 Invalid request; 401 Missing or invalid API key; 403 Scope, policy, or live-trading restriction; 404 Owned resource not found; 409 State or idempotency conflict; 422 Request body failed schema validation; 429 Rate limit or durable quota exceeded; 500 Internal failure; 502 Venue or provider failure; 503 Required dependency unavailable; 504 Request timeout. ### POST /v1/positions/{position_id}/polymarket/redeem/submit Submit the locally signed redemption of a resolved position under a persisted checkpoint. Authorization: API key with `trade` scope. Rate-limit bucket: `reconcile`. `Idempotency-Key` header: required. Path parameters: - `position_id` (string, required) Request body (JSON, required): - `intent_token` (string, required): Opaque, bounded Felix funding intent returned by the matching prepare call. [at least 1 character; at most 16000 characters] - `signed_request` (object, required): Exact owner-signed request returned by the matching prepare call. Error statuses: 400 Invalid request; 401 Missing or invalid API key; 403 Scope, policy, or live-trading restriction; 404 Owned resource not found; 409 State or idempotency conflict; 422 Request body failed schema validation; 429 Rate limit or durable quota exceeded; 500 Internal failure; 502 Venue or provider failure; 503 Required dependency unavailable; 504 Request timeout. ### POST /v1/positions/{position_id}/polymarket/redeem/confirm Confirm a submitted redemption for its intent token and reconcile it by wallet, condition, token burn, and transaction hash. Authorization: API key with `trade` scope. Rate-limit bucket: `reconcile`. Path parameters: - `position_id` (string, required) Request body (JSON, required): - `intent_token` (string, required): Opaque, bounded Felix funding intent returned by the matching prepare call. [at least 1 character; at most 16000 characters] Error statuses: 400 Invalid request; 401 Missing or invalid API key; 403 Scope, policy, or live-trading restriction; 404 Owned resource not found; 409 State or idempotency conflict; 422 Request body failed schema validation; 429 Rate limit or durable quota exceeded; 500 Internal failure; 502 Venue or provider failure; 503 Required dependency unavailable; 504 Request timeout. If a redemption reports `reconcile_required`, observe the existing intent. Never submit a replacement close. --- # API reference: Withdrawals Source: https://felix.trade/docs/api/withdrawals > Approve withdrawal destinations with owner signatures, and withdraw from a Polygon owner wallet. Every withdrawal goes to an address the owner approved with a signature. Destinations activate as soon as they are approved, and a `manage` or `transfer` key alone cannot approve one. The approved list is shared: Arc home withdrawals in [Balance](https://felix.trade/docs/api/balance) use the same destinations. ## Destinations ### GET /v1/withdrawal-addresses List approved withdrawal destinations and their owner-authorization status. Authorization: API key with `read` scope. Query parameters: - `account_id` (string, nullable, optional) Error statuses: 400 Invalid request; 401 Missing or invalid API key; 403 Scope, policy, or live-trading restriction; 404 Owned resource not found; 409 State or idempotency conflict; 422 Request body failed schema validation; 429 Rate limit or durable quota exceeded; 500 Internal failure; 502 Venue or provider failure; 503 Required dependency unavailable; 504 Request timeout. ### POST /v1/withdrawal-addresses/prepare Return the short-lived message binding the account, address, chain, and expiry that the owner must sign. Authorization: API key with `manage` scope. Rate-limit bucket: `manage`. `Idempotency-Key` header: required. Request body (JSON, required): - `account_id` (string, optional): Target isolated account UUID. Omit to use the key's own account. [matches ^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$] - `address` (string, required): Polygon withdrawal address to authorize. [matches ^0x[0-9a-fA-F]{40}$] - `chain` (string, optional): Withdrawal chain. [one of "polygon"; default "polygon"] Error statuses: 400 Invalid request; 401 Missing or invalid API key; 403 Scope, policy, or live-trading restriction; 404 Owned resource not found; 409 State or idempotency conflict; 422 Request body failed schema validation; 429 Rate limit or durable quota exceeded; 500 Internal failure; 502 Venue or provider failure; 503 Required dependency unavailable; 504 Request timeout. ### POST /v1/withdrawal-addresses Add and immediately activate a destination from the owner-signed message. Authorization: API key with `manage` scope. Rate-limit bucket: `manage`. `Idempotency-Key` header: required. Request body (JSON, required): - `account_id` (string, optional): Target isolated account UUID. Omit to use the key's own account. [matches ^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$] - `address` (string, required): Owner-approved Polygon withdrawal address. [matches ^0x[0-9a-fA-F]{40}$] - `chain` (string, optional): Withdrawal chain. [one of "polygon"; default "polygon"] - `owner_message` (string, required): Exact message returned by withdrawal-addresses/prepare. [at least 1 character; at most 512 characters] - `owner_signature` (string, required): Owner's canonical 65-byte personal-sign signature. [matches ^0x[0-9a-fA-F]{130}$] Error statuses: 400 Invalid request; 401 Missing or invalid API key; 403 Scope, policy, or live-trading restriction; 404 Owned resource not found; 409 State or idempotency conflict; 422 Request body failed schema validation; 429 Rate limit or durable quota exceeded; 500 Internal failure; 502 Venue or provider failure; 503 Required dependency unavailable; 504 Request timeout. ### POST /v1/withdrawal-addresses/{addr_id}/confirm Re-authorize a destination created before owner-signed destinations existed, using the same owner signature. Authorization: API key with `manage` scope. Rate-limit bucket: `manage`. `Idempotency-Key` header: required. Path parameters: - `addr_id` (string, required) Query parameters: - `account_id` (string, nullable, optional) Request body (JSON, required): - `owner_message` (string, required): Exact message returned by withdrawal-addresses/prepare. [at least 1 character; at most 512 characters] - `owner_signature` (string, required): Owner's canonical 65-byte personal-sign signature. [matches ^0x[0-9a-fA-F]{130}$] Error statuses: 400 Invalid request; 401 Missing or invalid API key; 403 Scope, policy, or live-trading restriction; 404 Owned resource not found; 409 State or idempotency conflict; 422 Request body failed schema validation; 429 Rate limit or durable quota exceeded; 500 Internal failure; 502 Venue or provider failure; 503 Required dependency unavailable; 504 Request timeout. ## Withdraw from a Polygon owner wallet These routes serve accounts that still hold funds in a Polygon owner wallet. Withdrawals from the Arc home are in [Balance](https://felix.trade/docs/api/balance). > **Warning: Token choice** > A USDC.e withdrawal delivers bridged USDC.e on Polygon at contract `0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174`. Many exchanges do not accept it. Unless the exchange confirms support, withdraw to a self-custody Polygon wallet and convert to native USDC first. ### POST /v1/withdraw/prepare Build the unsigned withdrawal transaction for the owner to sign after the destination checks. Authorization: API key with `transfer` scope. Rate-limit bucket: `transfer`. `Idempotency-Key` header: required. Request body (JSON, required): - `account_id` (string, optional): Target isolated account UUID. Omit to use the key's own account. [matches ^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$] - `to` (string, required): Confirmed, active allowlisted destination. [matches ^0x[0-9a-fA-F]{40}$] - `amount` (number, required): USD notional. [greater than 0] - `token` (string, optional): Token symbol. [one of "USDC.e", "pUSD", "USDC"; default "USDC.e"] - `source` (string, optional): Withdrawal source. auto uses the Safe when funded, otherwise the owner wallet. [one of "auto", "safe", "owner_wallet"; default "auto"] - `gas_grant` (object, optional): Optional exact owner-signed gas sponsorship grant. Error statuses: 400 Invalid request; 401 Missing or invalid API key; 403 Scope, policy, or live-trading restriction; 404 Owned resource not found; 409 State or idempotency conflict; 422 Request body failed schema validation; 429 Rate limit or durable quota exceeded; 500 Internal failure; 502 Venue or provider failure; 503 Required dependency unavailable; 504 Request timeout. ### POST /v1/withdraw/submit Broadcast a withdrawal signed by the owner. Accepts only the request id and the 65-byte signature, never a private key. Authorization: API key with `transfer` scope. Rate-limit bucket: `transfer`. `Idempotency-Key` header: required. Request body (JSON, required): - `account_id` (string, optional): Target isolated account UUID. Omit to use the key's own account. [matches ^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$] - `request_id` (string, required): Prepared withdrawal UUID. [matches ^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$] - `owner_signature` (string, required): Owner's canonical 65-byte signature. [matches ^0x[0-9a-fA-F]{130}$] Error statuses: 400 Invalid request; 401 Missing or invalid API key; 403 Scope, policy, or live-trading restriction; 404 Owned resource not found; 409 State or idempotency conflict; 422 Request body failed schema validation; 429 Rate limit or durable quota exceeded; 500 Internal failure; 502 Venue or provider failure; 503 Required dependency unavailable; 504 Request timeout. ### POST /v1/withdraw Deprecated server-signed withdrawal kept for compatibility. New clients must use prepare and submit. Authorization: API key with `manage` scope. Rate-limit bucket: `transfer`. `Idempotency-Key` header: required. Deprecated. Request body (JSON, required): - `account_id` (string, optional): Target isolated account UUID. Omit to use the key's own account. [matches ^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$] - `address` (string, required): Legacy allowlisted destination. [matches ^0x[0-9a-fA-F]{40}$] - `amount` (number, required): USD notional. [greater than 0] - `token` (string, optional): Token symbol. [one of "USDC.e", "pUSD", "USDC"] - `chain` (string, optional): Withdrawal chain. [one of "polygon"] Error statuses: 400 Invalid request; 401 Missing or invalid API key; 403 Scope, policy, or live-trading restriction; 404 Owned resource not found; 409 State or idempotency conflict; 422 Request body failed schema validation; 429 Rate limit or durable quota exceeded; 500 Internal failure; 502 Venue or provider failure; 503 Required dependency unavailable; 504 Request timeout. --- # API reference: Settlement transfers Source: https://felix.trade/docs/api/settlement > The owner-signed cross-chain transfer journey for USDC on Arc, and the read-only settlement discovery routes. A settlement transfer moves USDC between Arc and another chain through Circle's cross-chain transfer. The owner signs and broadcasts every transaction. Felix prepares the calls, records the journey, submits the owner's signed burn intent to Circle, and reconciles each phase from chain proof. There is no signer on the server. For everyday deposits into and withdrawals from the Arc home, the routes in [Balance](https://felix.trade/docs/api/balance) are simpler. Use these when you need the lower-level journey. ## Discover ### GET /v1/settlement/capabilities Public settlement and deposit discovery: supported chains, assets, and whether Arc transfers are available. No key required. Authorization: No API key. Error statuses: 400 Invalid request; 401 Missing or invalid API key; 403 Scope, policy, or live-trading restriction; 404 Owned resource not found; 409 State or idempotency conflict; 429 Rate limit or durable quota exceeded; 500 Internal failure; 502 Venue or provider failure; 503 Required dependency unavailable; 504 Request timeout. ### GET /v1/settlement/operations List this account's settlement journeys. Authorization: API key with `read` scope. Rate-limit bucket: `read`. Query parameters: - `limit` (integer, optional) [minimum 1; maximum 50; default 20] - `cursor` (string, nullable, optional) [at least 1 character; at most 1024 characters] Error statuses: 400 Invalid request; 401 Missing or invalid API key; 403 Scope, policy, or live-trading restriction; 404 Owned resource not found; 409 State or idempotency conflict; 422 Request body failed schema validation; 429 Rate limit or durable quota exceeded; 500 Internal failure; 502 Venue or provider failure; 503 Required dependency unavailable; 504 Request timeout. ### GET /v1/settlement/operations/{operation_id} Read one journey. An unknown id and another account's id both return 404. Authorization: API key with `read` scope. Rate-limit bucket: `read`. Path parameters: - `operation_id` (string, required) Error statuses: 400 Invalid request; 401 Missing or invalid API key; 403 Scope, policy, or live-trading restriction; 404 Owned resource not found; 409 State or idempotency conflict; 422 Request body failed schema validation; 429 Rate limit or durable quota exceeded; 500 Internal failure; 502 Venue or provider failure; 503 Required dependency unavailable; 504 Request timeout. ## Transfer journey 1. `prepare` creates the journey and returns the calls the owner signs on the source chain. 2. `source-submitted` records the owner's deposit transaction. 3. `authorization/prepare` returns a fresh burn intent, and `authorize` verifies the owner's signature over it, submits it to Circle, and returns the mint call. 4. `destination-submitted` records the owner's mint transaction. 5. `reconcile` advances at most one proven phase at a time. ### POST /v1/settlement/transfers/prepare Create one owner-scoped transfer journey and return the calls the owner signs. Authorization: API key with `manage` and `transfer` scope. Rate-limit bucket: `transfer`. `Idempotency-Key` header: required. Request body (JSON, required): - `source_domain` (integer, required): Circle Gateway source domain (not an EVM chain id). [minimum 0; maximum 4294967295] - `destination_domain` (integer, required): Circle Gateway destination domain; one side must be the pinned Arc domain. [minimum 0; maximum 4294967295] - `amount_units` (string, required): Exact six-decimal USDC integer units as a decimal string. [matches ^(?:0|[1-9][0-9]{0,77})$] - `maximum_fee_units` (string, required): Exact six-decimal USDC integer units as a decimal string. [matches ^(?:0|[1-9][0-9]{0,77})$] Error statuses: 400 Invalid request; 401 Missing or invalid API key; 403 Scope, policy, or live-trading restriction; 404 Owned resource not found; 409 State or idempotency conflict; 422 Request body failed schema validation; 429 Rate limit or durable quota exceeded; 500 Internal failure; 502 Venue or provider failure; 503 Required dependency unavailable; 504 Request timeout. ### POST /v1/settlement/transfers/{operation_id}/source-submitted Record the owner's source deposit transaction. Repeating the same hash is safe. Authorization: API key with `manage` and `transfer` scope. Rate-limit bucket: `transfer`. Path parameters: - `operation_id` (string, required) Request body (JSON, required): - `source_transaction_hash` (string, required): Lowercase 0x-prefixed 32-byte transaction hash submitted by the owner. [matches ^0x[0-9a-f]{64}$] Error statuses: 400 Invalid request; 401 Missing or invalid API key; 403 Scope, policy, or live-trading restriction; 404 Owned resource not found; 409 State or idempotency conflict; 422 Request body failed schema validation; 429 Rate limit or durable quota exceeded; 500 Internal failure; 502 Venue or provider failure; 503 Required dependency unavailable; 504 Request timeout. ### POST /v1/settlement/transfers/{operation_id}/authorization/prepare Return a fresh owner-bound burn intent right before local signing. Authorization: API key with `manage` and `transfer` scope. Rate-limit bucket: `transfer`. Path parameters: - `operation_id` (string, required) Error statuses: 400 Invalid request; 401 Missing or invalid API key; 403 Scope, policy, or live-trading restriction; 404 Owned resource not found; 409 State or idempotency conflict; 422 Request body failed schema validation; 429 Rate limit or durable quota exceeded; 500 Internal failure; 502 Venue or provider failure; 503 Required dependency unavailable; 504 Request timeout. ### POST /v1/settlement/transfers/{operation_id}/authorize Verify the owner's burn-intent signature, submit it to Circle, and return the mint call. Authorization: API key with `manage` and `transfer` scope. Rate-limit bucket: `transfer`. `Idempotency-Key` header: required. Path parameters: - `operation_id` (string, required) Request body (JSON, required): - `burn_intent` (object, required): The exact EIP-712 BurnIntent message returned by prepare as burn_intent_typed_data.message. - `maxBlockHeight` (integer, required): Block height after which the intent is void; must not be below the journey's expiration height. [minimum 0] - `maxFee` (integer, required): Fee ceiling in six-decimal USDC units. [minimum 0] - `spec` (object, required): The exact TransferSpec returned by prepare; any other shape is rejected. - `version` (integer, required): TransferSpec version from prepare. - `sourceDomain` (integer, required): Circle Gateway source domain. [minimum 0; maximum 4294967295] - `destinationDomain` (integer, required): Circle Gateway destination domain. [minimum 0; maximum 4294967295] - `sourceContract` (string, required): 0x-prefixed even-length hex. [matches ^0x(?:[0-9a-fA-F]{2})*$] - `destinationContract` (string, required): 0x-prefixed even-length hex. [matches ^0x(?:[0-9a-fA-F]{2})*$] - `sourceToken` (string, required): 0x-prefixed even-length hex. [matches ^0x(?:[0-9a-fA-F]{2})*$] - `destinationToken` (string, required): 0x-prefixed even-length hex. [matches ^0x(?:[0-9a-fA-F]{2})*$] - `sourceDepositor` (string, required): 0x-prefixed even-length hex. [matches ^0x(?:[0-9a-fA-F]{2})*$] - `destinationRecipient` (string, required): 0x-prefixed even-length hex. [matches ^0x(?:[0-9a-fA-F]{2})*$] - `sourceSigner` (string, required): 0x-prefixed even-length hex. [matches ^0x(?:[0-9a-fA-F]{2})*$] - `destinationCaller` (string, required): 0x-prefixed even-length hex. [matches ^0x(?:[0-9a-fA-F]{2})*$] - `value` (integer, required): Amount in six-decimal USDC units. [minimum 0] - `salt` (string, required): 0x-prefixed even-length hex. [matches ^0x(?:[0-9a-fA-F]{2})*$] - `hookData` (string, required): 0x-prefixed hex; may be empty (0x). [matches ^0x(?:[0-9a-fA-F]{2})*$] - `signature` (string, required): Owner's EIP-712 signature over the burn intent. [at most 1100000 characters; matches ^0x(?:[0-9a-fA-F]{2})*$] Error statuses: 400 Invalid request; 401 Missing or invalid API key; 403 Scope, policy, or live-trading restriction; 404 Owned resource not found; 409 State or idempotency conflict; 422 Request body failed schema validation; 429 Rate limit or durable quota exceeded; 500 Internal failure; 502 Venue or provider failure; 503 Required dependency unavailable; 504 Request timeout. ### POST /v1/settlement/transfers/{operation_id}/destination-submitted Record the owner's mint transaction. The chain receipt is the later proof. Authorization: API key with `manage` and `transfer` scope. Rate-limit bucket: `transfer`. Path parameters: - `operation_id` (string, required) Request body (JSON, required): - `destination_transaction_hash` (string, required): Lowercase 0x-prefixed 32-byte transaction hash submitted by the owner. [matches ^0x[0-9a-f]{64}$] Error statuses: 400 Invalid request; 401 Missing or invalid API key; 403 Scope, policy, or live-trading restriction; 404 Owned resource not found; 409 State or idempotency conflict; 422 Request body failed schema validation; 429 Rate limit or durable quota exceeded; 500 Internal failure; 502 Venue or provider failure; 503 Required dependency unavailable; 504 Request timeout. ### POST /v1/settlement/transfers/{operation_id}/reconcile Advance at most one proven phase of this account's journey. Authorization: API key with `manage` and `transfer` scope. Rate-limit bucket: `transfer`. Path parameters: - `operation_id` (string, required) Error statuses: 400 Invalid request; 401 Missing or invalid API key; 403 Scope, policy, or live-trading restriction; 404 Owned resource not found; 409 State or idempotency conflict; 422 Request body failed schema validation; 429 Rate limit or durable quota exceeded; 500 Internal failure; 502 Venue or provider failure; 503 Required dependency unavailable; 504 Request timeout. ### POST /v1/settlement/transfers/{operation_id}/rpc/{chain_id} Journey-scoped JSON-RPC relay for the owner's signed transactions and bounded reads. Authorization: API key with `manage` and `transfer` scope. Rate-limit bucket: `wallet_rpc`. Path parameters: - `operation_id` (string, required) - `chain_id` (integer, required) Request body (JSON, required): - `jsonrpc` (string, required): Always 2.0. [one of "2.0"] - `id` (string or integer, required): Echoed JSON-RPC id (string or integer; booleans are rejected). [at most 80 characters] - `method` (string, required): eth_sendRawTransaction for the journey's own owner-signed approve, deposit or mint call; otherwise a bounded owner-scoped read (nonce, fees, receipt, eth_call/eth_estimateGas against the journey's contracts). [matches ^eth_[A-Za-z0-9]{1,40}$] - `params` (array of any, optional): At most three JSON-RPC parameters; exactly one raw transaction for eth_sendRawTransaction. [at most 3 items] Error statuses: 400 Invalid request; 401 Missing or invalid API key; 403 Scope, policy, or live-trading restriction; 404 Owned resource not found; 409 State or idempotency conflict; 422 Request body failed schema validation; 429 Rate limit or durable quota exceeded; 500 Internal failure; 502 Venue or provider failure; 503 Required dependency unavailable; 504 Request timeout. ### POST /v1/settlement/transfers/{operation_id}/cancel Cancel a journey that has not reported a deposit yet. Authorization: API key with `manage` and `transfer` scope. Rate-limit bucket: `transfer`. Path parameters: - `operation_id` (string, required) Error statuses: 400 Invalid request; 401 Missing or invalid API key; 403 Scope, policy, or live-trading restriction; 404 Owned resource not found; 409 State or idempotency conflict; 422 Request body failed schema validation; 429 Rate limit or durable quota exceeded; 500 Internal failure; 502 Venue or provider failure; 503 Required dependency unavailable; 504 Request timeout. --- # API reference: Strategies Source: https://felix.trade/docs/api/strategies > Read the strategy sandbox contract and, optionally, generate a strategy from a plain-language idea. A strategy is Python source with one `think(ctx)` entry point. `GET /v1/strategies/context` returns the full contract: the decision schema, every `ctx` method, and the allowed language subset. Hand-written strategies need no generation call. Generation turns a plain-language idea into a `compiled_strategy` you can pass to backtests and deployments, and counts against the account's daily generation quota (60 on Free, 600 on Pro, 6,000 on Max). ### GET /v1/strategies/context Return the strategy sandbox reference, generated from the runtime code: the decision schema, every ctx method, and the safe language subset. Authorization: API key with `read` scope. Error statuses: 400 Invalid request; 401 Missing or invalid API key; 403 Scope, policy, or live-trading restriction; 404 Owned resource not found; 409 State or idempotency conflict; 429 Rate limit or durable quota exceeded; 500 Internal failure; 502 Venue or provider failure; 503 Required dependency unavailable; 504 Request timeout. ### POST /v1/strategies/generate Turn a plain-language idea into a runnable, AST-validated strategy. Uses the account's generation budget. Authorization: API key with `trade` scope. Rate-limit bucket: `strategy`. `Idempotency-Key` header: required. Request body (JSON, required): - `prompt` (string, required): Plain-English strategy request. [at least 1 character; at most 4000 characters] Error statuses: 400 Invalid request; 401 Missing or invalid API key; 403 Scope, policy, or live-trading restriction; 404 Owned resource not found; 409 State or idempotency conflict; 422 Request body failed schema validation; 429 Rate limit or durable quota exceeded; 500 Internal failure; 502 Venue or provider failure; 503 Required dependency unavailable; 504 Request timeout. Generated code is validated before it runs and executes only inside the bounded strategy runtime. Exact retries with the same prompt and `Idempotency-Key` return the cached result. --- # API reference: Backtests Source: https://felix.trade/docs/api/backtests > Run a read-only backtest synchronously or as a durable operation, poll it, and resume it after an expired lease. Backtests never deploy an agent, place an order, sign a transaction, or change a balance. They need only `read` scope. How to read a result is in [Research and backtests](https://felix.trade/docs/guides/research-and-backtests). ### POST /v1/backtests Backtest a strategy on real historical bars and return the result, or with async set to true return an operation id for a durable job. Authorization: API key with `read` scope. Rate-limit bucket: `backtest`. `Idempotency-Key` header: required. Request body (JSON, required): - `strategy` (object, optional): Compiled strategy containing def think(ctx). - `compiled_strategy` (object, optional): Compatibility alias for strategy. - `markets` (array of string, optional): One to four instruments. [at least 1 item; at most 4 items] - `venue` (string, optional): Optional market-class hint. [at most 40 characters] - `name` (string, optional): Display name included in the chart-ready summary. [at least 1 character; at most 80 characters; default "Strategy"] - `interval` (string, optional): Bar interval. [one of "1m", "5m", "15m", "1h", "4h", "1d"; default "1h"] - `bars` (integer, optional): Historical bars. The interval-specific ceiling is returned in validation errors; Felix never silently clamps. [minimum 20; maximum 45000; default 300] - `years` (number, optional): Historical years. Overrides bars; use 1d for windows up to 40 years. [minimum 0.1; maximum 40] - `capital` (number, optional): Starting capital. [minimum 10; maximum 1000000; default 1000] - `fee_bps_per_side` (number, optional): Execution fee charged on every simulated fill. Use evidenced venue costs; the compatibility default is 5 bps per side. [minimum 0; maximum 10000; default 5] - `slippage_bps_per_side` (number, optional): Adverse price movement applied to every simulated fill. The compatibility default is 0 bps per side. [minimum 0; maximum 5000; default 0] - `detail` (string, optional): summary is compact and agent-friendly; full also includes raw curves, positions, and price series. [one of "summary", "full"; default "full"] - `async` (boolean, optional): Return an operation handle immediately and run the backtest in the background. [default false] Error statuses: 400 Invalid request; 401 Missing or invalid API key; 403 Scope, policy, or live-trading restriction; 404 Owned resource not found; 409 State or idempotency conflict; 422 Request body failed schema validation; 429 Rate limit or durable quota exceeded; 500 Internal failure; 502 Venue or provider failure; 503 Required dependency unavailable; 504 Request timeout. For long runs, call POST /v1/backtests with body field async:true. It returns an operation id at once; poll the operation for progress and the result. ### GET /v1/backtests/operations/{operation_id} Read progress or the terminal result of a durable backtest without starting another computation. Authorization: API key with `read` scope. Rate-limit bucket: `backtest`. Path parameters: - `operation_id` (string, required) Error statuses: 400 Invalid request; 401 Missing or invalid API key; 403 Scope, policy, or live-trading restriction; 404 Owned resource not found; 409 State or idempotency conflict; 422 Request body failed schema validation; 429 Rate limit or durable quota exceeded; 500 Internal failure; 502 Venue or provider failure; 503 Required dependency unavailable; 504 Request timeout. ### POST /v1/backtests/operations/{operation_id}/resume Resume a durable backtest only after its worker lease expired; completed operations replay their terminal result. Authorization: API key with `read` scope. Rate-limit bucket: `backtest`. Path parameters: - `operation_id` (string, required) Error statuses: 400 Invalid request; 401 Missing or invalid API key; 403 Scope, policy, or live-trading restriction; 404 Owned resource not found; 409 State or idempotency conflict; 422 Request body failed schema validation; 429 Rate limit or durable quota exceeded; 500 Internal failure; 502 Venue or provider failure; 503 Required dependency unavailable; 504 Request timeout. ## Bounds Bounds are rejected, never clamped. | Parameter | Allowed | | --- | --- | | `markets` | 1 to 4 canonical instruments | | `interval` | `1m`, `5m`, `15m`, `1h`, `4h`, `1d` | | `bars` | Minimum 20; caps of 20,000 (`1m`), 25,000 (`5m`), 30,000 (`15m`), 45,000 (`1h`), 15,000 (`4h`), and 12,000 (`1d`) | | `years` | 0.1 to 40, for intervals wider than one minute | | `capital` | 10 to 1,000,000 USD | | `detail` | `summary` or `full` | | Durable `Idempotency-Key` | `fxbt_` followed by 32 lowercase hexadecimal characters | Daily quotas for new backtest workflows are 50 on Free, 500 on Pro, and 5,000 on Max. Exact replays return the cached result and do not count again. ## Robustness checks These run several backtests in one call to test whether a result holds up. Each counts against its own daily quota of 10 on Free, 50 on Pro, and 200 on Max, and against the `expensive` rate-limit bucket. ### POST /v1/backtests/walk-forward Choose among strategy variants on earlier data and evaluate the choice on later data it never saw. Authorization: API key with `read` scope. Rate-limit bucket: `expensive`. Request body (JSON, required): - `variants` (array of any, required): Two to four explicit strategy variants evaluated on one shared immutable dataset. [at least 2 items; at most 4 items] - `name` (string, required): Unique variant label. [at least 1 character; at most 80 characters] - `strategy` (object, optional): Compiled strategy containing def think(ctx). - `compiled_strategy` (object, optional): Compatibility alias for strategy. - `market` (string, required): One canonical instrument shared by every variant. [at least 1 character; at most 80 characters] - `venue` (string, optional): Optional market-class hint. [one of "hyperliquid", "hyperliquid_spot", "polymarket"] - `interval` (string, optional): Bar interval. [one of "1m", "5m", "15m", "1h", "4h", "1d"; default "1h"] - `bars` (integer, optional): Aligned bars split chronologically into anchored training and untouched holdout windows. [minimum 80; maximum 2000; default 600] - `capital` (number, optional): Fresh starting capital for every training and holdout replay. [minimum 10; maximum 1000000; default 1000] - `fee_bps_per_side` (number, optional): Execution fee charged on every training and holdout fill. [minimum 0; maximum 10000; default 5] - `slippage_bps_per_side` (number, optional): Adverse price movement applied to every training and holdout fill. [minimum 0; maximum 5000; default 0] - `folds` (integer, optional): Number of chronological holdouts. [minimum 2; maximum 4; default 3] - `objective` (string, optional): Training-only variant selection objective. [one of "sharpe", "total_return_pct", "return_over_drawdown"; default "return_over_drawdown"] - `min_train_trades` (integer, optional): Minimum clean training trades required before a variant can be selected. [minimum 0; maximum 100; default 1] Error statuses: 400 Invalid request; 401 Missing or invalid API key; 403 Scope, policy, or live-trading restriction; 404 Owned resource not found; 409 State or idempotency conflict; 422 Request body failed schema validation; 429 Rate limit or durable quota exceeded; 500 Internal failure; 502 Venue or provider failure; 503 Required dependency unavailable; 504 Request timeout. ### POST /v1/backtests/sensitivity Re-run a backtest across execution-cost and history-window settings to show how much the result depends on them. Authorization: API key with `read` scope. Rate-limit bucket: `expensive`. `Idempotency-Key` header: required. Request body (JSON, required): - `strategy` (object, optional): Compiled strategy containing def think(ctx). - `compiled_strategy` (object, optional): Compatibility alias for strategy. - `market` (string, required): One canonical instrument shared by every scenario. [at least 1 character; at most 80 characters] - `venue` (string, optional): Optional market-class hint. [one of "hyperliquid", "hyperliquid_spot", "polymarket"] - `interval` (string, optional): Bar interval. [one of "1m", "5m", "15m", "1h", "4h", "1d"; default "1h"] - `scenarios` (array of object, required): Two to eight explicit history and execution-cost assumptions run sequentially on one shared immutable price dataset. [at least 2 items; at most 8 items] - `name` (string, required): Unique scenario label. [at least 1 character; at most 80 characters] - `bars` (integer, required): Trailing aligned history used by this scenario. [minimum 20; maximum 2000] - `capital` (number, required): Fresh starting capital for this scenario. [minimum 10; maximum 1000000] - `fee_bps_per_side` (number, required): Execution fee applied to every simulated fill. [minimum 0; maximum 10000] - `slippage_bps_per_side` (number, required): Adverse movement applied to every simulated fill. [minimum 0; maximum 5000] - `min_trades` (integer, optional): Minimum clean trades required in every scenario before robustness can be true. [minimum 0; maximum 100; default 1] Error statuses: 400 Invalid request; 401 Missing or invalid API key; 403 Scope, policy, or live-trading restriction; 404 Owned resource not found; 409 State or idempotency conflict; 422 Request body failed schema validation; 429 Rate limit or durable quota exceeded; 500 Internal failure; 502 Venue or provider failure; 503 Required dependency unavailable; 504 Request timeout. ### POST /v1/backtests/strategy-revision-review Compare one saved strategy with a candidate revision on the same data, without changing either. Authorization: API key with `read` scope. Rate-limit bucket: `expensive`. Request body (JSON, required): - `agent_id` (string, required): Caller-owned saved agent UUID. [matches ^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$] - `candidate_strategy` (object, required): Proposed strategy containing def think(ctx). The saved current source is loaded internally and is never returned. - `market` (string, optional): One market authorized by the saved agent. Required when the agent authorizes multiple markets. [at least 1 character; at most 120 characters] - `interval` (string, optional): Bar interval. [one of "1m", "5m", "15m", "1h", "4h", "1d"; default "1h"] - `bars` (integer, optional): Exact shared historical bars split into development and holdout phases. [minimum 80; maximum 2000; default 600] - `capital` (number, optional): Fresh hypothetical capital used independently for every replay phase. [minimum 10; maximum 1000000; default 1000] - `holdout_fraction` (number, optional): Trailing chronological cold-state holdout fraction. [minimum 0.2; maximum 0.5; default 0.3] - `objective` (string, optional): Holdout comparison objective. [one of "sharpe", "total_return_pct", "return_over_drawdown"; default "return_over_drawdown"] - `min_holdout_trades` (integer, optional): Minimum candidate holdout trades before the comparison is decision-usable. [minimum 0; maximum 1000; default 1] - `fee_bps_per_side` (number, optional): Execution fee charged on every simulated fill in every phase. [minimum 0; maximum 10000; default 5] - `slippage_bps_per_side` (number, optional): Adverse movement applied to every simulated fill in every phase. [minimum 0; maximum 5000; default 0] Error statuses: 400 Invalid request; 401 Missing or invalid API key; 403 Scope, policy, or live-trading restriction; 404 Owned resource not found; 409 State or idempotency conflict; 422 Request body failed schema validation; 429 Rate limit or durable quota exceeded; 500 Internal failure; 502 Venue or provider failure; 503 Required dependency unavailable; 504 Request timeout. ### POST /v1/backtests/portfolio Replay several of your agents together, each with its own capital, as one portfolio. Authorization: API key with `read` scope. Rate-limit bucket: `expensive`. Request body (JSON, required): - `sleeves` (array of object, required): Two to six unique saved agents whose weights total exactly 10000 bps. [at least 2 items; at most 6 items] - `agent_id` (string, required): Caller-owned saved agent UUID. [at least 36 characters; at most 36 characters] - `weight_bps` (integer, required): Fixed capital allocation in basis points. [minimum 1; maximum 9999] - `interval` (string, optional): Shared bar interval. [one of "1m", "5m", "15m", "1h", "4h", "1d"; default "1h"] - `bars` (integer, optional): Trailing bars fetched once per represented venue. [minimum 80; maximum 2000; default 600] - `capital` (number, optional): Total hypothetical capital split into independent fixed sleeves. [minimum 10; maximum 1000000; default 1000] - `holdout_fraction` (number, optional): Trailing chronological fraction replayed from cold strategy state. [minimum 0.2; maximum 0.5; default 0.3] - `min_holdout_trades` (integer, optional): Minimum aggregate holdout trades required by the verdict. [minimum 0; maximum 1000; default 1] - `min_holdout_return_pct` (number, optional): Optional explicit minimum aggregate holdout return. - `max_holdout_drawdown_pct` (number, optional): Optional explicit maximum absolute holdout drawdown. [minimum 0; maximum 100] - `fee_bps_per_side` (number, optional): Execution fee charged on every simulated fill. [minimum 0; maximum 10000; default 5] - `slippage_bps_per_side` (number, optional): Adverse movement applied to every simulated fill. [minimum 0; maximum 5000; default 0] Error statuses: 400 Invalid request; 401 Missing or invalid API key; 403 Scope, policy, or live-trading restriction; 404 Owned resource not found; 409 State or idempotency conflict; 422 Request body failed schema validation; 429 Rate limit or durable quota exceeded; 500 Internal failure; 502 Venue or provider failure; 503 Required dependency unavailable; 504 Request timeout. --- # API reference: Agents Source: https://felix.trade/docs/api/agents > Deploy, list, inspect, update, and stop agents, read their decision logs, take the one-call situation snapshot, and long-poll account events. An agent runs a strategy on a schedule with an explicit budget, a list of markets, and risk limits. A live agent places real orders without asking before each one, within those limits and the authority of the key that deployed it. How agents behave day to day is in [Run agents](https://felix.trade/docs/guides/run-agents). ## Limits an agent carries | Field | Rule | | --- | --- | | `budget_usd` | The most the agent may have deployed. | | `max_position_usd` | The largest single position. An order above it counts as an error. | | `max_daily_loss_usd` | At most `budget_usd`. Counted against losses realized by every agent on the account during the current UTC day, so one agent's losses reduce the room the others have left. | | `cycle_seconds` | How often the agent runs, up to 86,400. The minimum depends on the agent's venues (30 seconds for Hyperliquid); the error names it. | | `leverage` | A whole number from 1 to 20 for perpetuals on Hyperliquid and Lighter, capped at each market's maximum. `allow_leverage: true` without a level means 5x. | An agent pauses itself after 3 errors in a row. Through the API, change limits only on a stopped, paused, or errored agent; a running agent returns `409 agent_must_be_stopped`. The number of active agents an account may run depends on its plan; see [Plans](https://felix.trade/docs/api/plans). Agents that react to every market move instead of running on a schedule need a paid plan. ## Venues Agents can trade Polymarket, Hyperliquid, Lighter, and Derive. Lighter is available to agents only. If an agent is allowed to trade the same market on both Hyperliquid and Lighter and the venue an order is aimed at is unavailable, Felix places the order on the other one with the same side, size, and leverage, capped at that venue's maximum. ## Lifecycle ### POST /v1/agents Deploy a hand-written or compiled strategy as an agent with a budget, its markets, risk limits, optional exit rules, and live or paper mode. Authorization: API key with `trade` scope. Rate-limit bucket: `order`. `Idempotency-Key` header: required. Request body (JSON, required): - `strategy` (object, optional): Compiled strategy containing def think(ctx). - `compiled_strategy` (object, optional): Compatibility alias for strategy. - `name` (string, optional): Agent name. [at most 80 characters] - `budget_usd` (number, required): Agent budget. [greater than 0; maximum 1000000000; default 100] - `mode` (string, optional): Execution mode; defaults to live. Set paper explicitly for simulation. [one of "live", "paper"; default "live"] - `venue` (string, optional): Public market class. [one of "prediction_market", "crypto", "options"] - `markets` (array of string, required): One to four instruments; required for live agents and enforced on every open. [at least 1 item; at most 4 items] - `cycle_seconds` (integer, optional): Scheduled timer or market-mode idle scheduled fallback, separate from the market-event minimum interval. Market evaluations postpone the fallback; continuous activity can defer it indefinitely. It does not run independently. Polymarket requires at least 5 seconds; Hyperliquid and Derive require at least 30 seconds in either trigger mode. Neither interval guarantees order-to-fill latency. [minimum 5; maximum 86400; default 300] - `evaluation_trigger` (string, optional): scheduled uses cycle_seconds as a timer; market evaluates on market updates with an idle scheduled fallback. Market evaluations postpone the fallback, so continuous activity can defer it indefinitely; it does not run independently. Market-triggered evaluation must be supported and enabled on this deployment first; otherwise market_evaluation_unavailable is returned. Use scheduled evaluation or contact support. Omission retains scheduled behavior. Bound into encrypted execution intent. [one of "scheduled", "market"; default "scheduled"] - `min_event_interval_ms` (integer, optional): Per-agent minimum milliseconds between market-event evaluations, separate from the cycle_seconds idle scheduled fallback. Updates may be coalesced and decisions may take longer; this is not an order-to-fill latency guarantee. Unused in scheduled mode. Integer only, without coercion. [minimum 250; maximum 60000; default 1000] - `max_position_usd` (number, optional): Live per-position ceiling. [greater than 0] - `max_daily_loss_usd` (number, optional): Live daily-loss ceiling. [greater than 0] - `allow_leverage` (boolean, optional): Explicitly permit Hyperliquid or Lighter perp notional above free collateral (5x). Omitted or false keeps the agent unleveraged. [default false] - `leverage` (integer, optional): Leverage for live Hyperliquid or Lighter perp orders, 1 to 20, capped per coin by the venue. Felix sets it on the venue before each open; each order needs size / leverage of margin. Above 1 implies allow_leverage. [minimum 1; maximum 20; default 1] - `stop_loss_pct` (number, optional): Optional server-monitored hard-stop loss fraction for Hyperliquid and Derive agents, e.g. 0.05 for 5%. Omit it to run without a server stop. [minimum 0.001; maximum 0.99] - `take_profit_pct` (number, optional): Optional server-monitored profit target fraction. [minimum 0.001; maximum 10] - `trailing_stop_pct` (number, optional): Optional server-monitored trailing distance fraction. [minimum 0.001; maximum 0.99] - `trailing_activation_pct` (number, optional): Optional profit fraction before the trailing stop arms. [minimum 0; maximum 10] - `break_even_after_pct` (number, optional): Optional profit fraction that activates a break-even exit. [minimum 0.001; maximum 10] - `max_holding_minutes` (number, optional): Optional maximum position age in minutes. [minimum 1; maximum 525600] - `prompt` (string, optional): Optional source prompt retained encrypted for audit. [at most 500 characters] - `replay_attestation` (string, optional): Signed proof that this exact strategy code was replayed, from replay_attestation.token on a POST /v1/backtests result. Required for mode=live unless acknowledge_unvalidated is true. The proof binds to sha256 of the code, to this account, and expires 24 hours after the replay. [at least 32 characters; at most 4096 characters] - `acknowledge_unvalidated` (boolean, optional): Explicitly deploy live without verified replay evidence, or with a replay whose historical validity is degraded because the strategy reads live-only signals. The waiver and the conditions it covers are recorded on the agent and returned in strategy_evidence. A replay proof that fails verification is refused regardless of this flag. Paper agents reject this field. [default false] Error statuses: 400 Invalid request; 401 Missing or invalid API key; 403 Scope, policy, or live-trading restriction; 404 Owned resource not found; 409 State or idempotency conflict; 422 Request body failed schema validation; 429 Rate limit or durable quota exceeded; 500 Internal failure; 502 Venue or provider failure; 503 Required dependency unavailable; 504 Request timeout. ### GET /v1/agents List this account's agents by status and mode, including recovery steps for paused or errored agents, without strategy source or encrypted state. Authorization: API key with `read` scope. Query parameters: - `status` (string, nullable, optional) [at most 20 characters] - `mode` (string, nullable, optional) [at most 10 characters] - `before` (string, nullable, optional) [at most 64 characters] - `limit` (integer, optional) [minimum 1; maximum 100; default 20] Error statuses: 400 Invalid request; 401 Missing or invalid API key; 403 Scope, policy, or live-trading restriction; 404 Owned resource not found; 409 State or idempotency conflict; 422 Request body failed schema validation; 429 Rate limit or durable quota exceeded; 500 Internal failure; 502 Venue or provider failure; 503 Required dependency unavailable; 504 Request timeout. ### GET /v1/agents/{agent_id} Return one agent's status, run count, PnL, leverage, and last decision. Authorization: API key with `read` scope. Path parameters: - `agent_id` (string, required) Error statuses: 400 Invalid request; 401 Missing or invalid API key; 403 Scope, policy, or live-trading restriction; 404 Owned resource not found; 409 State or idempotency conflict; 422 Request body failed schema validation; 429 Rate limit or durable quota exceeded; 500 Internal failure; 502 Venue or provider failure; 503 Required dependency unavailable; 504 Request timeout. ### PATCH /v1/agents/{agent_id} Update a stopped or paused agent's name, cadence, risk limits, or exit rules in place, keeping its id and history, and optionally resume it. Authorization: API key with `trade` scope. Rate-limit bucket: `safety`. `Idempotency-Key` header: required. Path parameters: - `agent_id` (string, required) Request body (JSON, required): - `name` (string, optional): Updated agent name. [at least 1 character; at most 80 characters] - `strategy` (object, optional): Replacement compiled strategy containing config.code. The agent must be stopped and have no open positions. Strategy replacement cannot be combined with resume. - `cycle_seconds` (integer, optional): Updated scheduled timer or market-mode idle scheduled fallback, separate from the market-event minimum interval. Market evaluations postpone the fallback; continuous activity can defer it indefinitely. It does not run independently. Venue-specific minimums still apply. No order-to-fill latency guarantee. [minimum 5; maximum 86400] - `evaluation_trigger` (string, optional): Updated trigger: scheduled timer or market-update driven evaluation. Market-triggered evaluation must be supported and enabled on this deployment first; use scheduled evaluation or contact support when unavailable. Omission preserves the existing trigger; legacy agents default to scheduled. [one of "scheduled", "market"] - `min_event_interval_ms` (integer, optional): Updated per-agent minimum milliseconds between market-event evaluations, separate from the cycle_seconds idle scheduled fallback and not an order-to-fill latency guarantee. Updates may be coalesced; unused in scheduled mode. Integer only, without coercion; omission preserves the existing value (legacy default 1000). [minimum 250; maximum 60000] - `budget_usd` (number, optional): Updated agent capital ceiling; bounded by live-key caps and any approved portfolio envelope. [greater than 0; maximum 1000000000] - `max_position_usd` (number, optional): Updated per-position ceiling; bounded by budget and key caps. [greater than 0] - `max_daily_loss_usd` (number, optional): Updated daily realized-loss ceiling; bounded by budget and key caps. [greater than 0] - `stop_loss_pct` (number, optional): Loss fraction from entry, e.g. 0.05 for 5%. [minimum 0.001; maximum 0.99] - `take_profit_pct` (number, optional): Profit fraction from entry, e.g. 0.10 for 10%. [minimum 0.001; maximum 10] - `trailing_stop_pct` (number, optional): Trailing distance as a decimal fraction. [minimum 0.001; maximum 0.99] - `trailing_activation_pct` (number, optional): Profit fraction required before trailing protection arms. [minimum 0; maximum 10] - `break_even_after_pct` (number, optional): Profit fraction that activates a break-even exit. [minimum 0.001; maximum 10] - `max_holding_minutes` (number, optional): Maximum position age in minutes. [minimum 1; maximum 525600] - `clear_exit_plan` (boolean, optional): Remove every server-monitored exit rule from this agent. [default false] - `resume` (boolean, optional): Restart the same agent after the policy update. [default false] - `replay_attestation` (string, optional): Signed proof that the replacement strategy code was replayed, from replay_attestation.token on a POST /v1/backtests result. Required when revising a live agent's strategy unless acknowledge_unvalidated is true. The proof binds to sha256 of the replacement code, so the previous revision's proof is not accepted. [at least 32 characters; at most 4096 characters] - `acknowledge_unvalidated` (boolean, optional): Explicitly revise a live agent's strategy without verified replay evidence, or with a replay whose historical validity is degraded. The waiver is recorded on the agent and returned in strategy_evidence. Both fields require strategy and are rejected for paper agents. [default false] Error statuses: 400 Invalid request; 401 Missing or invalid API key; 403 Scope, policy, or live-trading restriction; 404 Owned resource not found; 409 State or idempotency conflict; 422 Request body failed schema validation; 429 Rate limit or durable quota exceeded; 500 Internal failure; 502 Venue or provider failure; 503 Required dependency unavailable; 504 Request timeout. ### POST /v1/agents/{agent_id}/stop Stop a running agent. Its positions stay open. Authorization: API key with `trade` scope. Rate-limit bucket: `safety`. Path parameters: - `agent_id` (string, required) Error statuses: 400 Invalid request; 401 Missing or invalid API key; 403 Scope, policy, or live-trading restriction; 404 Owned resource not found; 409 State or idempotency conflict; 422 Request body failed schema validation; 429 Rate limit or durable quota exceeded; 500 Internal failure; 502 Venue or provider failure; 503 Required dependency unavailable; 504 Request timeout. Stopping an agent never sells its positions. Prediction-market positions are still settled automatically when their market resolves, including for stopped and paused agents, and an agent holding both outcomes of one market has matching pairs merged back into cash. ## Observe ### GET /v1/agents/{agent_id}/decisions Read an agent's decision log: each decision, its outcome, any block or error reason, the market snapshot, and latency. Authorization: API key with `read` scope. Path parameters: - `agent_id` (string, required) Query parameters: - `before` (string, nullable, optional) [at most 64 characters] - `limit` (integer, optional) [minimum 1; maximum 100; default 50] Error statuses: 400 Invalid request; 401 Missing or invalid API key; 403 Scope, policy, or live-trading restriction; 404 Owned resource not found; 409 State or idempotency conflict; 422 Request body failed schema validation; 429 Rate limit or durable quota exceeded; 500 Internal failure; 502 Venue or provider failure; 503 Required dependency unavailable; 504 Request timeout. ### GET /v1/situation Return one bounded account snapshot: agents, positions, marked PnL, money, active risk blocks, recent decisions, and pending operations, with every source marked available or unavailable. Authorization: API key with `read` scope. Query parameters: - `agent_limit` (integer, optional) [minimum 1; maximum 100; default 25] - `decision_limit` (integer, optional) [minimum 1; maximum 100; default 20] Error statuses: 400 Invalid request; 401 Missing or invalid API key; 403 Scope, policy, or live-trading restriction; 404 Owned resource not found; 409 State or idempotency conflict; 422 Request body failed schema validation; 429 Rate limit or durable quota exceeded; 500 Internal failure; 502 Venue or provider failure; 503 Required dependency unavailable; 504 Request timeout. ### GET /v1/events/wait Long-poll the account for agent decisions, agent errors, and position opens and closes from a cursor, returning after the next event or the timeout. Authorization: API key with `read` scope. Rate-limit bucket: `market`. Query parameters: - `after` (string, nullable, optional) [at most 64 characters] - `types` (string, nullable, optional) [at most 200 characters] - `wait_seconds` (integer, optional) [minimum 0; maximum 25; default 20] - `limit` (integer, optional) [minimum 1; maximum 100; default 25] Error statuses: 400 Invalid request; 401 Missing or invalid API key; 403 Scope, policy, or live-trading restriction; 404 Owned resource not found; 409 State or idempotency conflict; 422 Request body failed schema validation; 429 Rate limit or durable quota exceeded; 500 Internal failure; 502 Venue or provider failure; 503 Required dependency unavailable; 504 Request timeout. Event types are `agent.decision`, `agent.error`, `position.opened`, and `position.closed`. Pass the previous response's `next_after` as `after`. An empty timeout is a successful wait, not an error. --- # API reference: Mandates Source: https://felix.trade/docs/api/mandates > Bind one live key to owner-signed venues, instruments, size, concentration, slippage, leverage, and expiry for unattended trading. A mandate narrows what one live key may do autonomously. The client validates and signs the exact prepared policy locally; Felix activates the next policy version atomically and enforces it before producing any venue signature. `GET /v1/mandates/current` returns verified public metadata only, never the signature or the sealed token. ### POST /v1/mandates/prepare Prepare an exact owner-signable autonomous-trading policy for one live key and return its sealed policy token. Authorization: API key with `manage` scope. Rate-limit bucket: `transfer`. Request body (JSON, required): - `account_id` (string, optional): Target isolated account UUID. Omit to use the key's own account. [matches ^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$] - `api_key_id` (string, required): Live key UUID bound to this mandate. [matches ^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$] - `venues` (array of string, optional): Owner-authorized venues. [at least 1 item; at most 4 items] - `instruments` (array of string, optional): Authorized instruments. A lone * authorizes all instruments. [at least 1 item; at most 64 items] - `max_position_usd` (number, optional): Maximum resulting notional in one position. [greater than 0] - `max_concentration_bps` (integer, optional): Maximum position concentration in basis points. [minimum 1; maximum 10000; default 10000] - `max_slippage_bps` (integer, optional): Maximum execution slippage in basis points. [minimum 1; maximum 10000; default 200] - `max_leverage` (integer, optional): Maximum venue leverage. [minimum 1; maximum 100; default 20] - `mandate_days` (integer, optional): Autonomous authorization lifetime in days. [minimum 1; maximum 90; default 30] - `allow_reduce_only_after_expiry` (boolean, optional): Permit risk-reducing exits after mandate expiry. [default true] Error statuses: 400 Invalid request; 401 Missing or invalid API key; 403 Scope, policy, or live-trading restriction; 404 Owned resource not found; 409 State or idempotency conflict; 422 Request body failed schema validation; 429 Rate limit or durable quota exceeded; 500 Internal failure; 502 Venue or provider failure; 503 Required dependency unavailable; 504 Request timeout. ### POST /v1/mandates/submit Verify the owner signature over the policy token and atomically activate the next policy version for that key. Authorization: API key with `manage` scope. Rate-limit bucket: `transfer`. Request body (JSON, required): - `account_id` (string, optional): Target isolated account UUID. Omit to use the key's own account. [matches ^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$] - `api_key_id` (string, required): Live key UUID bound to this mandate. [matches ^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$] - `policy_token` (string, required): Opaque sealed mandate returned by prepare. [at least 1 character; at most 32000 characters] - `owner_signature` (string, required): Owner's canonical 65-byte personal-sign signature. [matches ^0x[0-9a-fA-F]{130}$] Error statuses: 400 Invalid request; 401 Missing or invalid API key; 403 Scope, policy, or live-trading restriction; 404 Owned resource not found; 409 State or idempotency conflict; 422 Request body failed schema validation; 429 Rate limit or durable quota exceeded; 500 Internal failure; 502 Venue or provider failure; 503 Required dependency unavailable; 504 Request timeout. ### GET /v1/mandates/current Return the verified public metadata of the current mandate for a key. Authorization: API key with `read` scope. Rate-limit bucket: `market`. Query parameters: - `account_id` (string, nullable, optional) - `api_key_id` (string, nullable, optional) Error statuses: 400 Invalid request; 401 Missing or invalid API key; 403 Scope, policy, or live-trading restriction; 404 Owned resource not found; 409 State or idempotency conflict; 422 Request body failed schema validation; 429 Rate limit or durable quota exceeded; 500 Internal failure; 502 Venue or provider failure; 503 Required dependency unavailable; 504 Request timeout. A mandate can only narrow authority. It cannot raise the key's caps or the account's wallet-policy ceilings. Account-wide limits across every key and agent are set separately in [Portfolio risk](https://felix.trade/docs/api/portfolio-risk). --- # API reference: Portfolio risk Source: https://felix.trade/docs/api/portfolio-risk > Set an account-wide risk mandate, read a combined-book risk snapshot, and preview position sizes, orders, and rebalances against it. The portfolio mandate is one shared policy applied across every key, agent, and venue on the account. It only adds restrictions: it cannot widen API-key caps, owner-signed ceilings, venue limits, or agent limits. Updates are atomic and use an optimistic-lock version. Previews here check portfolio limits only; call `POST /v1/orders/preview` separately for venue fees, minimums, collateral, and liquidity. ## Mandate ### GET /v1/portfolio/mandate Read the caller-owned portfolio risk mandate and its current version. Authorization: API key with `read` scope. Rate-limit bucket: `market`. Query parameters: - `account_id` (string, nullable, optional) Error statuses: 400 Invalid request; 401 Missing or invalid API key; 403 Scope, policy, or live-trading restriction; 404 Owned resource not found; 409 State or idempotency conflict; 422 Request body failed schema validation; 429 Rate limit or durable quota exceeded; 500 Internal failure; 502 Venue or provider failure; 503 Required dependency unavailable; 504 Request timeout. ### PUT /v1/portfolio/mandate Atomically replace the portfolio mandate with a profile, mode, limits, and allocation targets, given the expected current version. Authorization: API key with `manage` scope. Rate-limit bucket: `transfer`. `Idempotency-Key` header: required. Request body (JSON, required): - `account_id` (string, optional): Target isolated account UUID. Omit to use the key's own account. [matches ^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$] - `expected_version` (integer, required): Current version returned by GET /v1/portfolio/mandate. [minimum 0] - `profile` (string, required): Guided preset or custom advanced policy. [one of "preservation", "balanced", "growth", "custom"] - `mode` (string, required): Retail presentation mode; both modes use the same enforcement contract. [one of "guided", "advanced"] - `enforcement_mode` (string, optional): Whether this owner-saved mandate monitors or blocks new live opens. Omission preserves the current setting; a new mandate defaults to monitor. [one of "monitor", "enforce"] - `limits` (object, required) - `risk_per_trade_pct` (number, required): Position-sizing budget as account-value percent at the caller's stated invalidation distance. It is not a guaranteed loss cap unless the strategy separately enforces an exit. [minimum 0.05; maximum 10] - `max_position_pct` (number, required): Maximum single-position notional as account-value percent. [minimum 1; maximum 100] - `max_gross_exposure_pct` (number, required): Maximum combined live notional as account-value percent. [minimum 10; maximum 500] - `max_asset_concentration_pct` (number, required): Maximum absolute owned linear net notional to one asset. Verified option delta is reported separately and does not silently replace this limit basis. [minimum 5; maximum 100] - `max_daily_loss_pct` (number, required): Desk-wide UTC daily-loss circuit breaker. [minimum 0.25; maximum 50] - `min_cash_reserve_pct` (number, required): Minimum verified free cash kept outside live positions. [minimum 0; maximum 95] - `target_portfolio_vol_pct` (number, required): Annualized volatility target used by volatility sizing. [minimum 1; maximum 100] - `hedge_at_net_exposure_pct` (number, required): Verified USD delta above which a preview-only hedge candidate is proposed. Candidates are withheld when the delta model is incomplete. [minimum 1; maximum 100] - `rebalance_drift_pct` (number, required): Minimum account-value allocation drift before a move is proposed. [minimum 0.5; maximum 50] - `allocation_targets` (object, required): Targets must add to 100 percent. - `cash` (number, required): Target account allocation to cash. [minimum 0; maximum 100] - `hyperliquid` (number, required): Target account allocation to hyperliquid. [minimum 0; maximum 100] - `polymarket` (number, required): Target account allocation to polymarket. [minimum 0; maximum 100] - `derive` (number, required): Target account allocation to derive. [minimum 0; maximum 100] - `derive_greek_limits` (array of object, optional): Zero to sixteen owner-configured per-underlying Derive Greek limits. [at most 16 items] - `asset` (string, required): Canonical Derive underlying, such as BTC or ETH. [matches ^[A-Z][A-Z0-9]{0,15}$] - `max_abs_net_gamma` (number, optional): Maximum absolute net gamma in Derive venue-native position-Greek units. [minimum 0; maximum 1000000000000] - `max_gross_gamma` (number, optional): Maximum gross gamma in Derive venue-native position-Greek units. [minimum 0; maximum 1000000000000] - `max_abs_net_theta` (number, optional): Maximum absolute net theta in Derive venue-native position-Greek units. [minimum 0; maximum 1000000000000] - `max_gross_theta` (number, optional): Maximum gross theta in Derive venue-native position-Greek units. [minimum 0; maximum 1000000000000] - `max_abs_net_vega` (number, optional): Maximum absolute net vega in Derive venue-native position-Greek units. [minimum 0; maximum 1000000000000] - `max_gross_vega` (number, optional): Maximum gross vega in Derive venue-native position-Greek units. [minimum 0; maximum 1000000000000] Error statuses: 400 Invalid request; 401 Missing or invalid API key; 403 Scope, policy, or live-trading restriction; 404 Owned resource not found; 409 State or idempotency conflict; 422 Request body failed schema validation; 429 Rate limit or durable quota exceeded; 500 Internal failure; 502 Venue or provider failure; 503 Required dependency unavailable; 504 Request timeout. ## Risk ### GET /v1/portfolio/risk Return one fail-closed combined-book snapshot: verified capital, daily loss, gross exposure, linear net exposure, concentration, hedge candidates, and venue allocations. Authorization: API key with `read` scope. Rate-limit bucket: `market`. Query parameters: - `account_id` (string, nullable, optional) Error statuses: 400 Invalid request; 401 Missing or invalid API key; 403 Scope, policy, or live-trading restriction; 404 Owned resource not found; 409 State or idempotency conflict; 422 Request body failed schema validation; 429 Rate limit or durable quota exceeded; 500 Internal failure; 502 Venue or provider failure; 503 Required dependency unavailable; 504 Request timeout. ## Previews ### POST /v1/portfolio/position-size Calculate a portfolio-constrained position size from the applied mandate and an invalidation distance. No order is placed. Authorization: API key with `read` scope. Rate-limit bucket: `market`. Request body (JSON, required): - `account_id` (string, optional): Target isolated account UUID. Omit to use the key's own account. [matches ^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$] - `method` (string, required): Sizing method. [one of "fixed_risk", "volatility_target"; default "fixed_risk"] - `invalidation_distance_pct` (number, required): Adverse move at which the trade thesis is invalidated. [greater than 0; maximum 100] - `instrument_volatility_pct` (number, optional): Annualized instrument volatility; required for volatility_target. [greater than 0; maximum 1000] Error statuses: 400 Invalid request; 401 Missing or invalid API key; 403 Scope, policy, or live-trading restriction; 404 Owned resource not found; 409 State or idempotency conflict; 422 Request body failed schema validation; 429 Rate limit or durable quota exceeded; 500 Internal failure; 502 Venue or provider failure; 503 Required dependency unavailable; 504 Request timeout. ### POST /v1/portfolio/preview-order Check one order against combined position, gross, concentration, daily-loss, reserve, and leverage limits. No order is placed. Authorization: API key with `read` scope. Rate-limit bucket: `market`. Request body (JSON, required): - `account_id` (string, optional): Target isolated account UUID. Omit to use the key's own account. [matches ^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$] - `venue` (string, required): Execution venue. [one of "hyperliquid", "hyperliquid_spot", "polymarket", "derive"] - `instrument` (string, required): Canonical symbol or Felix instrument, for example BTC, NVDA, option:BTC-..., or pm:. [at least 1 character; at most 180 characters] - `side` (string, required): Order direction or outcome. [one of "buy", "sell", "long", "short", "yes", "no"] - `size_usd` (number, required): USD notional. [greater than 0] - `allow_leverage` (boolean, optional): Explicit Hyperliquid leverage opt-in. [default false] Error statuses: 400 Invalid request; 401 Missing or invalid API key; 403 Scope, policy, or live-trading restriction; 404 Owned resource not found; 409 State or idempotency conflict; 422 Request body failed schema validation; 429 Rate limit or durable quota exceeded; 500 Internal failure; 502 Venue or provider failure; 503 Required dependency unavailable; 504 Request timeout. ### POST /v1/portfolio/rebalance-preview Preview committed-capital allocation targets under the applied mandate. Deltas are not order notionals or transfer amounts, and cash is a reserve, not a destination venue. Authorization: API key with `read` scope. Rate-limit bucket: `market`. Request body (JSON): - `account_id` (string, optional): Target isolated account UUID. Omit to use the key's own account. [matches ^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$] Error statuses: 400 Invalid request; 401 Missing or invalid API key; 403 Scope, policy, or live-trading restriction; 404 Owned resource not found; 409 State or idempotency conflict; 422 Request body failed schema validation; 429 Rate limit or durable quota exceeded; 500 Internal failure; 502 Venue or provider failure; 503 Required dependency unavailable; 504 Request timeout. ## Hedges and trims ### POST /v1/portfolio/hedge-preview Find hedge candidates that reduce one asset's verified exposure and return an execution review hash for the exact preview. Places nothing. Authorization: API key with `read` scope. Rate-limit bucket: `market`. Request body (JSON, required): - `account_id` (string, optional): Target isolated account UUID. Omit to use the key's own account. [matches ^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$] - `asset` (string, required): Canonical asset symbol from the verified portfolio delta view. [matches ^(?:(?:XYZ|VNTL):)?[A-Z0-9][A-Z0-9._-]{0,31}$] - `allow_leverage` (boolean, optional): Explicit Hyperliquid leverage opt-in. [default false] Error statuses: 400 Invalid request; 401 Missing or invalid API key; 403 Scope, policy, or live-trading restriction; 404 Owned resource not found; 409 State or idempotency conflict; 422 Request body failed schema validation; 429 Rate limit or durable quota exceeded; 500 Internal failure; 502 Venue or provider failure; 503 Required dependency unavailable; 504 Request timeout. ### POST /v1/portfolio/hedge/execute Place the reviewed hedge. Requires the expected_review_hash from the exact preview and an Idempotency-Key. Authorization: API key with `trade` scope. Rate-limit bucket: `order`. `Idempotency-Key` header: required. Request body (JSON, required): - `account_id` (string, optional): Target isolated account UUID. Omit to use the key's own account. [matches ^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$] - `asset` (string, required): Canonical asset symbol from the verified portfolio delta view. [matches ^(?:(?:XYZ|VNTL):)?[A-Z0-9][A-Z0-9._-]{0,31}$] - `allow_leverage` (boolean, optional): Explicit Hyperliquid leverage opt-in matching the reviewed preview. [default false] - `expected_review_hash` (string, required): sha256 hash returned in execution_review.hash by the exact /v1/portfolio/hedge-preview response. [matches ^sha256:[0-9a-f]{64}$] - `candidate` (object, required) - `venue` (string, required): Must be hyperliquid. [one of "hyperliquid"] - `instrument` (string, required): Candidate instrument returned by hedge-preview. [at least 1 character; at most 80 characters] - `side` (string, required): Delta-reducing Hyperliquid side. [one of "long", "short"] - `size_usd` (number, required): USD notional. [greater than 0] - `delta_reducing` (boolean, optional): Must be true in the reviewed hedge candidate. [default true] Error statuses: 400 Invalid request; 401 Missing or invalid API key; 403 Scope, policy, or live-trading restriction; 404 Owned resource not found; 409 State or idempotency conflict; 422 Request body failed schema validation; 429 Rate limit or durable quota exceeded; 500 Internal failure; 502 Venue or provider failure; 503 Required dependency unavailable; 504 Request timeout. ### POST /v1/portfolio/covariance-trim-preview Preview one trim of an existing Hyperliquid exposure using return covariance. It can only reduce that exposure and never submits. Authorization: API key with `read` scope. Rate-limit bucket: `market`. Request body (JSON, required): - `account_id` (string, optional): Target isolated account UUID. Omit to use the key's own account. [matches ^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$] - `asset` (string, required): Canonical asset with an existing verified linear USD delta to reduce. [matches ^(?:(?:XYZ|VNTL):)?[A-Z0-9][A-Z0-9._-]{0,31}$] - `max_size_usd` (number, required): USD notional. [greater than 0] - `target_portfolio_volatility_pct` (number, optional): Optional annualized portfolio-volatility target. It may tighten, but never loosen, the owner mandate. [minimum 0; maximum 100] - `observations` (array of object, required): The same 20-500 aligned daily-return observations used for historical risk. [at least 20 items; at most 500 items] - `date` (string, required): Unique UTC observation date. [matches ^\d{4}-\d{2}-\d{2}$] - `asset_returns_pct` (object, required): Exact one-day close-to-close returns for every verified linear delta asset. Error statuses: 400 Invalid request; 401 Missing or invalid API key; 403 Scope, policy, or live-trading restriction; 404 Owned resource not found; 409 State or idempotency conflict; 422 Request body failed schema validation; 429 Rate limit or durable quota exceeded; 500 Internal failure; 502 Venue or provider failure; 503 Required dependency unavailable; 504 Request timeout. ### POST /v1/portfolio/derive-greek-hedge-preview Rank up to four exact Derive option previews that reduce one net Greek. Places nothing. Authorization: API key with `read` scope. Rate-limit bucket: `market`. Request body (JSON, required): - `account_id` (string, optional): Target isolated account UUID. Omit to use the key's own account. [matches ^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$] - `asset` (string, required): Canonical Derive underlying from the verified sensitivity view. [matches ^[A-Z][A-Z0-9]{0,15}$] - `metric` (string, required): One net higher-order sensitivity to reduce. [one of "gamma", "theta", "vega"] - `max_size_usd` (number, required): USD notional. [greater than 0] - `target_abs_net` (number, optional): Optional absolute-net target in Derive venue-native position-Greek units. Omit to use the matching owner-mandate net limit. [minimum 0; maximum 1000000000000] - `max_candidates` (integer, optional): Maximum exact Derive quote previews after bounded chain preselection. [minimum 1; maximum 4; default 4] Error statuses: 400 Invalid request; 401 Missing or invalid API key; 403 Scope, policy, or live-trading restriction; 404 Owned resource not found; 409 State or idempotency conflict; 422 Request body failed schema validation; 429 Rate limit or durable quota exceeded; 500 Internal failure; 502 Venue or provider failure; 503 Required dependency unavailable; 504 Request timeout. ### POST /v1/portfolio/execution-route-preview Select a fully verified immediate route for an order without moving money. Authorization: API key with `read` scope. Rate-limit bucket: `market`. Request body (JSON, required): - `account_id` (string, optional): Target isolated account UUID. Omit to use the key's own account. [matches ^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$] - `objective` (string, required): Economic objective. Directional compares supported linear expressions; own requires spot ownership; event and option preserve the exact contract. [one of "directional", "own", "event", "option"] - `instrument` (string, required): Canonical symbol or Felix instrument, for example BTC, NVDA, option:BTC-..., or pm:. [at least 1 character; at most 180 characters] - `side` (string, required): Order direction or outcome. [one of "buy", "sell", "long", "short", "yes", "no"] - `size_usd` (number, required): USD notional. [greater than 0] - `allow_leverage` (boolean, optional): Permit a leveraged perpetual candidate only after explicit review. [default false] Error statuses: 400 Invalid request; 401 Missing or invalid API key; 403 Scope, policy, or live-trading restriction; 404 Owned resource not found; 409 State or idempotency conflict; 422 Request body failed schema validation; 429 Rate limit or durable quota exceeded; 500 Internal failure; 502 Venue or provider failure; 503 Required dependency unavailable; 504 Request timeout. ## Stress and historical risk These previews never trade. Unknown costs stay unknown, and incomplete books are refused instead of approximated. ### POST /v1/portfolio/stress-preview Apply one to eight scenarios to the verified book and report first-order profit and loss. This is not a forecast or a value-at-risk figure. Authorization: API key with `read` scope. Rate-limit bucket: `market`. Request body (JSON, required): - `account_id` (string, optional): Target isolated account UUID. Omit to use the key's own account. [matches ^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$] - `scenarios` (array of object, required): One to eight bounded deterministic portfolio scenarios. [at least 1 item; at most 8 items] - `name` (string, required): Unique scenario label. [at least 1 character; at most 48 characters] - `asset_shocks_pct` (object, required): Canonical asset symbols mapped to deterministic price shocks in percent. Omitted assets are explicitly unchanged. - `nonlinear_pnl_adjustments_usd` (object, optional): Owned nonlinear position IDs mapped to explicit additive scenario P&L in USD. Every nonlinear position requires an adjustment before the scenario is decision-usable. Error statuses: 400 Invalid request; 401 Missing or invalid API key; 403 Scope, policy, or live-trading restriction; 404 Owned resource not found; 409 State or idempotency conflict; 422 Request body failed schema validation; 429 Rate limit or durable quota exceeded; 500 Internal failure; 502 Venue or provider failure; 503 Required dependency unavailable; 504 Request timeout. ### POST /v1/portfolio/historical-risk-preview Compute historical-simulation value at risk and expected shortfall from 20 to 500 daily returns you supply. Authorization: API key with `read` scope. Rate-limit bucket: `market`. Request body (JSON, required): - `account_id` (string, optional): Target isolated account UUID. Omit to use the key's own account. [matches ^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$] - `confidence_pct` (integer, required): Historical tail confidence. [one of 95, 99; default 95] - `observations` (array of object, required): Twenty to 500 bounded daily return observations. [at least 20 items; at most 500 items] - `date` (string, required): Unique UTC observation date. [matches ^\d{4}-\d{2}-\d{2}$] - `asset_returns_pct` (object, required): Exact one-day close-to-close returns for every verified linear delta asset. Error statuses: 400 Invalid request; 401 Missing or invalid API key; 403 Scope, policy, or live-trading restriction; 404 Owned resource not found; 409 State or idempotency conflict; 422 Request body failed schema validation; 429 Rate limit or durable quota exceeded; 500 Internal failure; 502 Venue or provider failure; 503 Required dependency unavailable; 504 Request timeout. ## Agent fleet ### POST /v1/portfolio/fleet-capacity-preview Show how much verified cash and headroom each agent can use under its remaining budget. Read-only. Authorization: API key with `read` scope. Rate-limit bucket: `market`. Request body (JSON): - `account_id` (string, optional): Target isolated account UUID. Omit to use the key's own account. [matches ^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$] - `agent_weights` (array of object, optional): Optional exact split across every active owned agent; weights must total 10000 basis points. [at least 1 item; at most 100 items] - `agent_id` (string, required): Active owned agent UUID. [matches ^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$] - `weight_bps` (integer, required): Requested share of deployable headroom in basis points. [minimum 0; maximum 10000] Error statuses: 400 Invalid request; 401 Missing or invalid API key; 403 Scope, policy, or live-trading restriction; 404 Owned resource not found; 409 State or idempotency conflict; 422 Request body failed schema validation; 429 Rate limit or durable quota exceeded; 500 Internal failure; 502 Venue or provider failure; 503 Required dependency unavailable; 504 Request timeout. ### POST /v1/portfolio/fleet-reallocation-preview Preview new budget ceilings across your agents. Read-only. Authorization: API key with `read` scope. Rate-limit bucket: `market`. Request body (JSON, required): - `account_id` (string, optional): Target isolated account UUID. Omit to use the key's own account. [matches ^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$] - `target_deployed_capital_usd` (number, required): Explicit total live capital target across the active agent fleet. [minimum 0; maximum 1000000000] - `agent_weights` (array of object, required): Exact owner-selected split across every active owned agent; weights must total 10000 basis points. [at least 1 item; at most 100 items] - `agent_id` (string, required): Active owned agent UUID. [matches ^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$] - `weight_bps` (integer, required): Exact target share in basis points. [minimum 0; maximum 10000] Error statuses: 400 Invalid request; 401 Missing or invalid API key; 403 Scope, policy, or live-trading restriction; 404 Owned resource not found; 409 State or idempotency conflict; 422 Request body failed schema validation; 429 Rate limit or durable quota exceeded; 500 Internal failure; 502 Venue or provider failure; 503 Required dependency unavailable; 504 Request timeout. ### POST /v1/portfolio/fleet-reallocation/apply Apply verified agent budget ceilings in one atomic update. Moves no money. Authorization: API key with `trade` scope. Rate-limit bucket: `safety`. `Idempotency-Key` header: required. Request body (JSON, required): - `account_id` (string, optional): Target isolated account UUID. Omit to use the key's own account. [matches ^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$] - `expected_policy_version` (integer, required): Portfolio mandate version returned by the reviewed fleet preview. [minimum 1; maximum 2147483647] - `target_deployed_capital_usd` (number, required): Exact reviewed total live capital target across the active fleet. [minimum 0; maximum 1000000000] - `agent_weights` (array of object, required): Exact split from a fresh fleet-reallocation preview; weights must total 10000 basis points. [at least 1 item; at most 100 items] - `agent_id` (string, required): Active owned agent UUID. [matches ^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$] - `weight_bps` (integer, required): Exact reviewed target share in basis points. [minimum 0; maximum 10000] Error statuses: 400 Invalid request; 401 Missing or invalid API key; 403 Scope, policy, or live-trading restriction; 404 Owned resource not found; 409 State or idempotency conflict; 422 Request body failed schema validation; 429 Rate limit or durable quota exceeded; 500 Internal failure; 502 Venue or provider failure; 503 Required dependency unavailable; 504 Request timeout. ### GET /v1/portfolio/execution-quality Return recent agent decisions, outcomes, and runtime latency for the account's agents. Authorization: API key with `read` scope. Rate-limit bucket: `market`. Query parameters: - `account_id` (string, nullable, optional) - `limit` (integer, optional) [minimum 1; maximum 500; default 250] Error statuses: 400 Invalid request; 401 Missing or invalid API key; 403 Scope, policy, or live-trading restriction; 404 Owned resource not found; 409 State or idempotency conflict; 422 Request body failed schema validation; 429 Rate limit or durable quota exceeded; 500 Internal failure; 502 Venue or provider failure; 503 Required dependency unavailable; 504 Request timeout. --- # API reference: Routing Source: https://felix.trade/docs/api/routing > Cross-venue request-for-quote routing and the fast funding routes, which are discoverable now and execute only when capabilities report readiness. Routing moves funds between venues without a round trip through the owner wallet. The request-for-quote pairs and the fast routes are published so integrations can be built against a stable contract; they execute only when `GET /v1/router/rfqs/capabilities` reports `cross_venue_execution_ready: true`. Until then, use [Venue funding and returns](https://felix.trade/docs/api/venue-funding) or [Agent capital](https://felix.trade/docs/api/agent-capital). ## Request for quote ### GET /v1/router/rfqs/capabilities Return the routable source and destination pairs and whether cross-venue execution is ready. Authorization: API key with `read` scope. Rate-limit bucket: `read`. Error statuses: 400 Invalid request; 401 Missing or invalid API key; 403 Scope, policy, or live-trading restriction; 404 Owned resource not found; 409 State or idempotency conflict; 429 Rate limit or durable quota exceeded; 500 Internal failure; 502 Venue or provider failure; 503 Required dependency unavailable; 504 Request timeout. ### POST /v1/router/rfqs Open a request for quote to move an amount from one venue to another with an optional minimum receive amount. Authorization: API key with `transfer` scope. Rate-limit bucket: `transfer`. `Idempotency-Key` header: required. Request body (JSON, required): - `account_id` (string, optional): Target isolated account UUID. Omit to use the key's own account. [matches ^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$] - `market` (string, optional): Destination for owner-wallet funding. Do not combine with source_market or destination_market. [one of "crypto", "prediction_market", "options"] - `source_market` (string, optional): Source venue for a venue-to-venue transfer. [one of "crypto", "prediction_market", "options"] - `destination_market` (string, optional): Destination venue for a venue-to-venue transfer. Must differ from source_market. [one of "crypto", "prediction_market", "options"] - `amount_usd` (number, required): Exact source amount, with at most six decimals. [greater than 0] - `minimum_receive_usd` (number, optional): Optional minimum destination amount. Omit to use corridor spread policy. [greater than 0] Error statuses: 400 Invalid request; 401 Missing or invalid API key; 403 Scope, policy, or live-trading restriction; 404 Owned resource not found; 409 State or idempotency conflict; 422 Request body failed schema validation; 429 Rate limit or durable quota exceeded; 500 Internal failure; 502 Venue or provider failure; 503 Required dependency unavailable; 504 Request timeout. ### GET /v1/router/rfqs/{rfq_id} Read one caller-owned request for quote and its version. Authorization: API key with `read` scope. Rate-limit bucket: `read`. Path parameters: - `rfq_id` (string, required) Query parameters: - `account_id` (string, nullable, optional) Error statuses: 400 Invalid request; 401 Missing or invalid API key; 403 Scope, policy, or live-trading restriction; 404 Owned resource not found; 409 State or idempotency conflict; 422 Request body failed schema validation; 429 Rate limit or durable quota exceeded; 500 Internal failure; 502 Venue or provider failure; 503 Required dependency unavailable; 504 Request timeout. ### POST /v1/router/rfqs/{rfq_id}/cancel Cancel a request for quote at its expected version. Authorization: API key with `transfer` scope. Rate-limit bucket: `transfer`. `Idempotency-Key` header: required. Path parameters: - `rfq_id` (string, required) Request body (JSON): - `account_id` (string, optional): Target isolated account UUID. Omit to use the key's own account. [matches ^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$] - `expected_version` (integer, required): Latest RFQ version returned by its status endpoint. [minimum 1] Error statuses: 400 Invalid request; 401 Missing or invalid API key; 403 Scope, policy, or live-trading restriction; 404 Owned resource not found; 409 State or idempotency conflict; 422 Request body failed schema validation; 429 Rate limit or durable quota exceeded; 500 Internal failure; 502 Venue or provider failure; 503 Required dependency unavailable; 504 Request timeout. ## Fast funding routes Each fast route reserves destination inventory, returns an owner-signed source transaction, verifies and binds the exact signed transaction, and relays it. The operation id from `prepare` is the identity for `submit` and status. ### POST /v1/wallet/funding/hyperliquid-fast/prepare Reserve destination inventory for a fast perpetuals funding and return the source transaction for the owner to sign. Authorization: API key with `transfer` scope. Rate-limit bucket: `transfer`. `Idempotency-Key` header: required. Request body (JSON, required): - `amount_usd` (number, required): USD notional. [greater than 0] Error statuses: 400 Invalid request; 401 Missing or invalid API key; 403 Scope, policy, or live-trading restriction; 404 Owned resource not found; 409 State or idempotency conflict; 422 Request body failed schema validation; 429 Rate limit or durable quota exceeded; 500 Internal failure; 502 Venue or provider failure; 503 Required dependency unavailable; 504 Request timeout. ### POST /v1/wallet/funding/hyperliquid-fast/{operation_id}/submit Verify, bind, and relay the exact transaction the owner signed for this operation. Authorization: API key with `transfer` scope. Rate-limit bucket: `transfer`. `Idempotency-Key` header: required. Path parameters: - `operation_id` (string, required) Request body (JSON, required): - `raw_transaction` (string, required): Exact owner-signed source transaction returned by prepare. [at most 20000 characters; matches ^0x[0-9a-fA-F]+$] Error statuses: 400 Invalid request; 401 Missing or invalid API key; 403 Scope, policy, or live-trading restriction; 404 Owned resource not found; 409 State or idempotency conflict; 422 Request body failed schema validation; 429 Rate limit or durable quota exceeded; 500 Internal failure; 502 Venue or provider failure; 503 Required dependency unavailable; 504 Request timeout. ### GET /v1/wallet/funding/hyperliquid-fast/{operation_id} Read the status of one fast perpetuals funding operation. Authorization: API key with `read` scope. Rate-limit bucket: `read`. Path parameters: - `operation_id` (string, required) Error statuses: 400 Invalid request; 401 Missing or invalid API key; 403 Scope, policy, or live-trading restriction; 404 Owned resource not found; 409 State or idempotency conflict; 422 Request body failed schema validation; 429 Rate limit or durable quota exceeded; 500 Internal failure; 502 Venue or provider failure; 503 Required dependency unavailable; 504 Request timeout. ### POST /v1/wallet/funding/polymarket-fast/prepare Reserve destination inventory for a fast prediction-market funding and return the source transaction for the owner to sign. Authorization: API key with `transfer` scope. Rate-limit bucket: `transfer`. `Idempotency-Key` header: required. Request body (JSON, required): - `amount_usd` (number, required): USD notional. [greater than 0] Error statuses: 400 Invalid request; 401 Missing or invalid API key; 403 Scope, policy, or live-trading restriction; 404 Owned resource not found; 409 State or idempotency conflict; 422 Request body failed schema validation; 429 Rate limit or durable quota exceeded; 500 Internal failure; 502 Venue or provider failure; 503 Required dependency unavailable; 504 Request timeout. ### POST /v1/wallet/funding/polymarket-fast/{operation_id}/submit Verify, bind, and relay the exact transaction the owner signed for this operation. Authorization: API key with `transfer` scope. Rate-limit bucket: `transfer`. `Idempotency-Key` header: required. Path parameters: - `operation_id` (string, required) Request body (JSON, required): - `raw_transaction` (string, required): Exact owner-signed source transaction returned by prepare. [at most 20000 characters; matches ^0x[0-9a-fA-F]+$] Error statuses: 400 Invalid request; 401 Missing or invalid API key; 403 Scope, policy, or live-trading restriction; 404 Owned resource not found; 409 State or idempotency conflict; 422 Request body failed schema validation; 429 Rate limit or durable quota exceeded; 500 Internal failure; 502 Venue or provider failure; 503 Required dependency unavailable; 504 Request timeout. ### GET /v1/wallet/funding/polymarket-fast/{operation_id} Read the status of one fast prediction-market funding operation. Authorization: API key with `read` scope. Rate-limit bucket: `read`. Path parameters: - `operation_id` (string, required) Error statuses: 400 Invalid request; 401 Missing or invalid API key; 403 Scope, policy, or live-trading restriction; 404 Owned resource not found; 409 State or idempotency conflict; 422 Request body failed schema validation; 429 Rate limit or durable quota exceeded; 500 Internal failure; 502 Venue or provider failure; 503 Required dependency unavailable; 504 Request timeout. ### POST /v1/wallet/funding/derive-fast/prepare Reserve destination inventory for a fast options funding and return the source transaction for the owner to sign. Authorization: API key with `transfer` scope. Rate-limit bucket: `transfer`. `Idempotency-Key` header: required. Request body (JSON, required): - `amount_usd` (number, required): USD notional. [greater than 0] Error statuses: 400 Invalid request; 401 Missing or invalid API key; 403 Scope, policy, or live-trading restriction; 404 Owned resource not found; 409 State or idempotency conflict; 422 Request body failed schema validation; 429 Rate limit or durable quota exceeded; 500 Internal failure; 502 Venue or provider failure; 503 Required dependency unavailable; 504 Request timeout. ### POST /v1/wallet/funding/derive-fast/{operation_id}/submit Verify, bind, and relay the exact transaction the owner signed for this operation. Authorization: API key with `transfer` scope. Rate-limit bucket: `transfer`. `Idempotency-Key` header: required. Path parameters: - `operation_id` (string, required) Request body (JSON, required): - `raw_transaction` (string, required): Exact owner-signed source transaction returned by prepare. [at most 20000 characters; matches ^0x[0-9a-fA-F]+$] Error statuses: 400 Invalid request; 401 Missing or invalid API key; 403 Scope, policy, or live-trading restriction; 404 Owned resource not found; 409 State or idempotency conflict; 422 Request body failed schema validation; 429 Rate limit or durable quota exceeded; 500 Internal failure; 502 Venue or provider failure; 503 Required dependency unavailable; 504 Request timeout. ### GET /v1/wallet/funding/derive-fast/{operation_id} Read the status of one fast options funding operation. Authorization: API key with `read` scope. Rate-limit bucket: `read`. Path parameters: - `operation_id` (string, required) Error statuses: 400 Invalid request; 401 Missing or invalid API key; 403 Scope, policy, or live-trading restriction; 404 Owned resource not found; 409 State or idempotency conflict; 422 Request body failed schema validation; 429 Rate limit or durable quota exceeded; 500 Internal failure; 502 Venue or provider failure; 503 Required dependency unavailable; 504 Request timeout. --- # API reference: Streams Source: https://felix.trade/docs/api/streams > Mint the one-time ticket that authenticates a read-only market-data WebSocket session, and the session rules. The WebSocket at `wss://api.felix.trade/v1/stream` is read-only market data. It is authenticated with a short-lived ticket, never with an API key in the URL. ### POST /v1/stream/tickets Mint a one-use ticket that expires after 30 seconds and return the WebSocket URL and subprotocol to connect with. Authorization: API key with `read` scope. Rate-limit bucket: `stream`. Error statuses: 400 Invalid request; 401 Missing or invalid API key; 403 Scope, policy, or live-trading restriction; 404 Owned resource not found; 409 State or idempotency conflict; 429 Rate limit or durable quota exceeded; 500 Internal failure; 502 Venue or provider failure; 503 Required dependency unavailable; 504 Request timeout. ```json ticket response { "ticket": "...", "websocket_url": "wss://api.felix.trade/v1/stream", "protocol": "felix.market.v1", "expires_at": "..." } ``` ## Session rules - Send `{"op": "authenticate", "ticket": "..."}` as the first message within 5 seconds of connecting. - The key that minted the ticket is checked again for ownership, scope, and active state when the ticket is used. - A session lasts at most 30 minutes. Mint a new ticket and reconnect before it ends. - Channels are `quote`, `book`, and `trades`. - Polymarket, Hyperliquid, and Derive markets stream. Lighter markets do not. - Ticket minting counts against the `stream` rate-limit bucket: 10 per minute on Free, 30 on Pro, and 120 on Max. --- # API reference: Webhooks Source: https://felix.trade/docs/api/webhooks > Register, list, test, and delete signed HTTPS webhooks for fill, position, and agent events, and verify each delivery. Webhooks deliver five event types to a public HTTPS endpoint: `order.filled`, `position.opened`, `position.closed`, `agent.decision`, and `agent.error`. ### GET /v1/webhooks List active webhooks for the account without their signing secrets. Authorization: API key with `read` scope. Query parameters: - `account_id` (string, nullable, optional) Error statuses: 400 Invalid request; 401 Missing or invalid API key; 403 Scope, policy, or live-trading restriction; 404 Owned resource not found; 409 State or idempotency conflict; 422 Request body failed schema validation; 429 Rate limit or durable quota exceeded; 500 Internal failure; 502 Venue or provider failure; 503 Required dependency unavailable; 504 Request timeout. ### POST /v1/webhooks Register a public HTTPS endpoint for one to five event types and return the signing secret exactly once. Authorization: API key with `manage` scope. Rate-limit bucket: `manage`. `Idempotency-Key` header: required. Request body (JSON, required): - `account_id` (string, optional): Target isolated account UUID. Omit to use the key's own account. [matches ^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$] - `url` (string, required): Public HTTPS receiver; private, loopback, and metadata destinations are rejected. [matches ^https://] - `events` (array of string, required): Subscribed events. [at least 1 item; at most 5 items] Error statuses: 400 Invalid request; 401 Missing or invalid API key; 403 Scope, policy, or live-trading restriction; 404 Owned resource not found; 409 State or idempotency conflict; 422 Request body failed schema validation; 429 Rate limit or durable quota exceeded; 500 Internal failure; 502 Venue or provider failure; 503 Required dependency unavailable; 504 Request timeout. ```json registration response { "id": "...", "url": "https://you.dev/hook", "events": ["order.filled", "position.closed"], "signing_secret": "whsec_..." } ``` ### POST /v1/webhooks/test Send a sample order.filled event to every active receiver subscribed to it and report how many accepted it. Authorization: API key with `manage` scope. Rate-limit bucket: `expensive`. `Idempotency-Key` header: required. Request body (JSON): - `account_id` (string, optional): Target isolated account UUID. Omit to use the key's own account. [matches ^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$] Error statuses: 400 Invalid request; 401 Missing or invalid API key; 403 Scope, policy, or live-trading restriction; 404 Owned resource not found; 409 State or idempotency conflict; 422 Request body failed schema validation; 429 Rate limit or durable quota exceeded; 500 Internal failure; 502 Venue or provider failure; 503 Required dependency unavailable; 504 Request timeout. ### DELETE /v1/webhooks/{webhook_id} Delete one webhook. Authorization: API key with `manage` scope. Rate-limit bucket: `manage`. Path parameters: - `webhook_id` (string, required) Query parameters: - `account_id` (string, nullable, optional) Error statuses: 400 Invalid request; 401 Missing or invalid API key; 403 Scope, policy, or live-trading restriction; 404 Owned resource not found; 409 State or idempotency conflict; 422 Request body failed schema validation; 429 Rate limit or durable quota exceeded; 500 Internal failure; 502 Venue or provider failure; 503 Required dependency unavailable; 504 Request timeout. ## Each delivery Every delivery is a JSON `POST` with these headers: | Header | Value | | --- | --- | | `X-Felix-Signature` | Hex HMAC-SHA256 of the raw request body, keyed with your signing secret. | | `X-Felix-Event` | The event type. | | `X-Felix-Event-ID` | A unique id for this event. | | `X-Felix-Timestamp` | When the event was created. It is not part of the signature. | Verify the signature over the raw body before parsing it, and compare in constant time. Because the timestamp is not signed, deduplicate on `X-Felix-Event-ID` instead of trusting the time. ```python verify a delivery import hashlib, hmac def is_valid(raw_body: bytes, signature: str, secret: str) -> bool: expected = hmac.new(secret.encode(), raw_body, hashlib.sha256).hexdigest() return hmac.compare_digest(expected, signature) ``` ## Limits - The URL must be HTTPS and must resolve to a public IP address. Private, loopback, and cloud-metadata addresses are refused. - Webhooks per account: 1 on Free, 5 on Pro, and 25 on Max. --- # API reference: Plans and subscription Source: https://felix.trade/docs/api/plans > The Free, Pro, and Max plans, what each changes, how to read the calling account's plan, and how to pay for Pro through the API. Every venue is available on every plan. Plans change how many agents you can run, how much AI chat you get each day, API throughput, research depth, backtest capacity, and the trading-fee discount. They never change risk checks or withdrawal safety. | | Free | Pro | Max | | --- | --- | --- | --- | | Price | $0 | $20 per month | $99 per month | | Active agents | 3 | 10 | 50 | | AI chat per day | 300,000 tokens (600,000 after your first deposit) | 1,000,000 tokens | 3,000,000 tokens | | Agents that react to every market move | No | Yes | Yes | | API tier | `free` | `dev` | `scale` | | Trading-fee discount | None | 1 basis point | 2 basis points | Rate limits and daily quotas for each API tier are in [Rate limits](https://felix.trade/docs/api/rate-limits). Felix's trading fees are in [Fees](https://felix.trade/docs/overview/fees). Pro and Max are bought in the Felix app, from your balance. Auto-renew is optional there, can be turned off in Settings, and never charges more than the price you approved. More detail is in [Plans](https://felix.trade/docs/overview/plans). ### GET /v1/tiers Return the public API tiers with prices, per-minute rate-limit buckets, daily limits, and fee discounts. No key required. Authorization: No API key. Error statuses: 400 Invalid request; 401 Missing or invalid API key; 403 Scope, policy, or live-trading restriction; 404 Owned resource not found; 409 State or idempotency conflict; 429 Rate limit or durable quota exceeded; 500 Internal failure; 502 Venue or provider failure; 503 Required dependency unavailable; 504 Request timeout. ### GET /v1/me/subscription Return the calling account's effective tier, its limits, the billing plan, expiry, and the renewal contract. Authorization: API key with `read` scope. Error statuses: 400 Invalid request; 401 Missing or invalid API key; 403 Scope, policy, or live-trading restriction; 404 Owned resource not found; 409 State or idempotency conflict; 429 Rate limit or durable quota exceeded; 500 Internal failure; 502 Venue or provider failure; 503 Required dependency unavailable; 504 Request timeout. ## Pay for Pro through the API The API can buy one 30-day period of Pro for $20, paid as one exact owner-signed native USDC transfer on Polygon. It does not renew automatically. Both calls need the `manage` scope and a stable `Idempotency-Key`. Max is bought in the app. ### POST /v1/me/subscription/prepare Prepare one exact owner-signed Polygon USDC payment for 30 days of Pro and return the subscription token. Authorization: API key with `manage` scope. Rate-limit bucket: `manage`. `Idempotency-Key` header: required. Request body (JSON): - `account_id` (string, optional): Target isolated account UUID. Omit to use the key's own account. [matches ^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$] - `plan` (string, optional): Programmatic plan purchase. Pro is the only self-serve paid plan. [one of "pro"; default "pro"] - `gas_grant` (object, optional): Optional exact owner-signed gas sponsorship grant. Error statuses: 400 Invalid request; 401 Missing or invalid API key; 403 Scope, policy, or live-trading restriction; 404 Owned resource not found; 409 State or idempotency conflict; 422 Request body failed schema validation; 429 Rate limit or durable quota exceeded; 500 Internal failure; 502 Venue or provider failure; 503 Required dependency unavailable; 504 Request timeout. ### POST /v1/me/subscription/confirm Verify the exact on-chain payment and activate one Pro period. Retries reconcile the original transaction rather than paying twice. Authorization: API key with `manage` scope. Rate-limit bucket: `manage`. `Idempotency-Key` header: required. Request body (JSON, required): - `account_id` (string, optional): Target isolated account UUID. Omit to use the key's own account. [matches ^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$] - `subscription_token` (string, required): Opaque account- and key-bound subscription intent returned by prepare. [at least 1 character; at most 24000 characters] - `transaction_hash` (string, required): 0x-prefixed 32-byte transaction hash. [matches ^0x[0-9a-fA-F]{64}$] Error statuses: 400 Invalid request; 401 Missing or invalid API key; 403 Scope, policy, or live-trading restriction; 404 Owned resource not found; 409 State or idempotency conflict; 422 Request body failed schema validation; 429 Rate limit or durable quota exceeded; 500 Internal failure; 502 Venue or provider failure; 503 Required dependency unavailable; 504 Request timeout. ## Referrals ### POST /v1/referrals Create or return the calling account's referral code and revenue-share link. Authorization: API key with `manage` scope. Rate-limit bucket: `manage`. Request body (JSON): - `account_id` (string, optional): Target isolated account UUID. Omit to use the key's own account. [matches ^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$] - `label` (string, optional): Optional source label. [at most 60 characters] - `rev_share_bps` (integer, optional): Requested referral revenue share in basis points. [minimum 0; maximum 100] Error statuses: 400 Invalid request; 401 Missing or invalid API key; 403 Scope, policy, or live-trading restriction; 404 Owned resource not found; 409 State or idempotency conflict; 422 Request body failed schema validation; 429 Rate limit or durable quota exceeded; 500 Internal failure; 502 Venue or provider failure; 503 Required dependency unavailable; 504 Request timeout. --- # API reference: Feedback and support Source: https://felix.trade/docs/api/feedback-and-support > Report feedback and run encrypted, account-scoped support tickets through the API. Feedback and support writes are encrypted at rest, scoped to the calling account, idempotent, and rate-limited. Include request ids, operation ids, endpoint names, position or agent ids, the client version, and the error code. Never include a credential, signature, or signed transaction. ## Feedback ### POST /v1/feedback Report a bug, product issue, or request with a bounded category, severity, message, and diagnostic context. Authorization: API key with `read` scope. Rate-limit bucket: `feedback`. `Idempotency-Key` header: required. Request body (JSON, required): - `category` (string, required): Problem area. [one of "bug", "feature_request", "docs", "order", "backtest", "wallet", "account", "support", "other"] - `severity` (string, optional): Reporter-assessed severity. [one of "low", "medium", "high", "critical"; default "medium"] - `message` (string, required): Problem description. Stored encrypted and never logged. [at least 10 characters; at most 4000 characters] - `context` (object, optional): Optional bounded diagnostic identifiers. Secrets and free-form nested data are not accepted. - `request_id` (string, optional): Felix request id. [at most 240 characters] - `endpoint` (string, optional): API endpoint. [at most 240 characters] - `tool` (string, optional): MCP tool name. [at most 240 characters] - `order_id` (string, optional): Related order id. [at most 240 characters] - `position_id` (string, optional): Related position id. [at most 240 characters] - `backtest_id` (string, optional): Related backtest id. [at most 240 characters] - `agent_id` (string, optional): Related agent id. [at most 240 characters] - `client_version` (string, optional): SDK/MCP version. [at most 240 characters] - `error_code` (string, optional): Stable Felix error code. [at most 240 characters] Error statuses: 400 Invalid request; 401 Missing or invalid API key; 403 Scope, policy, or live-trading restriction; 404 Owned resource not found; 409 State or idempotency conflict; 422 Request body failed schema validation; 429 Rate limit or durable quota exceeded; 500 Internal failure; 502 Venue or provider failure; 503 Required dependency unavailable; 504 Request timeout. ### GET /v1/feedback List feedback reports belonging to this account. Authorization: API key with `read` scope. Rate-limit bucket: `read`. Query parameters: - `limit` (integer, optional) [minimum 1; maximum 50; default 20] Error statuses: 400 Invalid request; 401 Missing or invalid API key; 403 Scope, policy, or live-trading restriction; 404 Owned resource not found; 409 State or idempotency conflict; 422 Request body failed schema validation; 429 Rate limit or durable quota exceeded; 500 Internal failure; 502 Venue or provider failure; 503 Required dependency unavailable; 504 Request timeout. ### GET /v1/feedback/{feedback_id} Read one feedback report belonging to this account. Authorization: API key with `read` scope. Rate-limit bucket: `read`. Path parameters: - `feedback_id` (string, required) Error statuses: 400 Invalid request; 401 Missing or invalid API key; 403 Scope, policy, or live-trading restriction; 404 Owned resource not found; 409 State or idempotency conflict; 422 Request body failed schema validation; 429 Rate limit or durable quota exceeded; 500 Internal failure; 502 Venue or provider failure; 503 Required dependency unavailable; 504 Request timeout. ## Support tickets Ticket creation is limited to 10 per account per day and messages to 30 per account per day. Retry an interrupted write with the same `Idempotency-Key`; Felix repairs state deterministically without duplicating the ticket or message. ### POST /v1/support/tickets Open an encrypted two-way support ticket readable only by this account and Felix support. Authorization: API key with `read` scope. Rate-limit bucket: `feedback`. `Idempotency-Key` header: required. Request body (JSON, required): - `subject` (string, required): Short support-ticket summary. [at least 4 characters; at most 160 characters] - `message` (string, required): Initial support request. Stored encrypted. [at least 10 characters; at most 4000 characters] - `category` (string, optional): Problem area. [one of "bug", "feature_request", "docs", "order", "backtest", "wallet", "account", "support", "other"; default "support"] - `severity` (string, optional): Reporter-assessed severity. [one of "low", "medium", "high", "critical"; default "medium"] - `context` (object, optional): Bounded diagnostic identifiers only. Never include credentials or private keys. - `request_id` (string, optional): Felix request id. [at most 240 characters] - `endpoint` (string, optional): API endpoint. [at most 240 characters] - `tool` (string, optional): MCP tool name. [at most 240 characters] - `order_id` (string, optional): Related order id. [at most 240 characters] - `position_id` (string, optional): Related position id. [at most 240 characters] - `backtest_id` (string, optional): Related backtest id. [at most 240 characters] - `agent_id` (string, optional): Related agent id. [at most 240 characters] - `client_version` (string, optional): SDK or MCP version. [at most 240 characters] - `error_code` (string, optional): Stable Felix error code. [at most 240 characters] Error statuses: 400 Invalid request; 401 Missing or invalid API key; 403 Scope, policy, or live-trading restriction; 404 Owned resource not found; 409 State or idempotency conflict; 422 Request body failed schema validation; 429 Rate limit or durable quota exceeded; 500 Internal failure; 502 Venue or provider failure; 503 Required dependency unavailable; 504 Request timeout. ### GET /v1/support/tickets List this account's support tickets by status. Authorization: API key with `read` scope. Query parameters: - `status` (string, nullable, optional) [at most 24 characters] - `limit` (integer, optional) [minimum 1; maximum 50; default 20] Error statuses: 400 Invalid request; 401 Missing or invalid API key; 403 Scope, policy, or live-trading restriction; 404 Owned resource not found; 409 State or idempotency conflict; 422 Request body failed schema validation; 429 Rate limit or durable quota exceeded; 500 Internal failure; 502 Venue or provider failure; 503 Required dependency unavailable; 504 Request timeout. ### GET /v1/support/tickets/{ticket_id} Read one ticket and its complete message thread. Authorization: API key with `read` scope. Path parameters: - `ticket_id` (string, required) Error statuses: 400 Invalid request; 401 Missing or invalid API key; 403 Scope, policy, or live-trading restriction; 404 Owned resource not found; 409 State or idempotency conflict; 422 Request body failed schema validation; 429 Rate limit or durable quota exceeded; 500 Internal failure; 502 Venue or provider failure; 503 Required dependency unavailable; 504 Request timeout. ### POST /v1/support/tickets/{ticket_id}/messages Add an encrypted message to an open ticket. Authorization: API key with `read` scope. Rate-limit bucket: `feedback`. `Idempotency-Key` header: required. Path parameters: - `ticket_id` (string, required) Request body (JSON, required): - `message` (string, required): Support-thread reply. Stored encrypted. [at least 1 character; at most 4000 characters] Error statuses: 400 Invalid request; 401 Missing or invalid API key; 403 Scope, policy, or live-trading restriction; 404 Owned resource not found; 409 State or idempotency conflict; 422 Request body failed schema validation; 429 Rate limit or durable quota exceeded; 500 Internal failure; 502 Venue or provider failure; 503 Required dependency unavailable; 504 Request timeout. ### POST /v1/support/tickets/{ticket_id}/close Close a ticket while keeping its encrypted thread for audit. Authorization: API key with `read` scope. Rate-limit bucket: `feedback`. `Idempotency-Key` header: required. Path parameters: - `ticket_id` (string, required) Error statuses: 400 Invalid request; 401 Missing or invalid API key; 403 Scope, policy, or live-trading restriction; 404 Owned resource not found; 409 State or idempotency conflict; 422 Request body failed schema validation; 429 Rate limit or durable quota exceeded; 500 Internal failure; 502 Venue or provider failure; 503 Required dependency unavailable; 504 Request timeout. --- # API reference: Platform Source: https://felix.trade/docs/api/platform > Health, readiness, runtime status, client-observable reliability fields, the fee schedule, and the live capability matrix. These endpoints describe the service rather than an account. Health, readiness, status, fees, and capabilities need no key and are rate-limited per IP address. None of them exposes infrastructure internals. ## Health and status ### GET /v1/health Liveness check returning ok, the service name, the API version, and a timestamp. Authorization: No API key. Error statuses: 400 Invalid request; 401 Missing or invalid API key; 403 Scope, policy, or live-trading restriction; 404 Owned resource not found; 409 State or idempotency conflict; 429 Rate limit or durable quota exceeded; 500 Internal failure; 502 Venue or provider failure; 503 Required dependency unavailable; 504 Request timeout. ### GET /v1/ready Minimal readiness check; internal dependency checks are not exposed. Authorization: No API key. Error statuses: 400 Invalid request; 401 Missing or invalid API key; 403 Scope, policy, or live-trading restriction; 404 Owned resource not found; 409 State or idempotency conflict; 429 Rate limit or durable quota exceeded; 500 Internal failure; 502 Venue or provider failure; 503 Required dependency unavailable; 504 Request timeout. ### GET /v1/status Minimal public runtime status: service health, the API version, and bounded freshness fields. Authorization: No API key. Error statuses: 400 Invalid request; 401 Missing or invalid API key; 403 Scope, policy, or live-trading restriction; 404 Owned resource not found; 409 State or idempotency conflict; 429 Rate limit or durable quota exceeded; 500 Internal failure; 502 Venue or provider failure; 503 Required dependency unavailable; 504 Request timeout. ```json status response { "service": "felix-api", "status": "operational", "version": "2.0.221", "stale": false, "refreshing": false, "age_seconds": 4.2 } ``` ### GET /v1/metrics Document the client-observable reliability fields available on every response: request id, server latency, retry timing, and the public status URL. Returns no process or platform diagnostics. Authorization: API key with `read` scope. Rate-limit bucket: `market`. Error statuses: 400 Invalid request; 401 Missing or invalid API key; 403 Scope, policy, or live-trading restriction; 404 Owned resource not found; 409 State or idempotency conflict; 429 Rate limit or durable quota exceeded; 500 Internal failure; 502 Venue or provider failure; 503 Required dependency unavailable; 504 Request timeout. ## Fees and capabilities ### GET /v1/fees Return the execution-fee schedule by market type, tier discounts, and the live order types. No key required. Authorization: No API key. Error statuses: 400 Invalid request; 401 Missing or invalid API key; 403 Scope, policy, or live-trading restriction; 404 Owned resource not found; 409 State or idempotency conflict; 429 Rate limit or durable quota exceeded; 500 Internal failure; 502 Venue or provider failure; 503 Required dependency unavailable; 504 Request timeout. ### GET /v1/capabilities Return the capability matrix by venue with each cell marked live, private_beta, planned, or n/a, derived from the same registry the order executor enforces. Authorization: No API key. Error statuses: 400 Invalid request; 401 Missing or invalid API key; 403 Scope, policy, or live-trading restriction; 404 Owned resource not found; 409 State or idempotency conflict; 429 Rate limit or durable quota exceeded; 500 Internal failure; 502 Venue or provider failure; 503 Required dependency unavailable; 504 Request timeout. The matrix covers direct API trading. Lighter is not in it, because Lighter is available to agents only. The capability rows are `quotes`, `orderbook`, `funding_rates`, `options`, `paper_orders`, `live_orders`, `positions`, `pnl_reconciliation`, `agent_policies`, and `autonomous_agents`. Market data, paper trading, positions, PnL reconciliation, and owner-signed agent policies are platform-level and available for every implemented venue.