# Anboto API Reference > REST and WebSocket API reference for the Anboto algorithmic trading platform. Anboto is an institutional crypto execution platform: REST + WebSocket API for algo order execution (TWAP, VWAP, POV, Implementation Shortfall, Iceberg, Limit, Market) routed across 14+ CEXs and perp-DEXs (Binance, OKX, Bybit, Coinbase Prime, Hyperliquid, ...). Authentication uses API keys with HMAC-SHA256 or RSA-SHA256 request signing. Testnet (all fills simulated): https://api.testnet.anboto.xyz; production: https://api.pro.anboto.xyz. # Documentation # Anboto Trading API Execute orders across 14+ CEXs and perp-DEXs with Anboto's algorithmic strategies (TWAP, VWAP, POV, IS, Iceberg) through one REST + WebSocket API. ## Start here - [Get started](https://api-docs.anboto.xyz/resources/get-started/index.md) — keys, environments, signing, first order - [API Reference](https://api-docs.anboto.xyz/reference/index.md) — every REST endpoint, with code samples - [WebSocket](https://api-docs.anboto.xyz/resources/websocket/index.md) — real-time order, trade, position and balance streams - [Request examples](https://api-docs.anboto.xyz/resources/examples/index.md) — downloadable JSON payloads per strategy - [Rate limits](https://api-docs.anboto.xyz/resources/rate-limits/index.md) ## Machine-readable - [OpenAPI spec](https://api-docs.anboto.xyz/spec/anboto-trading-api-2.0.yml) · [AsyncAPI spec](https://api-docs.anboto.xyz/spec/asynapi.yml) - [llms.txt](/llms.txt) · [llms-full.txt](/llms-full.txt) — every page also has a Markdown twin (append `.md`) Client examples: [github.com/anbotolabs/examples](https://github.com/anbotolabs/examples) # For AI agents Anboto ships first-party tooling that connects AI agents (Claude, Cursor, Codex, or any MCP-compatible client) to the Trading API — including the execution algos (TWAP, VWAP, POV, IS, ICEBERG) that make Anboto an execution desk rather than an order button. Everything lives in the open-source [anboto-agent-kit](https://github.com/anbotolabs/anboto-agent-kit) (MIT): - `@anboto/mcp` — MCP server (stdio) with 22 tools: order creation and monitoring, portfolio, market data, preflight validation and guardrails - `@anboto/core` — typed TypeScript client (HMAC/RSA signing included) - `anboto-trading` — a Claude Skill teaching agents algo selection, execution monitoring and TCA ## Quickstart (Claude Code) ``` claude mcp add anboto \ -e ANBOTO_API_KEY=your-key \ -e ANBOTO_API_SECRET=your-base64-secret \ -- npx -y @anboto/mcp --testnet ``` Claude Desktop / Cursor (JSON config): ``` { "mcpServers": { "anboto": { "command": "npx", "args": ["-y", "@anboto/mcp", "--testnet"], "env": { "ANBOTO_API_KEY": "your-key", "ANBOTO_API_SECRET": "your-base64-secret" } } } } ``` Then ask the agent: *"On testnet, buy 0.001 BTC on Binance via TWAP over 5 minutes, monitor to completion, and give me an execution report."* ## Guardrails API keys stay on your machine (env vars only — never in the model context). Optional flags, all fail-closed: | Flag | Effect | | --------------------------------- | -------------------------------------------- | | `--testnet` | Simulated environment (recommended to start) | | `--read-only` | Trading tools are not registered at all | | `--max-order-notional=50000` | Reject orders above an estimated notional | | `--allowed-exchanges=BINANCE,OKX` | Exchange allowlist | | `--allowed-symbols=BTC/USDT` | Symbol allowlist | ## Machine-readable docs - [llms.txt](/llms.txt) index · full docs as one file: [llms-full.txt](/llms-full.txt) - OpenAPI (REST): [anboto-trading-api-2.0.yml](https://api-docs.anboto.xyz/spec/anboto-trading-api-2.0.yml) - AsyncAPI (WebSocket): [asynapi.yml](https://api-docs.anboto.xyz/spec/asynapi.yml) - Every page on this site has a Markdown twin — append `.md` to its URL # Error reference ## REST Failed requests return an HTTP error status; order-level failures also carry an `error_code` (`ApiErrorCode`) in the response body (`OrderSummary.error_code`, order status messages). ### HTTP statuses | Status | Meaning | | ------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `400` | Bad signature — `X-SIGN` does not match the request. The body is plain text, `Invalid Signature (7003)`, not JSON | | `401` | Unauthorized — missing/invalid API key | | `403` | Forbidden — the API key is read-only and the endpoint creates or cancels orders (see [Get started](https://api-docs.anboto.xyz/resources/get-started/#1-generate-an-api-key)) | | `429` | Rate limit exceeded — the JSON body gives `reason` and `retry_after_ms`, the `Retry-After` header the wait in seconds; see [Rate limits](https://api-docs.anboto.xyz/resources/rate-limits/index.md) | - A bad signature returns `400` on every endpoint, with the plain-text body above. The per-endpoint pages of the [API Reference](https://api-docs.anboto.xyz/reference/index.md) do not list this case; their `401` row means a missing or unknown API key. - A request whose `X-TIMESTAMP` is more than `X-RECV-WINDOW` ms (default 5000) in the past is rejected before it reaches the endpoint, but not with `401`: the gateway currently answers it with a generic server error (`5xx`). If every request fails that way, check your clock first. ### `error_code` values **Authentication / request** | Code | Description | | ---------------------- | ---------------------------------------- | | `AUTHENTICATION_ERROR` | Key not recognized or not permitted | | `INVALID_SIGNATURE` | `X-SIGN` does not match the payload | | `INVALID_API_KEY` | Unknown API key | | `INVALID_TIMESTAMP` | `X-TIMESTAMP` outside the receive window | | `INVALID_REQUEST` | Malformed request | | `INVALID_PARAM` | A parameter failed validation | | `BATCH_OVERSIZE` | Too many orders in one batch call | **Order validation** | Code | Description | | ------------------------ | --------------------------------------------------------- | | `INVALID_ORDER` | Order rejected at validation | | `INVALID_QUANTITY` | Quantity missing, non-positive, or below exchange minimum | | `QUANTITY_EXCEED` | Quantity above the allowed maximum | | `INVALID_SYMBOL` | Symbol unknown on the target exchange | | `INVALID_EXCHANGE` | Exchange not supported or not connected for the account | | `INVALID_TRADE_STRATEGY` | Unknown `strategy` value | | `INVALID_LIMIT_PRICE` | Limit price fails validation | | `INVALID_WOULD_PRICE` | Would price fails validation | | `INVALID_TRIGGER_PRICE` | Trigger price fails validation | | `INVALID_END_TIME` | End time in the past or before start time | | `INVALID_TRADE_TIME` | Execution window fails validation | | `INVALID_FEE` | Fee parameter fails validation | **Execution / exchange** | Code | Description | | ------------------------------------- | -------------------------------------------------------- | | `INSUFFICIENT_FUNDS` | Not enough balance on the venue | | `EXCHANGE_ERROR` | Exchange rejected the request (unmapped venue error) | | `EXCHANGE_NOT_AVAILABLE` | Venue unreachable or in maintenance | | `NETWORK_ERROR` | Transient connectivity failure | | `SLIPPAGE_EXCEEDED` | Fill would exceed the slippage tolerance | | `EXPIRY_REACHED` | Order expired before completing | | `PARENT_ORDER_WAS_TERMINATED` | Child rejected because the parent was cancelled/finished | | `MAX_FEE_PER_GAS_IS_TOO_LOW` | DEX: gas fee cap too low | | `MAX_PRIORITY_FEE_PER_GAS_IS_TOO_LOW` | DEX: priority fee too low | **Platform** | Code | Description | | --------------------- | ------------------------------------------------ | | `RATE_LIMIT_EXCEEDED` | Account request budget exhausted | | `DDOS_PROTECTION` | Venue anti-abuse triggered — reduce request rate | | `EMS_INSTANCES_DOWN` | Execution engine temporarily unavailable | | `SYSTEM_ERROR` | Internal error | | `SYSTEM_BUSY` | Platform under load — retry | | `OTHER` | Unclassified | ## WebSocket Every subscribe/unsubscribe gets a `{code, message}` response: | Code | Meaning | | ------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `0` | OK — ack; `message` echoes your request | | `5` | `RATE_LIMIT_EXCEEDED` — a message limit, a subscription limit, or the account's connection limit (`connection limit reached (N per account)`, then close 1008); see [Rate limits](https://api-docs.anboto.xyz/resources/rate-limits/index.md) | | `8054` | `exchange` missing or invalid | | `7002` | Invalid request — unparseable message or missing `method` | | `7001` | Internal error — the subscription stream terminated; re-subscribe | Close codes: `1001` idle timeout (no client message for 5 min), `1008` policy violation (rate limits, invalid listenKey). # Request examples Ready-to-send JSON payloads for the most common calls. Values are illustrative — adjust symbol, size and times. Field reference: the endpoint pages linked under each example. Full client examples (signing included): [github.com/anbotolabs/examples](https://github.com/anbotolabs/examples). All create-order payloads go to [Create order](https://api-docs.anboto.xyz/reference/create-order/index.md) unless stated otherwise. ## TWAP Spread 0.5 BTC over one hour, hybrid style, randomized slices. `duration_seconds` is required for TWAP and VWAP. By default TWAP, VWAP and IS orders may run a little past `duration_seconds` to finish, but never past `end_time`; send `"extend_duration": false` in `params` to stop on schedule. [Download](https://api-docs.anboto.xyz/examples/create-order-twap.json) ``` { "client_order_id": "ORD-2026-0001", "exchange": "BINANCE", "symbol": "BTC/USDT", "asset_category": "SPOT", "side": "BUY", "quantity": "0.5", "strategy": "TWAP", "limit_price": "62000", "start_time": "2026-09-01T10:00:00Z", "end_time": "2026-09-01T11:00:00Z", "params": { "duration_seconds": "3600", "trading_style": "HYBRID", "randomize_amount": true } } ``` ## VWAP Four-hour passive VWAP. [Download](https://api-docs.anboto.xyz/examples/create-order-vwap.json) ``` { "client_order_id": "ORD-2026-0002", "exchange": "BINANCE", "symbol": "BTC/USDT", "asset_category": "SPOT", "side": "BUY", "quantity": "0.5", "strategy": "VWAP", "limit_price": "62000", "start_time": "2026-09-01T10:00:00Z", "end_time": "2026-09-01T14:00:00Z", "params": { "duration_seconds": "14400", "trading_style": "PASSIVE" } } ``` ## Limit One order at `limit_price`. [Download](https://api-docs.anboto.xyz/examples/create-order-limit.json) ``` { "client_order_id": "ORD-2026-0003", "exchange": "BINANCE", "symbol": "BTC/USDT", "asset_category": "SPOT", "side": "BUY", "quantity": "0.5", "strategy": "LIMIT", "limit_price": "60500" } ``` ## Market (reduce-only, perpetual) Close 0.25 BTC of a perp position at market. [Download](https://api-docs.anboto.xyz/examples/create-order-market.json) ``` { "client_order_id": "ORD-2026-0004", "exchange": "BINANCE", "symbol": "BTC/USDT:USDT", "asset_category": "FUTURE", "side": "SELL", "quantity": "0.25", "strategy": "MARKET", "params": { "reduce_only": true } } ``` ## Iceberg Show 0.25 BTC clips of a 5 BTC order, about 2 seconds apart. `timer_iceberg_delay` is the delay between clips in seconds, from 0.25 to 3600 (default 0.25); with `randomize_iceberg_timer` (default `true`) each delay is drawn between 80 % and 120 % of it. Both also apply to Scale orders. [Download](https://api-docs.anboto.xyz/examples/create-order-iceberg.json) ``` { "client_order_id": "ORD-2026-0005", "exchange": "BINANCE", "symbol": "BTC/USDT", "asset_category": "SPOT", "side": "BUY", "quantity": "5", "strategy": "ICEBERG", "limit_price": "61000", "clip_size_type": "ABSOLUTE", "clip_size_val": "0.25", "params": { "trading_style": "PASSIVE", "randomize_amount": true, "timer_iceberg_delay": 2, "randomize_iceberg_timer": true } } ``` ## POV (percentage of volume) Sell 2 BTC at 5 % of the market volume, never below 60 000. `pov_ratio` is required: a percent of market volume, from 0.01 to 33. `pov_risk` sets how far the order may fall behind its target before it sends the next child order: `LOW` (2 %), `DEFAULT` (7.5 %) or `HIGH` (15 %). [Download](https://api-docs.anboto.xyz/examples/create-order-pov.json) ``` { "client_order_id": "ORD-2026-0009", "exchange": "BINANCE", "symbol": "BTC/USDT", "asset_category": "SPOT", "side": "SELL", "quantity": "2", "strategy": "POV", "limit_price": "60000", "params": { "pov_ratio": 5, "pov_risk": "DEFAULT", "trading_style": "HYBRID" } } ``` ## Implementation shortfall Urgency drives the schedule (`LOW` / `MEDIUM` / `HIGH`). [Download](https://api-docs.anboto.xyz/examples/create-order-is.json) ``` { "client_order_id": "ORD-2026-0006", "exchange": "BINANCE", "symbol": "BTC/USDT", "asset_category": "SPOT", "side": "BUY", "quantity": "0.5", "strategy": "IS", "limit_price": "62500", "params": { "urgency": "HIGH" } } ``` ## Scale (ladder) Ten resting orders laddered from 61 000 down to 59 000. [Download](https://api-docs.anboto.xyz/examples/create-order-scale.json) ``` { "client_order_id": "ORD-2026-0007", "exchange": "BINANCE", "symbol": "BTC/USDT", "asset_category": "SPOT", "side": "BUY", "quantity": "2", "strategy": "SCALE", "clip_size_type": "ORDER_COUNT", "clip_size_val": "10", "params": { "start_ladder_price": "61000", "end_ladder_price": "59000", "ladder_direction": "downwards", "ladder_profile": "linear", "size_skew": 1 } } ``` ## Triggered order TWAP that starts only once the price trades above 63 000. [Download](https://api-docs.anboto.xyz/examples/create-order-trigger.json) ``` { "client_order_id": "ORD-2026-0008", "exchange": "BINANCE", "symbol": "BTC/USDT", "asset_category": "SPOT", "side": "BUY", "quantity": "0.5", "strategy": "TWAP", "limit_price": "64000", "params": { "duration_seconds": "1800", "trigger": { "trigger_price": "63000", "trigger_condition": "ABOVE" } } } ``` ## Placement in basis points Rest each slice 5 bps from the midpoint, on its own side of the book, and cancel it once the market has moved away and it sits 20 bps from the midpoint. With `depth_mode: BPS_SPREAD`, `placement` and `cancel` are whole basis points from the midpoint and both are required: `placement` from 1 to 500, `cancel` above `placement` and at most 1000. Without `depth_mode` (or with `LEVEL`) they count levels of the order book. [Download](https://api-docs.anboto.xyz/examples/create-order-bps-placement.json) ``` { "client_order_id": "ORD-2026-0010", "exchange": "BINANCE", "symbol": "BTC/USDT", "asset_category": "SPOT", "side": "BUY", "quantity": "0.5", "strategy": "TWAP", "limit_price": "62000", "params": { "duration_seconds": "3600", "trading_style": "PASSIVE", "placement_infos": { "placement_mode": "CUSTOM", "depth_mode": "BPS_SPREAD", "placement": "5", "cancel": "20" } } } ``` ## Multi-leg pair Buy BTC / sell ETH, 10 000 USD each leg, BTC leading — [Create multi legs order](https://api-docs.anboto.xyz/reference/create-multi-legs-order/index.md). [Download](https://api-docs.anboto.xyz/examples/create-multi-legs-pair.json) ``` { "client_order_id": "PAIR-2026-0001", "algo": "PAIR", "legs": [ { "exchange": "BINANCE", "symbol": "BTC/USDT", "asset_category": "SPOT", "side": "BUY", "target_value": "10000", "ccy": "USD", "limit_price": "62000", "strategy": "TWAP", "params": { "duration_seconds": "1800", "trading_style": "HYBRID", "is_leading": true } }, { "exchange": "BINANCE", "symbol": "ETH/USDT", "asset_category": "SPOT", "side": "SELL", "target_value": "10000", "ccy": "USD", "limit_price": "2400", "strategy": "TWAP", "params": { "duration_seconds": "1800", "trading_style": "HYBRID", "is_leading": false } } ], "start_time": "2026-09-01T10:00:00Z", "end_time": "2026-09-01T10:30:00Z" } ``` ## Batch of orders Three TWAPs in one call — [Create many orders](https://api-docs.anboto.xyz/reference/create-many-orders/index.md). [Download](https://api-docs.anboto.xyz/examples/create-many-orders.json) ``` { "orders": [ { "client_order_id": "BASKET-1-BTC", "exchange": "BINANCE", "symbol": "BTC/USDT", "asset_category": "SPOT", "side": "BUY", "quantity": "0.5", "strategy": "TWAP", "params": { "duration_seconds": "3600" } }, { "client_order_id": "BASKET-1-ETH", "exchange": "BINANCE", "symbol": "ETH/USDT", "asset_category": "SPOT", "side": "BUY", "quantity": "8", "strategy": "TWAP", "params": { "duration_seconds": "3600" } }, { "client_order_id": "BASKET-1-SOL", "exchange": "BINANCE", "symbol": "SOL/USDT", "asset_category": "SPOT", "side": "BUY", "quantity": "150", "strategy": "TWAP", "params": { "duration_seconds": "3600" } } ] } ``` ## Cancel many By Anboto id or by your client id — [Cancel many](https://api-docs.anboto.xyz/reference/cancel-many/index.md). [Download](https://api-docs.anboto.xyz/examples/cancel-many.json) ``` { "orders": [ { "order_id": 123456 }, { "client_order_id": "BASKET-1-ETH" } ] } ``` # Get started Anboto's Trading API executes orders across 14+ CEXs and perp-DEXs with algorithmic strategies (TWAP, VWAP, POV, IS, Iceberg). This guide takes you from zero to a first order. ## 1. Generate an API key Create keys in the [trading app](https://pro.anboto.xyz/settings/api). Two types: | Type | Signing | Notes | | ---------------- | ----------- | --------------------------------------------------------- | | System-generated | HMAC-SHA256 | Anboto gives you key + secret | | Self-generated | RSA-SHA256 | You keep the private key; Anboto only gets the public key | A key has the permissions of the account member who created it. A member without trade permission gets a read-only key: it can call every read endpoint and open the WebSocket, but the endpoints that create or cancel orders, including [Cancel all open orders](https://api-docs.anboto.xyz/reference/cancel-all-open-orders/index.md), answer `403`. ## 2. Pick an environment | Environment | REST base | WebSocket | | ------------- | ---------------------------------------------------------------------------- | -------------------------------------------------- | | Production | `https://api.pro.anboto.xyz` | `wss://api.pro.anboto.xyz/api/v2/ws` | | Testnet | `https://api.testnet.anboto.xyz` — simulated fills, no real trades | `wss://api.testnet.anboto.xyz/api/v2/ws` | | Local sandbox | `http://127.0.0.1:8091` — compose `api-gw`; simulated Binance fills via JEMS | `ws://127.0.0.1:8092/api/v2/ws` — compose `api-ws` | ## 3. Sign requests Every authenticated call carries `X-API-KEY`, `X-TIMESTAMP` (ms), `X-SIGN`, optional `X-RECV-WINDOW` (default 5000 ms). String to sign: `timestamp + api_key + recv_window + (queryString | jsonBody)` — see [Authentication](https://api-docs.anboto.xyz/reference/index.md) for per-language code. ## 4. Place a first order Send a small TWAP on testnet: [Create order](https://api-docs.anboto.xyz/reference/create-order/index.md) — ready payloads in [Request examples](https://api-docs.anboto.xyz/resources/examples/index.md). Watch it fill in real time over the [WebSocket](https://api-docs.anboto.xyz/resources/websocket/index.md). Client examples: [github.com/anbotolabs/examples](https://github.com/anbotolabs/examples) # Portfolio PnL Three read-only endpoints report your team's portfolio performance. They use the same data and the same calculations as the PnL page of the [trading app](https://pro.anboto.xyz), so the API and the app show the same numbers for the same accounts and dates. | Endpoint | Returns | Built from | | ---------------------------------- | ------------------------------------------------------------------- | --------------------------------------------------------------------- | | `GET /api/v2/portfolio/pnl` | Daily PnL, returns, drawdown and Sharpe, per day and for the window | Daily account equity, minus deposits and withdrawals | | `GET /api/v2/portfolio/pnl/ledger` | Realized PnL, funding and fees, per day and per symbol | The income history the exchange reports (Binance USD-M futures first) | | `GET /api/v2/portfolio/flows` | Deposits, withdrawals and internal transfers | The exchange's transfer history, with duplicate legs removed | All three are signed GET requests, like the rest of the API (see [Get started](https://api-docs.anboto.xyz/resources/get-started/index.md)). A read-only API key is enough. Results are always for the team that owns the key. Every parameter and response field is listed in the [API Reference](https://api-docs.anboto.xyz/reference/index.md), under **Portfolio**. ## NAV PnL or ledger? The two PnL endpoints answer different questions, and their numbers do not match day by day. **`/pnl` is NAV PnL.** It measures how much the account value changed, with deposits and withdrawals taken out: ``` daily_pnl = equity_close - equity_prev - net_flows ``` `equity_close` is the account equity at 00:00 UTC at the end of the day, and it includes unrealized PnL. `equity_prev` is the previous day's close. So a day's PnL contains everything that moved the account value: realized and unrealized trading PnL, funding, fees, and price changes of non-stablecoin collateral. Use `/pnl` to measure performance: returns, drawdown, Sharpe. **`/pnl/ledger` is booked income.** It adds up what the exchange recorded as income: realized PnL on closed positions, funding payments, trading commissions, rebates and similar items. It contains no unrealized PnL. Use it to see where the performance came from: which symbols, how much funding, how much went to fees. On any given day, the gap between the two is mostly the change in unrealized PnL and in the value of collateral. The two get closer as positions are closed, but they are not expected to be equal: the ledger also leaves out venues and items it does not cover yet (see [Ledger coverage](#ledger-coverage)). NAV PnL covers accounts on Binance, Bybit, OKX, WOO X and Hyperliquid. Accounts on other exchanges have no NAV PnL yet. ## Selecting accounts All three endpoints take an optional `accounts` parameter: one comma-separated string. | Item | Selects | | -------------- | ----------------------------------------------------------------------- | | `binance` | Every Binance account of the team: the main account and all subaccounts | | `binance:` | The Binance main account only | | `binance:Sub1` | The Binance subaccount named `Sub1` | - Leave `accounts` out to get every account of the team, like the app's "All accounts" view. - Combine items freely, for example `accounts=binance:,bybit:Sub1,okx`. The selected accounts are added together day by day. - Exchange codes are lower case: `binance`, `bybit`, `okx`, `woo`, `hyperliquid`. - Send at most 20 items. Duplicates, empty items and unknown exchanges return `400`. - Subaccount names are matched exactly, case included, and are not checked against the team's accounts. The API has no endpoint that lists them. A name with no history is not an error: `/pnl` answers `200` with an empty `series`, `point_count: 0` and `since_inception_date: null`, and does not list it in `uncovered_exchanges`. On `/pnl/ledger`, such a name on Binance gets no entry in `coverage` (on other exchanges it is listed as `unsupported`), and `/flows` returns no rows for it. Read an empty result for a named subaccount as a possible misspelling, not as zero PnL. Not the same rule as `/trading/*` On [Get balance](https://api-docs.anboto.xyz/reference/get-balance/index.md), [Get position](https://api-docs.anboto.xyz/reference/get-position/index.md) and [Get account margin](https://api-docs.anboto.xyz/reference/get-account-margin/index.md), leaving out `subaccount` means the default account. Here, an exchange with no subaccount means **all** of that exchange's accounts. Write `binance:` to get the main account only. ### Signing the `accounts` value Sign the value as written, without percent-encoding: the string to sign contains `accounts=binance:,bybit:Sub1`. On the wire, `:` and `,` may be percent-encoded (`%3A`, `%2C`); the server decodes them before it checks the signature. Two limits apply: - Send a space as `%20`, never as `+`. The server does not turn `+` back into a space, so the signature check fails. Python's `urlencode` and `requests` both use `+` by default; pass `quote_via=quote` as shown below. - A subaccount whose name contains `,` `:` `&` `=` `#` or `+` cannot be selected on its own. Select the whole exchange instead (`binance`). In Python, with `BASE` and `signed_headers_query` from the authentication helpers in the [API Reference](https://api-docs.anboto.xyz/reference/index.md): ``` from urllib.parse import quote, urlencode import requests params = {"accounts": "binance:,binance:Desk 2", "period": "30d"} # keys in alphabetical order query = urlencode(params, quote_via=quote) # accounts=binance%3A%2Cbinance%3ADesk%202&period=30d r = requests.get(f"{BASE}/api/v2/portfolio/pnl?{query}", headers=signed_headers_query(params)) ``` ## Grouping `/pnl` returns one combined series for the whole selection. Add `groupBy` to also get one series per group: | `groupBy` | One group per | | ---------------- | ----------------------------------------------------- | | `none` (default) | No groups, only the total | | `exchange` | Exchange | | `account` | Account: an exchange's main account or one subaccount | Money values (`daily_pnl`, `net_flows`, the equity fields, cumulative PnL) of the groups add up to the total, up to floating-point rounding. A group's `series` has only the days of `total.series` on which that group had data; on a missing day the group contributed 0. Groups also carry `today_pnl`, `period_return_pct` and `estimated`; the return is computed separately for each group and does not add up. Sharpe, drawdown and the since-inception figures are only computed for `total`: in `groups`, `sharpe`, `max_drawdown_pct` and the `since_inception_*` fields are `null`, and so are each point's `daily_return_pct`, `drawdown_pct`, `daily_unrealized_pnl` and `unrealized_pnl_close`. In each group, `key` names the group: `exchange`, plus `subaccount` with `groupBy=account` (`""` is the main account). Key fields the grouping does not use are `null`. This `groupBy` belongs to `/pnl`. `/pnl/ledger` has its own `groupBy` with other values (see [Ledger and flows parameters](#ledger-and-flows-parameters)). ## Dates and freshness Days are UTC calendar days. A day closes at 00:00 UTC, and its row is written a few minutes later, so the last closed day is yesterday. ### Window `/pnl` and `/pnl/ledger` take a window of whole days: - Choose it with `period` (`d` with N from 1 to 3660, `week`, `month`, `quarter` or `year`; default `30d`) or with `startDate` and `endDate` (`YYYY-MM-DD`, both included). `startDate` takes precedence over `period`, and `period` counts back from `endDate`. Any other `period` value returns `400`. - On `/pnl`, `endDate` defaults to yesterday, the last closed day, and may not be later: an `endDate` of today or later returns `400`. Today's PnL so far is `today_pnl` (see [Freshness](#freshness)). - On `/pnl/ledger`, `endDate` defaults to today and may not be later. Today's figures are provisional (see [Ledger coverage](#ledger-coverage)). - `from_date` and `to_date` in the response give the window as applied. `/flows` takes its window in milliseconds instead: `startMs` and `endMs`, in ms since epoch, both included. `endMs` defaults to now and `startMs` to 30 days before `endMs`. `/flows` ignores `period`, `startDate` and `endDate` without returning an error, so a request that sends them gets the last 30 days. `scope` limits `/pnl` to the spot or the futures wallets (`total`, `spot` or `future`; default `total`). The longest window depends on the endpoint and, for `/pnl`, on `scope`: | Request | Longest window | | ------------------------------------------ | -------------------------------------- | | `/pnl` with `scope=total` | 3660 days | | `/pnl` with `scope=spot` or `scope=future` | 366 days | | `/pnl/ledger` | 366 days | | `/flows` | 366 days between `startMs` and `endMs` | A longer window returns `400`; it is not cut short. ### Freshness - `today_pnl` on `/pnl` is the PnL of the current, unfinished day, read from the latest equity snapshot. Snapshots are taken every hour. Today's figure moves during the day; after midnight the closed day replaces it. - `nav_usd` on `/pnl` is the current value of the selected accounts: the sum of each account's newest equity snapshot, if it is at most 3 days old. With `scope=spot` or `scope=future` it is the equity of that wallet only. It is `null` when no snapshot is available. - `as_of` is an ISO-8601 UTC time, or `null` when there is none. On `/pnl` it is the time of the newest equity snapshot used for `today_pnl` and `nav_usd`. On `/pnl/ledger` it is the time of the newest income data read from the exchange. - A point has `quality: "estimated"` when one of its two equity closes had to be estimated, or when one of that day's transfers had to be inferred from equity changes because the exchange's history did not record it or did not give its direction. `estimated` on the summary is `true` when any point in the window is estimated. - Since-inception figures (`since_inception_*`) start at the first closed day of the selected accounts, not of the whole team. ## Ledger and flows parameters Besides `accounts` and the window, the ledger and flows endpoints take these filters: | Endpoint | Parameter | Values | | ------------- | ---------- | ------------------------------------------------------------------------------------------------------------- | | `/pnl/ledger` | `groupBy` | One row per account and `day`, `symbol` or `day_symbol` (default). Not the same values as `groupBy` on `/pnl` | | `/pnl/ledger` | `symbol` | One Anboto symbol, for example `BTC/USDT:USDT` | | `/pnl/ledger` | `market` | `spot` or `future` | | `/flows` | `types` | Comma-separated `deposit`, `withdrawal`, `internal_transfer`; default all | | `/flows` | `external` | `true`: only deposits and withdrawals; `false`: only transfers inside the team; default both | ### Pagination `/pnl/ledger` and `/flows` return their rows in pages: - `limit` sets the page size: 1 to 5000 rows on `/pnl/ledger` (default 1000), 1 to 1000 flows on `/flows` (default 500). - `next_cursor` is `null` on the last page. Otherwise, send the same request again with `cursor` set to `next_cursor`, unchanged, and sign it like any other parameter. - `totals` covers the whole window and selection on every page, not only the rows of the current page. To store a history, read every page until `next_cursor` is `null`. The first page alone can miss rows. ## Units | Value | Unit | | ---------------------------------- | ---------------------------------------------------------------------- | | Money: PnL, equity, flows, `*_usd` | USD, as JSON numbers | | Every `*_pct` field | Percent: `2.5` means +2.5% | | `drawdown_pct`, `max_drawdown_pct` | Percent, zero or below: `-19.9` is 19.9% under the previous peak | | `sharpe` | Annualized with √365 from daily returns; `null` with fewer than 2 days | - `period_return_pct` is a simple return: the window's total PnL divided by the account equity at the start of the window. It is not time-weighted, so a large deposit or withdrawal inside the window changes its meaning. The daily `daily_return_pct` values are each day's PnL divided by the previous close. - `null` means unknown, never zero. For example, `today_pnl` is `null` when a transfer made today could not be priced yet. - An account's PnL for a day is unknown when that day has a transfer that could not be priced, or when the account has no two comparable equity closes. No point carries it as `null` or `0`; what happens to the date depends on the selection: - One account, any `scope`: the date is missing from `series`. - Several accounts with `scope=spot` or `scope=future`: the date is missing from `series` as soon as one selected account's PnL is unknown. - Several accounts with `scope=total`: the date is missing from `total.series` only when the accounts with an unknown PnL together held at least 5% of the selection's equity at the close of the previous day in `total.series`. Otherwise the day is kept without them: their PnL, flows and equity are left out of that day, like a group on a day it has no point (see [Grouping](#grouping)). An account that never comes back, for example after its API key is removed, removes at most 3 days; the days after that are kept without it. - `uncovered_exchanges` lists the requested exchanges that have no NAV PnL (without `accounts`: the team's connected exchanges that have none). They are left out of every figure. When none of the selected exchanges is covered, `total` still comes back, with `cumulative_pnl` at `0` and an empty `series`. Read that as "not covered", not as zero PnL. ## Flows sign convention `/flows` lists the capital movements that `/pnl` with `scope=total` takes out of the PnL, after the same de-duplication. | Field | Meaning | | ---------------- | -------------------------------------------------------------------------------------------------------------- | | `subaccount` | The account the row belongs to; `""` is the main account | | `type` | `deposit`, `withdrawal` or `internal_transfer` | | `direction` | `in`, `out`, `internal` or `unknown`, seen from the listed account | | `qty` | Amount of `asset`, always positive | | `usd_value` | USD value at the time of the transfer, or `null` if it could not be priced | | `net_flow_usd` | Signed contribution to `net_flows` of `/pnl` with `scope=total`: positive for money in, negative for money out | | `counted_in_pnl` | `false` when the transfer does not change `net_flows` | - A transfer between the main account and a subaccount, or between two subaccounts, is money out of one account and money in to the other. With both accounts selected, the two legs cancel out. - Moving funds between wallets of the same account, for example from Binance spot to USD-M futures, does not change that account's equity: `direction` is `internal`, `net_flow_usd` is `0` and `counted_in_pnl` is `false`. - A transfer whose direction is `unknown` is not counted either: `net_flow_usd` is `0` and `counted_in_pnl` is `false`. - A transfer that could not be priced has `usd_value: null`. It is counted in `totals.unpriced_count` and left out of the USD sums in `totals`. - Rows are sorted by time, oldest first. The exchange's raw transfer record is never returned. `/flows` and `net_flows` of `/pnl` match only with `scope=total`, and only on days whose transfers were all read from the exchange: - With `scope=spot` or `scope=future`, `net_flows` of `/pnl` also counts moves between the spot and futures wallets of one account, which `/flows` reports with `net_flow_usd` at `0`. - When the exchange's history did not record a transfer between two accounts of the team, or did not give its direction, `/pnl` can infer it from the opposite equity changes of the two accounts. It marks that day `quality: "estimated"`, and the day's `net_flows` then includes a transfer that has no counted row in `/flows`. ## Ledger coverage The ledger only reports what it has actually read from the exchange. A gap is reported as a gap, never as a zero. - **Covered:** Binance USD-M futures, including the USD-M side of Portfolio Margin accounts. - **Not covered yet:** Binance spot and COIN-M futures, and all other exchanges. The response's `coverage` lists these accounts as `unsupported`. - **History:** Binance keeps about three months of income history. Older days cannot be fetched. - **Freshness:** income is read every hour. Today's figures are provisional, and a day becomes final about two hours after it closes at 00:00 UTC. - **Prices:** amounts paid in a non-stablecoin asset, such as BNB commission, are valued at that asset's Binance daily close. `unpriced_assets` lists the assets that could not be valued; their amounts are missing from the USD figures. - **Not included:** Portfolio Margin borrowing interest. Each of the team's accounts in the selection has an entry in `coverage` that says whether its data for the window is complete; a Binance subaccount name the team does not have gets none (see [Selecting accounts](#selecting-accounts)). Its `status` is `complete`, `partial` or `unsupported`; `ingested_through` gives the time up to which income has been read, and `reason` says why an account is partial or unsupported. Rows exist only for days with income data. A date with no row is either a covered day with no income or a day that is not covered; `coverage` tells the two apart. A day that is not covered is never sent as a row of zeros. **Sign convention:** positive is income to the account, negative is a cost. `totals` and every row carry the same components. Rows exist only for covered days, so their components are always numbers. When no day of the window is covered, for example for an account on another exchange, with `market=spot`, or for a window older than the history Binance keeps, every component of `totals` is `null`; `coverage` says why. | Field | Contains | | -------------- | ---------------------------------------------------------------------------- | | `realized_pnl` | Realized PnL of closed positions | | `funding` | Funding payments: positive when received, negative when paid | | `commission` | Trading fees, zero or negative | | `fee_rebate` | Fee rebates, zero or positive | | `interest` | Borrowing interest; `0` while it is not covered (see **Not included** above) | | `other` | Other income that counts as PnL, such as rewards | | `net` | The sum of the fields above | Transfers are not income and never appear in the ledger; they are listed by `/flows`. ## Request cost - Responses are cached for about 60 seconds, so polling more often returns the same data. Daily rows change once a day, shortly after 00:00 UTC. `today_pnl` changes about once an hour. - `scope=spot` and `scope=future` are computed from equity snapshots on every request, which is much slower than `scope=total`. Every such request recomputes the whole history of the selected accounts, from their first daily close through yesterday, whatever the window. Their cost grows with the age of the accounts, not with the window: a `period=7d` request costs as much as a 366-day one. Request them only as often as you need them. - To build a long history, fetch it once, store it, and then request only the last few days: `period=7d` on `/pnl` with `scope=total` and on `/pnl/ledger`, or `startMs` set to 7 days ago on `/flows`. On `/pnl/ledger` and `/flows`, read every page (see [Pagination](#pagination)). - Select only the accounts you need. `groupBy=account` over a long window returns one series per account, which makes large responses. - Portfolio requests count against your rate limit. On `429`, back off and retry (see [Rate limits](https://api-docs.anboto.xyz/resources/rate-limits/index.md)). ## Errors | Status | Body | When | | ------ | -------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `400` | JSON: `{"error": ""}` | A parameter is invalid: a bad `accounts` item, an unknown exchange, a `period` that is not `d`, `week`, `month`, `quarter` or `year`, a malformed date, `startDate` after `endDate` or `startMs` after `endMs`, an `endDate` after yesterday on `/pnl` or after today on `/pnl/ledger`, a window that is too long, a `symbol` on `/pnl/ledger` that is not a known symbol of a covered market or is longer than 64 characters, or a bad `limit` or `cursor` | | `400` | Plain text: `Invalid Signature (7003)` | The signature does not match the request. A common cause here is a space sent as `+` in `accounts` (see [Signing the `accounts` value](#signing-the-accounts-value)) | | `401` | | The API key is missing or unknown (see [Errors](https://api-docs.anboto.xyz/resources/errors/index.md)) | | `429` | | Rate limit exceeded; back off and retry (see [Rate limits](https://api-docs.anboto.xyz/resources/rate-limits/index.md)) | | `502` | `{"error": ""}` | The portfolio service gave an answer the gateway could not use, for example one too large to pass on. Retry with a shorter window or fewer accounts (or without `groupBy=account`), and contact support if it persists | | `503` | `{"error": "portfolio service unavailable"}` | The portfolio service is down or timed out; retry later | Not every `400` body is JSON: check the `Content-Type` header before you parse it. # Rate limits ## REST Every signed REST request counts against your account's budget. All API keys of the account (team) share one budget. | Limit | Default | Meaning | | ------------------- | ------- | ------------------------------------------------------------------------------- | | Requests per second | 20 | Refill rate of a token bucket | | Burst | 100 | Size of the bucket: how many requests you can send at once after a quiet period | | Requests per day | 100 000 | Per UTC day; the count restarts at 00:00 UTC | Anboto can raise these for your account, up to 100 requests per second, a burst of 500 and 500 000 requests per day. A request over the budget is answered `429 Too Many Requests` with a JSON body and a `Retry-After` header: ``` HTTP/1.1 429 Too Many Requests Retry-After: 1 Content-Type: application/json {"code": 5, "message": "Rate limit exceeded", "reason": "burst", "retry_after_ms": 50} ``` | Field | Meaning | | -------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------ | | `code` | `5` = `RATE_LIMIT_EXCEEDED` | | `reason` | `burst`: the bucket is empty; wait `retry_after_ms` for the next token. `daily_quota`: the day's requests are used up; `retry_after_ms` runs until 00:00 UTC | | `retry_after_ms` | How long to wait, in milliseconds | | `Retry-After` header | The same wait in whole seconds, rounded up | A request refused because the bucket is empty does not count toward the daily total. A request whose `X-TIMESTAMP` is more than `X-RECV-WINDOW` ms (default 5000) in the past is rejected, currently with a generic server error rather than `401` (see [Errors](https://api-docs.anboto.xyz/resources/errors/index.md)). ## WebSocket | Limit | Default | On breach | | ----------------------------------------- | ------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | Concurrent connections per account | 5; Anboto can raise it up to 50 | the connection that goes over the limit gets a code-5 error frame (`connection limit reached (5 per account)`) and is closed (1008). Connections opened earlier stay up | | Messages per second per connection | 10 (burst 20) | code-5 error frame per dropped message; sustained flooding closes the connection (1008) | | Subscriptions per connection (all topics) | 50 | code-5 error frame | | Market data subscriptions per connection | 20 | error frame ("limit reached") | Error code `5` = `RATE_LIMIT_EXCEEDED`. # WebSocket Real-time streams: order status, child orders, trades, positions, position risk, balances, market data. **Read-only** — orders are placed and cancelled through the REST API. ## Authentication (listenKey) 1. Call `GET /api/v2/trading/listenKey` (signed like any REST call). Response body = listenKey, a JWT valid **1 hour**. 1. Connect to `wss:///api/v2/ws?listenKey=` — or send `Authorization: Bearer ` as a handshake header (keeps the token out of proxy logs). Invalid/expired listenKey → handshake rejected with HTTP 401. Checked only at handshake; established connections are not dropped on expiry, but every reconnect needs a fresh key. ## Keep-alive Server sends `{"topic":"ping"}` every minute — reply `{"topic":"pong"}`. No client message for 5 minutes → close 1001. Re-subscribe on every reconnect (subscriptions are per-connection). ## Subscribing ``` {"topic": "order", "exchange": "binance", "method": "subscribe"} ``` | Parameter | Description | | ---------- | ----------------------------------------------------------------------------------------------------------- | | `topic` | `order`, `child_order`, `trade`, `position`, `position_risk`, `balance`, `ticker`, `ohlcv`, `open_interest` | | `exchange` | required; any trading exchange, case-insensitive | | `method` | `subscribe` / `unsubscribe` | One subscription per `(topic, exchange)` pair per connection. ## Errors | Code | Meaning | | ------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `0` | OK — ack; `message` echoes your request | | `5` | rate limit exceeded — includes going over the account's connection limit, which closes the connection (1008); see [Rate limits](https://api-docs.anboto.xyz/resources/rate-limits/index.md) | | `8054` | `exchange` missing or invalid | | `7002` | invalid request — unparseable message or missing `method` | | `7001` | internal error — stream terminated; re-subscribe | # API changelog Every backend release that changes the public REST or WebSocket API adds an entry here, generated from the OpenAPI and AsyncAPI specs. Changes that need action on your side also get a numbered [change notice](https://api-docs.anboto.xyz/change-notices/index.md). ## v3.23063 — 2026-10-21 ### REST API **New endpoints** - [`GET /api/v2/strategies/campaigns`](https://api-docs.anboto.xyz/reference/campaigns/index.md) — List the team's PAPER-farm campaigns - [`GET /api/v2/strategies/campaigns/byId`](https://api-docs.anboto.xyz/reference/by-id/index.md) — Get one campaign - [`POST /api/v2/strategies/campaigns/create`](https://api-docs.anboto.xyz/reference/create/index.md) — Start a PAPER-farm campaign - [`POST /api/v2/strategies/campaigns/kill`](https://api-docs.anboto.xyz/reference/kill/index.md) — Hard-kill a campaign - [`POST /api/v2/strategies/campaigns/pause`](https://api-docs.anboto.xyz/reference/pause/index.md) — Pause a campaign - [`POST /api/v2/strategies/campaigns/resume`](https://api-docs.anboto.xyz/reference/resume/index.md) — Resume a paused or errored campaign - [`POST /api/v2/strategies/campaigns/stop`](https://api-docs.anboto.xyz/reference/stop/index.md) — Stop a campaign gracefully **Objects** - [`CreateStrategyCampaignRequest`](https://api-docs.anboto.xyz/reference/schemas/#createstrategycampaignrequest): new object. Used by `POST /api/v2/strategies/campaigns/create`. - [`PnlDateRange`](https://api-docs.anboto.xyz/reference/schemas/#pnldaterange): new object. Used by `GET /api/v2/portfolio/pnl`. - [`StrategyCampaign`](https://api-docs.anboto.xyz/reference/schemas/#strategycampaign): new object. Used by `GET /api/v2/strategies/campaigns`, `GET /api/v2/strategies/campaigns/byId`, `POST /api/v2/strategies/campaigns/create`, `POST /api/v2/strategies/campaigns/kill`, `POST /api/v2/strategies/campaigns/pause`, `POST /api/v2/strategies/campaigns/resume` and 1 more. - [`StrategyCampaignActionRequest`](https://api-docs.anboto.xyz/reference/schemas/#strategycampaignactionrequest): new object. Used by `POST /api/v2/strategies/campaigns/kill`, `POST /api/v2/strategies/campaigns/pause`, `POST /api/v2/strategies/campaigns/resume`, `POST /api/v2/strategies/campaigns/stop`. - [`StrategyCampaignCycle`](https://api-docs.anboto.xyz/reference/schemas/#strategycampaigncycle): new object. Used by `GET /api/v2/strategies/campaigns`, `GET /api/v2/strategies/campaigns/byId`, `POST /api/v2/strategies/campaigns/create`, `POST /api/v2/strategies/campaigns/kill`, `POST /api/v2/strategies/campaigns/pause`, `POST /api/v2/strategies/campaigns/resume` and 1 more. - [`StrategyCampaignLeg`](https://api-docs.anboto.xyz/reference/schemas/#strategycampaignleg): new object. Used by `GET /api/v2/strategies/campaigns`, `GET /api/v2/strategies/campaigns/byId`, `POST /api/v2/strategies/campaigns/create`, `POST /api/v2/strategies/campaigns/kill`, `POST /api/v2/strategies/campaigns/pause`, `POST /api/v2/strategies/campaigns/resume` and 1 more. - [`StrategyCampaignList`](https://api-docs.anboto.xyz/reference/schemas/#strategycampaignlist): new object. Used by `GET /api/v2/strategies/campaigns`. - [`StrategyStopRules`](https://api-docs.anboto.xyz/reference/schemas/#strategystoprules): new object. Used by `GET /api/v2/strategies/campaigns`, `GET /api/v2/strategies/campaigns/byId`, `POST /api/v2/strategies/campaigns/create`, `POST /api/v2/strategies/campaigns/kill`, `POST /api/v2/strategies/campaigns/pause`, `POST /api/v2/strategies/campaigns/resume` and 1 more. - [`ExchangeCode`](https://api-docs.anboto.xyz/reference/schemas/#exchangecode): new values `PAPERTRADE`. Used by `GET /api/v2/data/instruments`. - [`OrderLegParams`](https://api-docs.anboto.xyz/reference/schemas/#orderlegparams): added `timer_iceberg_delay_max` (number), `timer_iceberg_delay_min` (number). Used by `POST /api/v2/trading/order/createMany/multilegs`, `POST /api/v2/trading/order/create_multiLegs`. - [`OrderParams`](https://api-docs.anboto.xyz/reference/schemas/#orderparams): added `timer_iceberg_delay_max` (number), `timer_iceberg_delay_min` (number). Used by `GET /api/v2/trading/order/byId`, `GET /api/v2/trading/order/cancelAll`, `GET /api/v2/trading/order/find`, `GET /api/v2/trading/order/open`, `POST /api/v2/trading/order/create`, `POST /api/v2/trading/order/createMany`. - [`PnlGroup`](https://api-docs.anboto.xyz/reference/schemas/#pnlgroup): added `reconstructed_range` (PnlDateRange); now required: `reconstructed_range`. Used by `GET /api/v2/portfolio/pnl`. - [`PnlPoint`](https://api-docs.anboto.xyz/reference/schemas/#pnlpoint): added `reconstructed` (boolean); now required: `reconstructed`. Used by `GET /api/v2/portfolio/pnl`. - [`PnlSummary`](https://api-docs.anboto.xyz/reference/schemas/#pnlsummary): added `reconstructed_range` (PnlDateRange); now required: `reconstructed_range`. Used by `GET /api/v2/portfolio/pnl`. - [`TradingExchange`](https://api-docs.anboto.xyz/reference/schemas/#tradingexchange): new values `PAPERTRADE`. Used by `GET /api/v2/trading/balance`, `GET /api/v2/trading/margin`, `GET /api/v2/trading/order/byId`, `GET /api/v2/trading/order/cancelAll`, `GET /api/v2/trading/order/find`, `GET /api/v2/trading/order/open` and 6 more. ## v3.22928 — 2026-10-16 Covers releases v3.22713 to v3.22928. New [Portfolio](https://api-docs.anboto.xyz/resources/portfolio/index.md) endpoints report daily PnL, realized PnL/funding/fees by symbol, and deposits, withdrawals and transfers. New order parameters: `timer_iceberg_delay` and `randomize_iceberg_timer` (Iceberg and Scale), `extend_duration` (TWAP, VWAP, IS), and `placement_infos.depth_mode` for placement in basis points from the midpoint (see [Request examples](https://api-docs.anboto.xyz/resources/examples/index.md)). [Get account margin](https://api-docs.anboto.xyz/reference/get-account-margin/index.md) adds the venue's own ratio as `raw_margin_ratio` / `raw_margin_field`. Two behavior changes that the specs do not show: since v3.22713, [Cancel all open orders](https://api-docs.anboto.xyz/reference/cancel-all-open-orders/index.md) needs a key with trade permission and answers `403` to a read-only key, like the other endpoints that create or cancel orders; since v3.22864, a `429` carries a JSON body with `reason` and `retry_after_ms` plus a `Retry-After` header, and the WebSocket connection limit is set per account (see [Rate limits](https://api-docs.anboto.xyz/resources/rate-limits/index.md)). ### REST API **New endpoints** - [`GET /api/v2/portfolio/flows`](https://api-docs.anboto.xyz/reference/flows/index.md) — Returns deposits, withdrawals and internal transfers - [`GET /api/v2/portfolio/pnl`](https://api-docs.anboto.xyz/reference/pnl/index.md) — Returns the daily PnL of the team (NAV based) - [`GET /api/v2/portfolio/pnl/ledger`](https://api-docs.anboto.xyz/reference/ledger/index.md) — Returns realized PnL, funding and fees by day and symbol **Objects** - [`DepthMode`](https://api-docs.anboto.xyz/reference/schemas/#depthmode): new object. Used by `GET /api/v2/trading/order/byId`, `GET /api/v2/trading/order/cancelAll`, `GET /api/v2/trading/order/find`, `GET /api/v2/trading/order/open`, `POST /api/v2/trading/order/create`, `POST /api/v2/trading/order/createMany` and 2 more. - [`FlowRecord`](https://api-docs.anboto.xyz/reference/schemas/#flowrecord): new object. Used by `GET /api/v2/portfolio/flows`. - [`FlowTotals`](https://api-docs.anboto.xyz/reference/schemas/#flowtotals): new object. Used by `GET /api/v2/portfolio/flows`. - [`LedgerCoverage`](https://api-docs.anboto.xyz/reference/schemas/#ledgercoverage): new object. Used by `GET /api/v2/portfolio/pnl/ledger`. - [`LedgerRow`](https://api-docs.anboto.xyz/reference/schemas/#ledgerrow): new object. Used by `GET /api/v2/portfolio/pnl/ledger`. - [`LedgerTotals`](https://api-docs.anboto.xyz/reference/schemas/#ledgertotals): new object. Used by `GET /api/v2/portfolio/pnl/ledger`. - [`PnlGroup`](https://api-docs.anboto.xyz/reference/schemas/#pnlgroup): new object. Used by `GET /api/v2/portfolio/pnl`. - [`PnlGroupKey`](https://api-docs.anboto.xyz/reference/schemas/#pnlgroupkey): new object. Used by `GET /api/v2/portfolio/pnl`. - [`PnlPoint`](https://api-docs.anboto.xyz/reference/schemas/#pnlpoint): new object. Used by `GET /api/v2/portfolio/pnl`. - [`PnlSummary`](https://api-docs.anboto.xyz/reference/schemas/#pnlsummary): new object. Used by `GET /api/v2/portfolio/pnl`. - [`PortfolioAccountRef`](https://api-docs.anboto.xyz/reference/schemas/#portfolioaccountref): new object. Used by `GET /api/v2/portfolio/pnl`. - [`PortfolioFlowsResponse`](https://api-docs.anboto.xyz/reference/schemas/#portfolioflowsresponse): new object. Used by `GET /api/v2/portfolio/flows`. - [`PortfolioLedgerResponse`](https://api-docs.anboto.xyz/reference/schemas/#portfolioledgerresponse): new object. Used by `GET /api/v2/portfolio/pnl/ledger`. - [`PortfolioPnlResponse`](https://api-docs.anboto.xyz/reference/schemas/#portfoliopnlresponse): new object. Used by `GET /api/v2/portfolio/pnl`. - [`AccountMarginResponse`](https://api-docs.anboto.xyz/reference/schemas/#accountmarginresponse): added `raw_margin_field` (string), `raw_margin_ratio` (number/double). Used by `GET /api/v2/trading/margin`. - [`OrderLegParams`](https://api-docs.anboto.xyz/reference/schemas/#orderlegparams): added `extend_duration` (boolean), `randomize_iceberg_timer` (boolean), `timer_iceberg_delay` (number). Used by `POST /api/v2/trading/order/createMany/multilegs`, `POST /api/v2/trading/order/create_multiLegs`. - [`OrderParams`](https://api-docs.anboto.xyz/reference/schemas/#orderparams): added `extend_duration` (boolean), `randomize_iceberg_timer` (boolean), `timer_iceberg_delay` (number). Used by `GET /api/v2/trading/order/byId`, `GET /api/v2/trading/order/cancelAll`, `GET /api/v2/trading/order/find`, `GET /api/v2/trading/order/open`, `POST /api/v2/trading/order/create`, `POST /api/v2/trading/order/createMany`. - [`PlacementInfo`](https://api-docs.anboto.xyz/reference/schemas/#placementinfo): added `depth_mode` (DepthMode). Used by `GET /api/v2/trading/order/byId`, `GET /api/v2/trading/order/cancelAll`, `GET /api/v2/trading/order/find`, `GET /api/v2/trading/order/open`, `POST /api/v2/trading/order/create`, `POST /api/v2/trading/order/createMany` and 2 more. ## v3.22639 — 2026-10-08 New [pre-trade analysis](https://api-docs.anboto.xyz/reference/pre-trade-analysis/index.md) endpoint: estimated cost, market impact and a suggested duration for an order before you send it. POV orders can be placed through the API: `params.pov_ratio` (percent of market volume, 0.01 to 33) is required and `params.pov_risk` is optional; a POV order without a valid `pov_ratio` is rejected with `INVALID_PARAM` (see the [POV example](https://api-docs.anboto.xyz/resources/examples/#pov-percentage-of-volume)). [Get account margin](https://api-docs.anboto.xyz/reference/get-account-margin/index.md) adds a cross-venue margin meter: `remaining_cushion`, `liq_distance`, `vol_cover` with `vol_sigma_window`, and `margin_estimated`. ### REST API **New endpoints** - [`GET /api/v2/data/preTradeAnalysis`](https://api-docs.anboto.xyz/reference/pre-trade-analysis/index.md) — Pre-trade analysis of an order **Objects** - [`PovRisk`](https://api-docs.anboto.xyz/reference/schemas/#povrisk): new object. Used by `GET /api/v2/trading/order/byId`, `GET /api/v2/trading/order/cancelAll`, `GET /api/v2/trading/order/find`, `GET /api/v2/trading/order/open`, `POST /api/v2/trading/order/create`, `POST /api/v2/trading/order/createMany`. - [`PreTradeAdvice`](https://api-docs.anboto.xyz/reference/schemas/#pretradeadvice): new object. Used by `GET /api/v2/data/preTradeAnalysis`. - [`PreTradeAnalysis`](https://api-docs.anboto.xyz/reference/schemas/#pretradeanalysis): new object. Used by `GET /api/v2/data/preTradeAnalysis`. - [`PreTradeCostEstimate`](https://api-docs.anboto.xyz/reference/schemas/#pretradecostestimate): new object. Used by `GET /api/v2/data/preTradeAnalysis`. - [`PreTradeExecution`](https://api-docs.anboto.xyz/reference/schemas/#pretradeexecution): new object. Used by `GET /api/v2/data/preTradeAnalysis`. - [`PreTradeImpact`](https://api-docs.anboto.xyz/reference/schemas/#pretradeimpact): new object. Used by `GET /api/v2/data/preTradeAnalysis`. - [`PreTradeImpactModel`](https://api-docs.anboto.xyz/reference/schemas/#pretradeimpactmodel): new object. Used by `GET /api/v2/data/preTradeAnalysis`. - [`PreTradeMarket`](https://api-docs.anboto.xyz/reference/schemas/#pretrademarket): new object. Used by `GET /api/v2/data/preTradeAnalysis`. - [`PreTradePov`](https://api-docs.anboto.xyz/reference/schemas/#pretradepov): new object. Used by `GET /api/v2/data/preTradeAnalysis`. - [`PreTradeThresholds`](https://api-docs.anboto.xyz/reference/schemas/#pretradethresholds): new object. Used by `GET /api/v2/data/preTradeAnalysis`. - [`AccountMarginResponse`](https://api-docs.anboto.xyz/reference/schemas/#accountmarginresponse): added `liq_distance` (number/double), `margin_estimated` (boolean), `remaining_cushion` (number/double), `vol_cover` (number/double), `vol_sigma_window` (string). Used by `GET /api/v2/trading/margin`. - [`OrderParams`](https://api-docs.anboto.xyz/reference/schemas/#orderparams): added `pov_ratio` (number), `pov_risk` (PovRisk). Used by `GET /api/v2/trading/order/byId`, `GET /api/v2/trading/order/cancelAll`, `GET /api/v2/trading/order/find`, `GET /api/v2/trading/order/open`, `POST /api/v2/trading/order/create`, `POST /api/v2/trading/order/createMany`. ## v3.22428 — 2026-09-29 First entry. Covers everything published since the documentation moved to this site on 2026-08-31: a new account margin endpoint, parent-order fields on order responses, fills on order endpoints, and documented subscribe/unsubscribe operations for every WebSocket topic. The `TradeDetails` renames and the `trade_id` type are documentation corrections: the API already returned these fields this way. See [CH-003](https://api-docs.anboto.xyz/change-notices/#ch-003-trade-fill-schema-corrected). ### REST API **New endpoints** - [`GET /api/v2/trading/margin`](https://api-docs.anboto.xyz/reference/get-account-margin/index.md) — Returns the margin and equity summary of a futures account on an exchange **Query parameters** - [`GET /api/v2/trading/order/find`](https://api-docs.anboto.xyz/reference/find-orders/index.md): added `include_fees`, `include_trades` - [`GET /api/v2/trading/order/open`](https://api-docs.anboto.xyz/reference/get-open-orders/index.md): added `include_fees`, `include_trades` **Objects** - [`AccountMarginResponse`](https://api-docs.anboto.xyz/reference/schemas/#accountmarginresponse): new object. Used by `GET /api/v2/trading/margin`. - [`ExchangeCode`](https://api-docs.anboto.xyz/reference/schemas/#exchangecode): new object. Used by `GET /api/v2/data/instruments`. - [`CreateParentOrderRequest`](https://api-docs.anboto.xyz/reference/schemas/#createparentorderrequest): added `limit_is_arrival` (boolean). Used by `POST /api/v2/trading/order/create`, `POST /api/v2/trading/order/createMany`. - [`Instrument`](https://api-docs.anboto.xyz/reference/schemas/#instrument): `exchange` is now ExchangeCode (was Exchange_1). Used by `GET /api/v2/data/instruments`. - [`OrderDetails`](https://api-docs.anboto.xyz/reference/schemas/#orderdetails): added `clip_size_type` (ClipSizeType), `clip_size_val` (number), `limit_price` (number), `params` (OrderParams), `progress` (number), `quantity` (number), `target_value` (number). Used by `GET /api/v2/trading/order/byId`, `GET /api/v2/trading/order/cancelAll`, `GET /api/v2/trading/order/find`, `GET /api/v2/trading/order/open`. - [`OrderParams`](https://api-docs.anboto.xyz/reference/schemas/#orderparams): added `limit_bps` (string), `limit_is_arrival` (boolean); removed `post_only`. Used by `GET /api/v2/trading/order/byId`, `GET /api/v2/trading/order/cancelAll`, `GET /api/v2/trading/order/find`, `GET /api/v2/trading/order/open`, `POST /api/v2/trading/order/create`, `POST /api/v2/trading/order/createMany`. - [`TradeDetails`](https://api-docs.anboto.xyz/reference/schemas/#tradedetails): added `child_order_id` (integer/int64), `parent_order_id` (integer/int64); renamed `clientOrderId` → `client_order_id`, `exchangeOrderId` → `exchange_order_id`, `execTime` → `exec_time`, `feeCurrency` → `fee_currency`, `makerOrTaker` → `maker_or_taker`; `direction`: new values `BUY`, `SELL`; `trade_id` is now string (was integer/int64). Used by `GET /api/v2/trading/order/byId`, `GET /api/v2/trading/order/cancelAll`, `GET /api/v2/trading/order/find`, `GET /api/v2/trading/order/open`, `GET /api/v2/trading/userTrades`. - [`TradingExchange`](https://api-docs.anboto.xyz/reference/schemas/#tradingexchange): new values `KRAKEN`. Used by `GET /api/v2/trading/balance`, `GET /api/v2/trading/margin`, `GET /api/v2/trading/order/byId`, `GET /api/v2/trading/order/cancelAll`, `GET /api/v2/trading/order/find`, `GET /api/v2/trading/order/open` and 6 more. - [`WouldInfo`](https://api-docs.anboto.xyz/reference/schemas/#wouldinfo): added `would_bps` (string). Used by `GET /api/v2/trading/order/byId`, `GET /api/v2/trading/order/cancelAll`, `GET /api/v2/trading/order/find`, `GET /api/v2/trading/order/open`, `POST /api/v2/trading/order/create`, `POST /api/v2/trading/order/createMany` and 2 more. - `Exchange_1`: removed. ### WebSocket API - New messages: `subscribeChildOrder`, `subscribeOhlcv`, `subscribeOpenInterest`, `subscribePositionRisk`, `subscribeTicker`, `unsubscribeChildOrder`, `unsubscribeOhlcv`, `unsubscribeOpenInterest`, `unsubscribePositionRisk`, `unsubscribeTicker` - 15 subscribe/unsubscribe operations now documented # Change notices Numbered notices for changes that can affect API integrations. Breaking changes get a notice **before** rollout; subscribe by watching this page (every page also has a Markdown twin — append `.md` to its URL). | Notice | Date | Type | Summary | | ------ | ---------- | ---------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | CH-003 | 2026-09-29 | Correction | Trade fill objects (`TradeDetails`) were mis-documented: fields are snake_case on the wire, `trade_id` is a string, `direction` is `BUY`/`SELL`. Documentation fix only — no API behavior change. New optional fields `parent_order_id`, `child_order_id`. | | CH-002 | 2026-05 | Breaking | `api.trade.anboto.xyz` retired. Production REST and WebSocket hosts are `api.pro.anboto.xyz` / `wss://api.pro.anboto.xyz/api/v2/ws`. | | CH-001 | 2026-08-31 | Info | API documentation moved to this site (api-docs.anboto.xyz). The former GitHub Pages site remains available during the transition; specs and content are identical. No API behavior change. | ## CH-003 — Trade fill schema corrected **Type:** correction · **Date:** 2026-09-29 The `TradeDetails` object (fills inside orders from `order/open`, `order/byId`, `order/find`, `order/cancelAll`, and in `userTrades`) was documented with the wrong field names and types. The API itself did not change; only the documentation now matches what the server has always returned: | Documented before | Actually returned (now documented) | | ----------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------- | | `clientOrderId`, `exchangeOrderId`, `execTime`, `makerOrTaker`, `feeCurrency` | `client_order_id`, `exchange_order_id`, `exec_time`, `maker_or_taker`, `fee_currency` | | `trade_id` as integer | `trade_id` as string (the exchange trade id, or the Anboto trade id when none was captured) | | `direction` free text | `direction` is `BUY` or `SELL`; `maker_or_taker` is `MAKER` or `TAKER` | New optional fields: `parent_order_id` (the enclosing order) and `child_order_id` (the slice that executed; the WebSocket `trade` topic carries it as `order_id`). If your client was generated from the old OpenAPI file, regenerate it from the current [spec](https://api-docs.anboto.xyz/spec/anboto-trading-api-2.0.yml). ## CH-002 — `api.trade.anboto.xyz` retired **Type:** breaking · **Date:** May 2026 The legacy production host `api.trade.anboto.xyz` no longer resolves. Point REST calls at `https://api.pro.anboto.xyz` and WebSocket connections at `wss://api.pro.anboto.xyz/api/v2/ws`. Paths, authentication and signing are unchanged — the host is the only difference. Testnet (`api.testnet.anboto.xyz`) is unaffected. ## CH-001 — Documentation site migration **Type:** informational · **Date:** 2026-08-31 API docs now live at `api-docs.anboto.xyz`, generated directly from the OpenAPI/AsyncAPI specs. The GitHub Pages site (`anbotolabs.github.io/anboto-api-docs`) stays online until cutover completes, then redirects here. Spec URLs on this site: [OpenAPI](https://api-docs.anboto.xyz/spec/anboto-trading-api-2.0.yml) · [AsyncAPI](https://api-docs.anboto.xyz/spec/asynapi.yml). No endpoint, auth, or schema change. # API Reference — Anboto Trading API v2.0 [Download OpenAPI spec](https://api-docs.anboto.xyz/spec/anboto-trading-api-2.0.yml) · [AsyncAPI (WebSocket) spec](https://api-docs.anboto.xyz/spec/asynapi.yml) ## Authentication Endpoints marked **ApiKeyAuth** need four headers on every request: | Header | | | | --------------- | -------- | -------------------------------------- | | `X-API-KEY` | required | your API key | | `X-TIMESTAMP` | required | milliseconds since epoch | | `X-SIGN` | required | signature, standard Base64 | | `X-RECV-WINDOW` | | request validity in ms, default `5000` | **Signing.** Build `timestamp + api_key + recv_window + (queryString | jsonBody)` — query string in alphabetical key order, exactly as sent. Base64-decode the secret (standard Base64 if it contains `+`, `/` or ends with `=`, otherwise URL-safe). Sign with HMAC-SHA256 (system-generated keys) or RSA-SHA256 (self-generated keys). `X-SIGN` is the standard Base64 of the signature, not hex. Keys: [pro.anboto.xyz/settings/api](https://pro.anboto.xyz/settings/api). Every sample on this site calls `signed_headers(body)` / `signed_headers_query(params)` — the helper for each language, HMAC variant: ``` BASE=https://api.pro.anboto.xyz # signed_headers "" -> prints curl -H flags signed_headers() { local ts=$(($(date +%s) * 1000)) local key_hex=$(printf '%s' "$API_SECRET" | base64 -d | xxd -p -c 256) local sign=$(printf '%s' "${ts}${API_KEY}5000$1" \ | openssl dgst -sha256 -mac HMAC -macopt "hexkey:$key_hex" -binary | base64) printf -- '-H "X-API-KEY: %s" -H "X-TIMESTAMP: %s" -H "X-RECV-WINDOW: 5000" -H "X-SIGN: %s"' \ "$API_KEY" "$ts" "$sign" } # GET: curl "$BASE/api/v2/trading/balance?exchange=BINANCE" $(signed_headers "exchange=BINANCE") # POST: curl -X POST "$BASE/api/v2/trading/order/create" $(signed_headers "$body") \ # -H "Content-Type: application/json" -d "$body" ``` ``` import base64, hashlib, hmac, json, time import requests BASE = "https://api.pro.anboto.xyz" RECV_WINDOW = "5000" def _secret_bytes(secret: str) -> bytes: if any(c in secret for c in "+/") or secret.endswith("="): return base64.b64decode(secret) return base64.urlsafe_b64decode(secret + "=" * (-len(secret) % 4)) def _headers(payload: str) -> dict: ts = str(int(time.time() * 1000)) digest = hmac.new(_secret_bytes(API_SECRET), (ts + API_KEY + RECV_WINDOW + payload).encode(), hashlib.sha256).digest() return {"X-API-KEY": API_KEY, "X-TIMESTAMP": ts, "X-RECV-WINDOW": RECV_WINDOW, "X-SIGN": base64.b64encode(digest).decode()} def signed_headers(body: dict) -> dict: # POST: sign the JSON body you send return {**_headers(json.dumps(body)), "Content-Type": "application/json"} def signed_headers_query(params: dict) -> dict: # GET: sign the sorted query string return _headers("&".join(f"{k}={v}" for k, v in sorted(params.items()))) ``` ``` use base64::{engine::general_purpose::STANDARD, Engine}; use hmac::{Hmac, Mac}; use reqwest::header::HeaderMap; use sha2::Sha256; const BASE: &str = "https://api.pro.anboto.xyz"; fn headers(payload: &str) -> HeaderMap { let ts = chrono::Utc::now().timestamp_millis().to_string(); let key = STANDARD.decode(std::env::var("API_SECRET").unwrap()).unwrap(); let mut mac = Hmac::::new_from_slice(&key).unwrap(); mac.update(format!("{ts}{}5000{payload}", std::env::var("API_KEY").unwrap()).as_bytes()); let sign = STANDARD.encode(mac.finalize().into_bytes()); let mut h = HeaderMap::new(); h.insert("X-API-KEY", std::env::var("API_KEY").unwrap().parse().unwrap()); h.insert("X-TIMESTAMP", ts.parse().unwrap()); h.insert("X-RECV-WINDOW", "5000".parse().unwrap()); h.insert("X-SIGN", sign.parse().unwrap()); h } fn signed_headers(payload: &serde_json::Value) -> HeaderMap { headers(&payload.to_string()) } fn signed_headers_query(params: &std::collections::BTreeMap<&str, &str>) -> HeaderMap { headers(¶ms.iter().map(|(k, v)| format!("{k}={v}")).collect::>().join("&")) } ``` ``` const BASE = "https://api.pro.anboto.xyz" func headers(payload string) map[string]string { ts := strconv.FormatInt(time.Now().UnixMilli(), 10) key, _ := base64.StdEncoding.DecodeString(os.Getenv("API_SECRET")) mac := hmac.New(sha256.New, key) mac.Write([]byte(ts + os.Getenv("API_KEY") + "5000" + payload)) return map[string]string{ "X-API-KEY": os.Getenv("API_KEY"), "X-TIMESTAMP": ts, "X-RECV-WINDOW": "5000", "X-SIGN": base64.StdEncoding.EncodeToString(mac.Sum(nil)), } } func signedHeaders(body string) map[string]string { return headers(body) } func signedHeadersQuery(q url.Values) map[string]string { keys := make([]string, 0, len(q)) for k := range q { keys = append(keys, k) } sort.Strings(keys) parts := make([]string, 0, len(keys)) for _, k := range keys { parts = append(parts, k+"="+q.Get(k)) } return headers(strings.Join(parts, "&")) } ``` ``` static final String BASE = "https://api.pro.anboto.xyz"; static HttpRequest.Builder signed(String path, String payload) throws Exception { String ts = Long.toString(System.currentTimeMillis()); Mac mac = Mac.getInstance("HmacSHA256"); mac.init(new SecretKeySpec(Base64.getDecoder().decode(apiSecret), "HmacSHA256")); String sign = Base64.getEncoder().encodeToString( mac.doFinal((ts + apiKey + "5000" + payload).getBytes(StandardCharsets.UTF_8))); return HttpRequest.newBuilder(URI.create(BASE + path)) .header("X-API-KEY", apiKey).header("X-TIMESTAMP", ts) .header("X-RECV-WINDOW", "5000").header("X-SIGN", sign); } static HttpRequest signedPost(String path, String jsonBody) throws Exception { return signed(path, jsonBody).header("Content-Type", "application/json") .POST(HttpRequest.BodyPublishers.ofString(jsonBody)).build(); } static HttpRequest signedGet(String pathWithQuery) throws Exception { // query keys sorted String query = pathWithQuery.contains("?") ? pathWithQuery.substring(pathWithQuery.indexOf('?') + 1) : ""; return signed(pathWithQuery, query).GET().build(); } ``` ``` import { createHmac } from "node:crypto"; const BASE = "https://api.pro.anboto.xyz"; function headers(payload: string): Record { const ts = Date.now().toString(); const sign = createHmac("sha256", Buffer.from(process.env.API_SECRET!, "base64")) .update(ts + process.env.API_KEY + "5000" + payload).digest("base64"); return { "X-API-KEY": process.env.API_KEY!, "X-TIMESTAMP": ts, "X-RECV-WINDOW": "5000", "X-SIGN": sign }; } export const signedHeaders = (body: unknown) => ({ ...headers(JSON.stringify(body)), "Content-Type": "application/json" }); export const signedHeadersQuery = (params: Record) => headers(Object.keys(params).sort().map((k) => `${k}=${params[k]}`).join("&")); ``` ``` const val BASE = "https://api.pro.anboto.xyz" fun signed(path: String, payload: String): HttpRequest.Builder { val ts = System.currentTimeMillis().toString() val mac = Mac.getInstance("HmacSHA256").apply { init(SecretKeySpec(Base64.getDecoder().decode(apiSecret), "HmacSHA256")) } val sign = Base64.getEncoder().encodeToString(mac.doFinal((ts + apiKey + "5000" + payload).toByteArray())) return HttpRequest.newBuilder(URI.create(BASE + path)) .header("X-API-KEY", apiKey).header("X-TIMESTAMP", ts) .header("X-RECV-WINDOW", "5000").header("X-SIGN", sign) } fun signedPost(path: String, jsonBody: String): HttpRequest = signed(path, jsonBody).header("Content-Type", "application/json") .POST(HttpRequest.BodyPublishers.ofString(jsonBody)).build() fun signedGet(pathWithQuery: String): HttpRequest = // query keys sorted signed(pathWithQuery, pathWithQuery.substringAfter('?', "")).GET().build() ``` ``` const std::string BASE = "https://api.pro.anboto.xyz"; cpr::Header headers(const std::string& payload) { std::string ts = std::to_string(std::chrono::duration_cast( std::chrono::system_clock::now().time_since_epoch()).count()); std::string key = base64_decode(std::getenv("API_SECRET")); std::string msg = ts + std::getenv("API_KEY") + "5000" + payload; unsigned char digest[EVP_MAX_MD_SIZE]; unsigned int len = 0; HMAC(EVP_sha256(), key.data(), key.size(), reinterpret_cast(msg.data()), msg.size(), digest, &len); return cpr::Header{{"X-API-KEY", std::getenv("API_KEY")}, {"X-TIMESTAMP", ts}, {"X-RECV-WINDOW", "5000"}, {"X-SIGN", base64_encode(digest, len)}}; } cpr::Header signedHeaders(const std::string& body) { return headers(body); } cpr::Header signedHeadersQuery(const std::map& params) { // std::map = sorted std::string qs; for (auto& [k, v] : params) qs += (qs.empty() ? "" : "&") + k + "=" + v; return headers(qs); } ``` ``` import { createHmac } from "node:crypto"; const BASE = "https://api.pro.anboto.xyz"; function headers(payload) { const ts = Date.now().toString(); const sign = createHmac("sha256", Buffer.from(process.env.API_SECRET, "base64")) .update(ts + process.env.API_KEY + "5000" + payload).digest("base64"); return { "X-API-KEY": process.env.API_KEY, "X-TIMESTAMP": ts, "X-RECV-WINDOW": "5000", "X-SIGN": sign }; } export const signedHeaders = (body) => ({ ...headers(JSON.stringify(body)), "Content-Type": "application/json" }); export const signedHeadersQuery = (params) => headers(Object.keys(params).sort().map((k) => `${k}=${params[k]}`).join("&")); ``` Ready-made payloads: [Request examples](https://api-docs.anboto.xyz/resources/examples/index.md). Full clients: [github.com/anbotolabs/examples](https://github.com/anbotolabs/examples). ## Trading | | Endpoint | | | ---- | -------------------------------------------- | ------------------------------------------------------------------------------------------------------------- | | GET | `/api/v2/trading/balance` | [Get balance](https://api-docs.anboto.xyz/reference/get-balance/index.md) | | GET | `/api/v2/trading/listenKey` | [Listen key](https://api-docs.anboto.xyz/reference/listen-key/index.md) | | GET | `/api/v2/trading/margin` | [Get account margin](https://api-docs.anboto.xyz/reference/get-account-margin/index.md) | | GET | `/api/v2/trading/order/byId` | [Get orders](https://api-docs.anboto.xyz/reference/get-orders/index.md) | | POST | `/api/v2/trading/order/cancel` | [Cancel order](https://api-docs.anboto.xyz/reference/cancel-order/index.md) | | GET | `/api/v2/trading/order/cancelAll` | [Cancel all open orders](https://api-docs.anboto.xyz/reference/cancel-all-open-orders/index.md) | | POST | `/api/v2/trading/order/cancelMany` | [Cancel many](https://api-docs.anboto.xyz/reference/cancel-many/index.md) | | POST | `/api/v2/trading/order/create` | [Create order](https://api-docs.anboto.xyz/reference/create-order/index.md) | | POST | `/api/v2/trading/order/createMany` | [Create many orders](https://api-docs.anboto.xyz/reference/create-many-orders/index.md) | | POST | `/api/v2/trading/order/create_multiLegs` | [Create multi legs order](https://api-docs.anboto.xyz/reference/create-multi-legs-order/index.md) | | POST | `/api/v2/trading/order/createMany/multilegs` | [Create many multi legs orders](https://api-docs.anboto.xyz/reference/create-many-multi-legs-orders/index.md) | | GET | `/api/v2/trading/order/find` | [Find orders](https://api-docs.anboto.xyz/reference/find-orders/index.md) | | GET | `/api/v2/trading/order/open` | [Get open orders](https://api-docs.anboto.xyz/reference/get-open-orders/index.md) | | GET | `/api/v2/trading/position` | [Get position](https://api-docs.anboto.xyz/reference/get-position/index.md) | | GET | `/api/v2/trading/userTrades` | [Get user trades](https://api-docs.anboto.xyz/reference/get-user-trades/index.md) | ## Market data | | Endpoint | | | --- | --------------------------------- | ------------------------------------------------------------------------------------------- | | GET | `/api/v2/data/exchanges` | [Exchanges](https://api-docs.anboto.xyz/reference/exchanges/index.md) | | GET | `/api/v2/data/fundingRateHistory` | [Funding rate history](https://api-docs.anboto.xyz/reference/funding-rate-history/index.md) | | GET | `/api/v2/data/instruments` | [Instruments](https://api-docs.anboto.xyz/reference/instruments/index.md) | | GET | `/api/v2/data/lastFundingRates` | [Last funding rates](https://api-docs.anboto.xyz/reference/last-funding-rates/index.md) | | GET | `/api/v2/data/preTradeAnalysis` | [Pre trade analysis](https://api-docs.anboto.xyz/reference/pre-trade-analysis/index.md) | ## Portfolio | | Endpoint | | | --- | ------------------------------ | --------------------------------------------------------------- | | GET | `/api/v2/portfolio/flows` | [Flows](https://api-docs.anboto.xyz/reference/flows/index.md) | | GET | `/api/v2/portfolio/pnl` | [Pnl](https://api-docs.anboto.xyz/reference/pnl/index.md) | | GET | `/api/v2/portfolio/pnl/ledger` | [Ledger](https://api-docs.anboto.xyz/reference/ledger/index.md) | ## Status | | Endpoint | | | --- | -------------- | --------------------------------------------------------------- | | GET | `/status/ping` | [Status](https://api-docs.anboto.xyz/reference/status/index.md) | ## Strategies Rest API | | Endpoint | | | ---- | ------------------------------------- | --------------------------------------------------------------------- | | GET | `/api/v2/strategies/campaigns` | [Campaigns](https://api-docs.anboto.xyz/reference/campaigns/index.md) | | GET | `/api/v2/strategies/campaigns/byId` | [By id](https://api-docs.anboto.xyz/reference/by-id/index.md) | | POST | `/api/v2/strategies/campaigns/create` | [Create](https://api-docs.anboto.xyz/reference/create/index.md) | | POST | `/api/v2/strategies/campaigns/kill` | [Kill](https://api-docs.anboto.xyz/reference/kill/index.md) | | POST | `/api/v2/strategies/campaigns/pause` | [Pause](https://api-docs.anboto.xyz/reference/pause/index.md) | | POST | `/api/v2/strategies/campaigns/resume` | [Resume](https://api-docs.anboto.xyz/reference/resume/index.md) | | POST | `/api/v2/strategies/campaigns/stop` | [Stop](https://api-docs.anboto.xyz/reference/stop/index.md) | ## WebSocket streams [WebSocket overview](https://api-docs.anboto.xyz/reference/ws-index/index.md) — endpoints, listenKey auth, keep-alive, subscribe format. | | Topic | | | --- | ------------------------ | -------------------------------------------------------------------------------------- | | WS | `position` | [position](https://api-docs.anboto.xyz/reference/ws-position/index.md) | | WS | `balance` | [balance](https://api-docs.anboto.xyz/reference/ws-balance/index.md) | | WS | `order` | [order](https://api-docs.anboto.xyz/reference/ws-order/index.md) | | WS | `trade` | [trade](https://api-docs.anboto.xyz/reference/ws-trade/index.md) | | WS | `child_order` | [child_order](https://api-docs.anboto.xyz/reference/ws-child-order/index.md) | | WS | `position_risk` | [position_risk](https://api-docs.anboto.xyz/reference/ws-position-risk/index.md) | | WS | `ticker` | [ticker](https://api-docs.anboto.xyz/reference/ws-ticker/index.md) | | WS | `ohlcv` | [ohlcv](https://api-docs.anboto.xyz/reference/ws-ohlcv/index.md) | | WS | `open_interest` | [open_interest](https://api-docs.anboto.xyz/reference/ws-open-interest/index.md) | | WS | `Keep-alive (ping/pong)` | [Keep-alive (ping/pong)](https://api-docs.anboto.xyz/reference/ws-keep-alive/index.md) | ## Schemas All request/response objects: [Schemas](https://api-docs.anboto.xyz/reference/schemas/index.md) # By id GET `https://api.pro.anboto.xyz/api/v2/strategies/campaigns/byId` Get one campaign **ApiKeyAuth** required. ### Query params `campaignId` string required The campaign's id (UUID) ### Headers | Header | | | | --------------- | ----------------- | -------- | | `X-API-KEY` | string | required | | `X-TIMESTAMP` | int64 ms | required | | `X-SIGN` | string | required | | `X-RECV-WINDOW` | int, default 5000 | | ### Responses | | | | --- | --------------------------------------------------------------------- | | 200 | The campaign | | 400 | campaignId is not a valid id, `{"code", "error", "errors"?}` | | 401 | Unauthorized: missing or unknown API key | | 404 | No such campaign on this account, `{"code", "error", "errors"?}` | | 429 | Rate limit exceeded, retry later, `{"code", "error", "errors"?}` | | 503 | The strategies service is unavailable, `{"code", "error", "errors"?}` | ### Response fields — [StrategyCampaign](https://api-docs.anboto.xyz/reference/schemas/#strategycampaign) `id` string Campaign id (UUID) `type` string Campaign type; today always paper_farm `status` enum running | paused | stopped | done | error — `running`, `paused`, `stopped`, `done`, `error` `stopping` boolean A graceful stop or a hard kill is under way. Independent of status: can be true while status stays error (the open legs are being closed before the campaign reaches stopped) `phase` string Cycle phase the runner is in: idle, opening, open, closing or settling `stop_reason` string Why a stopped/done campaign ended: cycles_done, budget_spent, session_key_expiring, queued_share, user_stop or user_kill. Empty while still running `cycles_done` integer Cycles completed so far `cycles_planned` integer max_cycles from create, or null for unlimited `paper_minted` number Total PAPER minted by this campaign's losing legs `usdc_converted` number Total USDC spent converting minted PAPER (haircut + fee) `queued_usdc` number Profit queued to fund a future cycle's margin instead of being paid out `haircut_paid` number Total haircut paid converting PAPER to USDC `fees_paid` number Total trading fees paid by this campaign `current_legs` array\[[StrategyCampaignLeg](https://api-docs.anboto.xyz/reference/schemas/#strategycampaignleg)\] Open legs of the current cycle (0 while idle, up to 2 while open) `current_legs[].position_id` string The venue's position id, or null while the open is still unconfirmed `current_legs[].side` string long or short `current_legs[].entry` number Entry (mark) price the leg opened at `current_legs[].move_pct` number Signed move since entry, in percent, from this leg's point of view `current_legs[].bust` number This leg's liquidation (bust) price `current_legs[].size` number Position size `current_legs[].margin` number Margin posted for this leg, in USDC `current_legs[].leverage` integer Leverage of this leg `current_legs[].mark_price` number Latest mark price used to watch this leg `current_legs[].parent_order_id` string The order id that opened this leg `current_legs[].opened_at` date-time UTC time the leg opened, ISO 8601 `last_cycle` [StrategyCampaignCycle](https://api-docs.anboto.xyz/reference/schemas/#strategycampaigncycle) The campaign's most recently closed cycle `last_cycle.pnl_usdc` number Net result of the cycle, in USDC (can be negative) `last_cycle.paper` number PAPER minted by the losing leg of this cycle `last_cycle.closed_at` date-time UTC time both legs were closed, ISO 8601 `last_cycle.multileg_order_id` string The multileg (or paired single) order id the close went through, when known `last_error` string Why the campaign is in error; empty otherwise `symbol` string Anboto symbol being farmed, e.g. BTC/USDC:USDC `leverage` integer Leverage of each leg `margin_per_leg` number Margin posted per leg at the start of a cycle, in USDC `target_move_bps` integer Winning-leg move, in basis points, that closes the cycle `budget_usdc` number budget_usdc from create, or null for no spend cap `stop` [StrategyStopRules](https://api-docs.anboto.xyz/reference/schemas/#strategystoprules) Stop conditions the campaign watches on its own, besides an explicit stop/kill `stop.queued_share_pct` number Stop once this percent (0-100) of a new cycle's margin would come from queued profit rather than fresh budget. Null or omitted: off `stop.stop_before_key_expiry` boolean Stop gracefully once the Papertrade session key has under an hour left, rather than risk a cycle stuck open past expiry Default: `true` `stop.hard_kill_on_stop` boolean If a stop rule fires mid-cycle, close both legs at market now instead of waiting for the target Default: `false` `created_at` date-time UTC time the campaign was created, ISO 8601 `started_at` date-time UTC time the campaign started, ISO 8601 `stopped_at` date-time UTC time the campaign stopped, ISO 8601, or null while still running ``` curl -X GET "$BASE/api/v2/strategies/campaigns/byId?campaignId=string" \ -H "X-API-KEY: $API_KEY" -H "X-TIMESTAMP: $ts" \ -H "X-SIGN: $sign" ``` ``` params = {"campaignId": ...} r = requests.get(f"{BASE}/api/v2/strategies/campaigns/byId", params=params headers=signed_headers_query(params)) print(r.json()) ``` ``` let resp = client .get(format!("{BASE}/api/v2/strategies/campaigns/byId?campaignId=string")) .headers(signed_headers_query(¶ms)) .send()?; println!("{}", resp.text()?); ``` ``` req, _ := http.NewRequest("GET", BASE+"/api/v2/strategies/campaigns/byId?campaignId=string", nil) for k, v := range signedHeadersQuery(req.URL.Query()) { req.Header.Set(k, v) } resp, err := http.DefaultClient.Do(req) if err != nil { log.Fatal(err) } defer resp.Body.Close() io.Copy(os.Stdout, resp.Body) ``` ``` HttpResponse resp = client.send( signedGet("/api/v2/strategies/campaigns/byId?campaignId=string"), HttpResponse.BodyHandlers.ofString()); ``` ``` const res = await fetch(`${BASE}/api/v2/strategies/campaigns/byId?campaignId=string`, { method: "GET", headers: signedHeadersQuery(params), }); const data: StrategyCampaign = await res.json(); ``` ``` val request = signedGet("/api/v2/strategies/campaigns/byId?campaignId=string") val response = client.send(request, HttpResponse.BodyHandlers.ofString()) println(response.body()) ``` ``` cpr::Response r = cpr::Get( cpr::Url{BASE + "/api/v2/strategies/campaigns/byId?campaignId=string"}, signedHeadersQuery(params)); std::cout << r.text << std::endl; ``` ``` const res = await fetch(`${BASE}/api/v2/strategies/campaigns/byId?campaignId=string`, { method: "GET", headers: signedHeadersQuery(params), }); console.log(await res.json()); ``` **Response** 200 ``` { "id": "string", "type": "string", "status": "running", "stopping": true, "phase": "string", "stop_reason": "string", "cycles_done": 0, "cycles_planned": 0, "paper_minted": 0.0, "usdc_converted": 0.0, "queued_usdc": 0.0, "haircut_paid": 0.0, "fees_paid": 0.0, "current_legs": [ { "position_id": "string", "side": "string", "entry": 0.0, "move_pct": 0.0, "bust": 0.0, "size": 0.0, "margin": 0.0, "leverage": 0, "mark_price": 0.0, "parent_order_id": "string", "opened_at": "string" } ], "last_cycle": { "pnl_usdc": 0.0, "paper": 0.0, "closed_at": "string", "multileg_order_id": "string" }, "last_error": "string", "symbol": "string", "leverage": 0, "margin_per_leg": 0.0, "target_move_bps": 0, "budget_usdc": 0.0, "stop": { "queued_share_pct": 0.0, "stop_before_key_expiry": true, "hard_kill_on_stop": true }, "created_at": "string", "started_at": "string", "stopped_at": "string" } ``` # Campaigns GET `https://api.pro.anboto.xyz/api/v2/strategies/campaigns` Newest first. `status` uses the public values this API reports, not the internal ones. **ApiKeyAuth** required. ### Query params `type` string Only this campaign type; today only paper_farm `status` enum Only this status — `running`, `paused`, `stopped`, `done`, `error` `limit` integer Campaigns per page, 1-200 (default 20) Default: `20` `offset` integer Campaigns to skip (default 0) Default: `0` ### Headers | Header | | | | --------------- | ----------------- | -------- | | `X-API-KEY` | string | required | | `X-TIMESTAMP` | int64 ms | required | | `X-SIGN` | string | required | | `X-RECV-WINDOW` | int, default 5000 | | ### Responses | | | | --- | --------------------------------------------------------------------- | | 200 | A page of campaigns | | 401 | Unauthorized: missing or unknown API key | | 429 | Rate limit exceeded, retry later, `{"code", "error", "errors"?}` | | 503 | The strategies service is unavailable, `{"code", "error", "errors"?}` | ### Response fields — [StrategyCampaignList](https://api-docs.anboto.xyz/reference/schemas/#strategycampaignlist) `count` integer Total campaigns matching the filter, across every page `campaigns` array\[[StrategyCampaign](https://api-docs.anboto.xyz/reference/schemas/#strategycampaign)\] required This page's campaigns, newest first `campaigns[].id` string Campaign id (UUID) `campaigns[].type` string Campaign type; today always paper_farm `campaigns[].status` enum running | paused | stopped | done | error — `running`, `paused`, `stopped`, `done`, `error` `campaigns[].stopping` boolean A graceful stop or a hard kill is under way. Independent of status: can be true while status stays error (the open legs are being closed before the campaign reaches stopped) `campaigns[].phase` string Cycle phase the runner is in: idle, opening, open, closing or settling `campaigns[].stop_reason` string Why a stopped/done campaign ended: cycles_done, budget_spent, session_key_expiring, queued_share, user_stop or user_kill. Empty while still running `campaigns[].cycles_done` integer Cycles completed so far `campaigns[].cycles_planned` integer max_cycles from create, or null for unlimited `campaigns[].paper_minted` number Total PAPER minted by this campaign's losing legs `campaigns[].usdc_converted` number Total USDC spent converting minted PAPER (haircut + fee) `campaigns[].queued_usdc` number Profit queued to fund a future cycle's margin instead of being paid out `campaigns[].haircut_paid` number Total haircut paid converting PAPER to USDC `campaigns[].fees_paid` number Total trading fees paid by this campaign `campaigns[].current_legs` array\[[StrategyCampaignLeg](https://api-docs.anboto.xyz/reference/schemas/#strategycampaignleg)\] Open legs of the current cycle (0 while idle, up to 2 while open) `campaigns[].current_legs[].position_id` string The venue's position id, or null while the open is still unconfirmed `campaigns[].current_legs[].side` string long or short `campaigns[].current_legs[].entry` number Entry (mark) price the leg opened at `campaigns[].current_legs[].move_pct` number Signed move since entry, in percent, from this leg's point of view `campaigns[].current_legs[].bust` number This leg's liquidation (bust) price `campaigns[].current_legs[].size` number Position size `campaigns[].current_legs[].margin` number Margin posted for this leg, in USDC `campaigns[].current_legs[].leverage` integer Leverage of this leg `campaigns[].current_legs[].mark_price` number Latest mark price used to watch this leg `campaigns[].current_legs[].parent_order_id` string The order id that opened this leg `campaigns[].current_legs[].opened_at` date-time UTC time the leg opened, ISO 8601 `campaigns[].last_cycle` [StrategyCampaignCycle](https://api-docs.anboto.xyz/reference/schemas/#strategycampaigncycle) The campaign's most recently closed cycle `campaigns[].last_error` string Why the campaign is in error; empty otherwise `campaigns[].symbol` string Anboto symbol being farmed, e.g. BTC/USDC:USDC `campaigns[].leverage` integer Leverage of each leg `campaigns[].margin_per_leg` number Margin posted per leg at the start of a cycle, in USDC `campaigns[].target_move_bps` integer Winning-leg move, in basis points, that closes the cycle `campaigns[].budget_usdc` number budget_usdc from create, or null for no spend cap `campaigns[].stop` [StrategyStopRules](https://api-docs.anboto.xyz/reference/schemas/#strategystoprules) Stop conditions the campaign watches on its own, besides an explicit stop/kill `campaigns[].created_at` date-time UTC time the campaign was created, ISO 8601 `campaigns[].started_at` date-time UTC time the campaign started, ISO 8601 `campaigns[].stopped_at` date-time UTC time the campaign stopped, ISO 8601, or null while still running ``` curl -X GET "$BASE/api/v2/strategies/campaigns?type=string" \ -H "X-API-KEY: $API_KEY" -H "X-TIMESTAMP: $ts" \ -H "X-SIGN: $sign" ``` ``` params = {"type": ..., "status": ..., "limit": ..., "offset": ...} r = requests.get(f"{BASE}/api/v2/strategies/campaigns", params=params headers=signed_headers_query(params)) print(r.json()) ``` ``` let resp = client .get(format!("{BASE}/api/v2/strategies/campaigns?type=string")) .headers(signed_headers_query(¶ms)) .send()?; println!("{}", resp.text()?); ``` ``` req, _ := http.NewRequest("GET", BASE+"/api/v2/strategies/campaigns?type=string", nil) for k, v := range signedHeadersQuery(req.URL.Query()) { req.Header.Set(k, v) } resp, err := http.DefaultClient.Do(req) if err != nil { log.Fatal(err) } defer resp.Body.Close() io.Copy(os.Stdout, resp.Body) ``` ``` HttpResponse resp = client.send( signedGet("/api/v2/strategies/campaigns?type=string"), HttpResponse.BodyHandlers.ofString()); ``` ``` const res = await fetch(`${BASE}/api/v2/strategies/campaigns?type=string`, { method: "GET", headers: signedHeadersQuery(params), }); const data: StrategyCampaignList = await res.json(); ``` ``` val request = signedGet("/api/v2/strategies/campaigns?type=string") val response = client.send(request, HttpResponse.BodyHandlers.ofString()) println(response.body()) ``` ``` cpr::Response r = cpr::Get( cpr::Url{BASE + "/api/v2/strategies/campaigns?type=string"}, signedHeadersQuery(params)); std::cout << r.text << std::endl; ``` ``` const res = await fetch(`${BASE}/api/v2/strategies/campaigns?type=string`, { method: "GET", headers: signedHeadersQuery(params), }); console.log(await res.json()); ``` **Response** 200 ``` { "count": 0, "campaigns": [ { "id": "string", "type": "string", "status": "running", "stopping": true, "phase": "string", "stop_reason": "string", "cycles_done": 0, "cycles_planned": 0, "paper_minted": 0.0, "usdc_converted": 0.0, "queued_usdc": 0.0, "haircut_paid": 0.0, "fees_paid": 0.0, "current_legs": [ {} ], "last_cycle": { "pnl_usdc": 0.0, "paper": 0.0, "closed_at": "string", "multileg_order_id": "string" }, "last_error": "string", "symbol": "string", "leverage": 0, "margin_per_leg": 0.0, "target_move_bps": 0, "budget_usdc": 0.0, "stop": { "queued_share_pct": 0.0, "stop_before_key_expiry": true, "hard_kill_on_stop": true }, "created_at": "string", "started_at": "string", "stopped_at": "string" } ] } ``` # Cancel all open orders GET `https://api.pro.anboto.xyz/api/v2/trading/order/cancelAll` All orders that are not in a terminal state will be cancelled **ApiKeyAuth** required. ### Headers | Header | | | | --------------- | ----------------- | -------- | | `X-API-KEY` | string | required | | `X-TIMESTAMP` | int64 ms | required | | `X-SIGN` | string | required | | `X-RECV-WINDOW` | int, default 5000 | | ### Responses | | | | --- | -------------------------------------------------------------------------------------- | | 200 | The list of open orders that will be cancelled. | | 401 | Unauthorized: missing or unknown API key | | 403 | Forbidden: the API key is read-only (its owner has no trade permission on the account) | | 429 | Rate limit exceeded, retry later | ### Response fields — [OrderDetailsList](https://api-docs.anboto.xyz/reference/schemas/#orderdetailslist) `orders` array\[[OrderDetails](https://api-docs.anboto.xyz/reference/schemas/#orderdetails)\] required The list of order details for separate orders. `orders[].order_id` integer The Anboto generated order id Example: `123456` `orders[].client_order_id` string The client provided order id Example: `xxx-yyy-zzz` `orders[].symbol` string The order symbol in Anboto's symbology `orders[].status` [enum](https://api-docs.anboto.xyz/reference/schemas/#orderstatus) The order status — `PENDING_NEW`, `ACCEPTED`, `REJECTED`, `PARTIALLY_FILLED`, `FILLED`, `PENDING_CANCEL`, `CANCELLED`, `PENDING_PAUSE`, … (12 values) `orders[].asset_class` [enum](https://api-docs.anboto.xyz/reference/schemas/#assetcategory) The Asset category of the order. — `SPOT`, `FUTURE` Example: `SPOT` `orders[].exchange` [enum](https://api-docs.anboto.xyz/reference/schemas/#tradingexchange) The exchanges available for order placement via the API — `BINANCE`, `HUOBI`, `GATEIO`, `KRAKEN`, `KUCOIN`, `OKX`, `BYBIT`, `BITGET`, … (17 values) `orders[].strategy` [enum](https://api-docs.anboto.xyz/reference/schemas/#executionstrategy) The execution strategy for the order. — `TWAP`, `VWAP`, `ICEBERG`, `POV`, `MARKET`, `LIMIT`, `IS`, `SCALE` Example: `VWAP` `orders[].start_time` number The time when the order start trading from epoch time in ms `orders[].end_time` number The scheduled end of the execution from epoch time in ms while the order is working (e.g. start_time + duration for a TWAP); the time the order reached its terminal state once finished `orders[].quantity` number The total quantity of the parent order in base asset, as placed. Absent for value-target (notional) orders, see target_value Example: `6` `orders[].filled_quantity` number required The absolute amount of the order quantity filled Example: `0` `orders[].leaves_quantity` number required The absolute amount of the parent order quantity remaining to be filled (quantity - filled_quantity, 0 once the order is terminal). This is the parent order's remainder, never the leaves of the child order currently working it Example: `0` `orders[].progress` number Execution progress of the parent order between 0 and 1: filled_quantity / quantity, or filled notional / target_value for value-target orders. Same computation as the WebSocket order topic orderProgress; 1 once FILLED. Absent when the parent order is not known Example: `0.1783` `orders[].side` [enum](https://api-docs.anboto.xyz/reference/schemas/#side) The side of the book to trade. — `BUY`, `SELL` `orders[].last_quantity` number required The last qty received in a fill from the exchange Example: `0` `orders[].last_price` number required The last price executed on the exchange Example: `0` `orders[].average_price` number required The average execution price of the order Example: `0` `orders[].limit_price` number The limit price of the parent order, if one was set `orders[].clip_size_type` [enum](https://api-docs.anboto.xyz/reference/schemas/#clipsizetype) The clip size for the child orders. The default is AUTOMATIC — `ABSOLUTE`, `PERCENTAGE`, `AUTOMATIC`, `ORDER_COUNT` `orders[].clip_size_val` number The clip size value of the parent order, as placed `orders[].target_value` number The target notional of a value-target order (e.g. a multi-leg order leg); quantity is absent for such orders `orders[].params` [OrderParams](https://api-docs.anboto.xyz/reference/schemas/#orderparams) The advanced order parameters to modify the execution behavior. `orders[].trades` array\[[TradeDetails](https://api-docs.anboto.xyz/reference/schemas/#tradedetails)\] The list of trades associated with this order when include_trades=true `orders[].trades[].trade_id` string The trade id assigned by the exchange, or the Anboto platform trade id when no exchange trade id was captured Example: `1204004183` `orders[].trades[].symbol` string required The symbol of the fill in Anboto's symbology Example: `BTC/USDT:USDT` `orders[].trades[].exchange_order_id` string The exchange order id of the child order the fill belongs to Example: `151990408` `orders[].trades[].client_order_id` string The client order id of the child order the fill belongs to `orders[].trades[].quantity` number required The absolute amount filled by this trade, in base asset Example: `0.5` `orders[].trades[].price` number required The traded price Example: `92.91` `orders[].trades[].direction` enum The direction of the trade — `BUY`, `SELL` Example: `BUY` `orders[].trades[].maker_or_taker` enum Whether the fill was made as maker or taker — `MAKER`, `TAKER` Example: `MAKER` `orders[].trades[].exec_time` integer The execution time of the trade as ms since epoch Example: `1758276000000` `orders[].trades[].fee` number The fee charged on the trade, in fee_currency Example: `0.0021` `orders[].trades[].fee_currency` string The asset the fee was charged in Example: `USDT` `orders[].trades[].parent_order_id` integer The Anboto id of the parent order the fill belongs to (the order_id of the enclosing order) Example: `596990285759373312` `orders[].trades[].child_order_id` integer The Anboto id of the child (slice) order that executed on the exchange; the WebSocket trade topic carries it as order_id Example: `596990290020118528` `orders[].fees_infos` object Aggregated fees per currency when include_fees=true ``` curl -X GET "$BASE/api/v2/trading/order/cancelAll" \ -H "X-API-KEY: $API_KEY" -H "X-TIMESTAMP: $ts" \ -H "X-SIGN: $sign" ``` ``` r = requests.get(f"{BASE}/api/v2/trading/order/cancelAll", headers=signed_headers_query({})) print(r.json()) ``` ``` let resp = client .get(format!("{BASE}/api/v2/trading/order/cancelAll")) .headers(signed_headers_query(¶ms)) .send()?; println!("{}", resp.text()?); ``` ``` req, _ := http.NewRequest("GET", BASE+"/api/v2/trading/order/cancelAll", nil) for k, v := range signedHeadersQuery(req.URL.Query()) { req.Header.Set(k, v) } resp, err := http.DefaultClient.Do(req) if err != nil { log.Fatal(err) } defer resp.Body.Close() io.Copy(os.Stdout, resp.Body) ``` ``` HttpResponse resp = client.send( signedGet("/api/v2/trading/order/cancelAll"), HttpResponse.BodyHandlers.ofString()); ``` ``` const res = await fetch(`${BASE}/api/v2/trading/order/cancelAll`, { method: "GET", headers: signedHeadersQuery(params), }); const data: OrderDetailsList = await res.json(); ``` ``` val request = signedGet("/api/v2/trading/order/cancelAll") val response = client.send(request, HttpResponse.BodyHandlers.ofString()) println(response.body()) ``` ``` cpr::Response r = cpr::Get( cpr::Url{BASE + "/api/v2/trading/order/cancelAll"}, signedHeadersQuery(params)); std::cout << r.text << std::endl; ``` ``` const res = await fetch(`${BASE}/api/v2/trading/order/cancelAll`, { method: "GET", headers: signedHeadersQuery(params), }); console.log(await res.json()); ``` **Response** 200 ``` { "orders": [ { "order_id": 123456, "client_order_id": "xxx-yyy-zzz", "symbol": "string", "status": "PENDING_NEW", "asset_class": "SPOT", "exchange": "BINANCE", "strategy": "TWAP", "start_time": 0.0, "end_time": 0.0, "quantity": 6, "filled_quantity": 0, "leaves_quantity": 0, "progress": 0.1783, "side": "BUY", "last_quantity": 0, "last_price": 0, "average_price": 0, "limit_price": 0.0, "clip_size_type": "ABSOLUTE", "clip_size_val": 0.0, "target_value": 0.0, "params": { "duration_seconds": "120", "trading_style": "PASSIVE", "urgency": "LOW", "pov_ratio": 5, "pov_risk": "LOW", "randomize_amount": true, "would": {}, "trigger": {}, "placement_infos": {}, "reduce_only": true, "start_ladder_price": "string", "end_ladder_price": "string", "ladder_direction": "string", "ladder_profile": "string", "size_skew": 0.0, "ob_imbalance_cancel": true, "ob_imbalance_threshold": "0.75", "price_lock_bps": "5", "limit_is_arrival": true, "limit_bps": "-10", "timer_iceberg_delay": 0.5, "timer_iceberg_delay_min": 0, "timer_iceberg_delay_max": 10, "randomize_iceberg_timer": true, "extend_duration": true }, "trades": [ {} ], "fees_infos": {} } ] } ``` # Cancel many POST `https://api.pro.anboto.xyz/api/v2/trading/order/cancelMany` This will initiate the order cancellations and set the status of all orders to pending cancel. For the finalized state call /order?orderId=xxx **ApiKeyAuth** required. ### Body params `orders` array\[[CancelUpstreamOrderRequest](https://api-docs.anboto.xyz/reference/schemas/#cancelupstreamorderrequest)\] required The list of parent cancellation requests ### Headers | Header | | | | --------------- | ----------------- | -------- | | `X-API-KEY` | string | required | | `X-TIMESTAMP` | int64 ms | required | | `X-SIGN` | string | required | | `X-RECV-WINDOW` | int, default 5000 | | ### Responses | | | | --- | -------------------------------------------------------------------------------------- | | 200 | Cancellation request processed and in progress. | | 401 | Unauthorized: missing or unknown API key | | 403 | Forbidden: the API key is read-only (its owner has no trade permission on the account) | | 429 | Rate limit exceeded, retry later | ### Response fields — [OrderSummary](https://api-docs.anboto.xyz/reference/schemas/#ordersummary) `order_id` integer The Anboto assigned order identifier `client_order_id` string A custom string to identify the order Example: `ABC-12345^12-10-23` `status` [enum](https://api-docs.anboto.xyz/reference/schemas/#orderstatus) The order status — `PENDING_NEW`, `ACCEPTED`, `REJECTED`, `PARTIALLY_FILLED`, `FILLED`, `PENDING_CANCEL`, `CANCELLED`, `PENDING_PAUSE`, … (12 values) `created_at` date-time required The time in UTC when the order was created Example: `2024-01-22T22:05:00Z` `message` string Any additional information, usually if the order was rejected `error_code` [enum](https://api-docs.anboto.xyz/reference/schemas/#apierrorcode) The error code used to describe why an order was rejected. — `OTHER`, `QUANTITY_EXCEED`, `AUTHENTICATION_ERROR`, `INSUFFICIENT_FUNDS`, `RATE_LIMIT_EXCEEDED`, `DDOS_PROTECTION`, `EXCHANGE_NOT_AVAILABLE`, `NETWORK_ERROR`, … (34 values) Example: `INVALID_ORDER` ``` body='{ "orders": [ { "order_id": 123456, "client_order_id": "xxx-yyy-zzzz" } ] }' curl -X POST "$BASE/api/v2/trading/order/cancelMany" \ -H "X-API-KEY: $API_KEY" -H "X-TIMESTAMP: $ts" \ -H "X-SIGN: $sign" \ -H "Content-Type: application/json" -d "$body" ``` ``` payload = { "orders": [ { "order_id": 123456, "client_order_id": "xxx-yyy-zzzz" } ] } r = requests.post(f"{BASE}/api/v2/trading/order/cancelMany", data=json.dumps(payload) headers=signed_headers(payload)) print(r.json()) ``` ``` let payload = serde_json::json!({ "orders": [ { "order_id": 123456, "client_order_id": "xxx-yyy-zzzz" } ] }); let resp = client .post(format!("{BASE}/api/v2/trading/order/cancelMany")) .headers(signed_headers(&payload)) .json(&payload) .send()?; println!("{}", resp.text()?); ``` ``` payload := map[string]any{ "orders": []any{ map[string]any{ "order_id": 123456, "client_order_id": "xxx-yyy-zzzz", }, }, } body, _ := json.Marshal(payload) req, _ := http.NewRequest("POST", BASE+"/api/v2/trading/order/cancelMany", bytes.NewReader(body)) for k, v := range signedHeaders(string(body)) { req.Header.Set(k, v) } req.Header.Set("Content-Type", "application/json") resp, err := http.DefaultClient.Do(req) if err != nil { log.Fatal(err) } defer resp.Body.Close() io.Copy(os.Stdout, resp.Body) ``` ``` String jsonBody = mapper.writeValueAsString(payload); HttpResponse resp = client.send( signedPost("/api/v2/trading/order/cancelMany", jsonBody), HttpResponse.BodyHandlers.ofString()); ``` ``` const payload: CancelManyUpstreamOrdersRequest = { "orders": [ { "order_id": 123456, "client_order_id": "xxx-yyy-zzzz" } ] }; const res = await fetch(`${BASE}/api/v2/trading/order/cancelMany`, { method: "POST", headers: signedHeaders(payload), body: JSON.stringify(payload), }); const data: OrderSummary = await res.json(); ``` ``` val jsonBody = mapper.writeValueAsString(payload) val request = signedPost("/api/v2/trading/order/cancelMany", jsonBody) val response = client.send(request, HttpResponse.BodyHandlers.ofString()) println(response.body()) ``` ``` std::string body = R"({ "orders": [ { "order_id": 123456, "client_order_id": "xxx-yyy-zzzz" } ] })"; cpr::Response r = cpr::Post( cpr::Url{BASE + "/api/v2/trading/order/cancelMany"}, signedHeaders(body), cpr::Header{{"Content-Type", "application/json"}}, cpr::Body{body}); std::cout << r.text << std::endl; ``` ``` const payload = { "orders": [ { "order_id": 123456, "client_order_id": "xxx-yyy-zzzz" } ] }; const res = await fetch(`${BASE}/api/v2/trading/order/cancelMany`, { method: "POST", headers: signedHeaders(payload), body: JSON.stringify(payload), }); console.log(await res.json()); ``` **Response** 200 ``` { "order_id": 0, "client_order_id": "ABC-12345^12-10-23", "status": "PENDING_NEW", "created_at": "2024-01-22T22:05:00Z", "message": "string", "error_code": "OTHER" } ``` # Cancel order POST `https://api.pro.anboto.xyz/api/v2/trading/order/cancel` This will initiate a cancellation request and set the order state to pending cancel. For the finalized state call /order/id?orderId=xxx **ApiKeyAuth** required. ### Body params `order_id` integer The Anboto generated order id Example: `123456` `client_order_id` string The client provided order id Example: `xxx-yyy-zzzz` ### Headers | Header | | | | --------------- | ----------------- | -------- | | `X-API-KEY` | string | required | | `X-TIMESTAMP` | int64 ms | required | | `X-SIGN` | string | required | | `X-RECV-WINDOW` | int, default 5000 | | ### Responses | | | | --- | -------------------------------------------------------------------------------------- | | 200 | Cancellation request processed and in progress. | | 401 | Unauthorized: missing or unknown API key | | 403 | Forbidden: the API key is read-only (its owner has no trade permission on the account) | | 429 | Rate limit exceeded, retry later | ### Response fields — [OrderSummary](https://api-docs.anboto.xyz/reference/schemas/#ordersummary) `order_id` integer The Anboto assigned order identifier `client_order_id` string A custom string to identify the order Example: `ABC-12345^12-10-23` `status` [enum](https://api-docs.anboto.xyz/reference/schemas/#orderstatus) The order status — `PENDING_NEW`, `ACCEPTED`, `REJECTED`, `PARTIALLY_FILLED`, `FILLED`, `PENDING_CANCEL`, `CANCELLED`, `PENDING_PAUSE`, … (12 values) `created_at` date-time required The time in UTC when the order was created Example: `2024-01-22T22:05:00Z` `message` string Any additional information, usually if the order was rejected `error_code` [enum](https://api-docs.anboto.xyz/reference/schemas/#apierrorcode) The error code used to describe why an order was rejected. — `OTHER`, `QUANTITY_EXCEED`, `AUTHENTICATION_ERROR`, `INSUFFICIENT_FUNDS`, `RATE_LIMIT_EXCEEDED`, `DDOS_PROTECTION`, `EXCHANGE_NOT_AVAILABLE`, `NETWORK_ERROR`, … (34 values) Example: `INVALID_ORDER` ``` body='{ "order_id": 123456, "client_order_id": "xxx-yyy-zzzz" }' curl -X POST "$BASE/api/v2/trading/order/cancel" \ -H "X-API-KEY: $API_KEY" -H "X-TIMESTAMP: $ts" \ -H "X-SIGN: $sign" \ -H "Content-Type: application/json" -d "$body" ``` ``` payload = { "order_id": 123456, "client_order_id": "xxx-yyy-zzzz" } r = requests.post(f"{BASE}/api/v2/trading/order/cancel", data=json.dumps(payload) headers=signed_headers(payload)) print(r.json()) ``` ``` let payload = serde_json::json!({ "order_id": 123456, "client_order_id": "xxx-yyy-zzzz" }); let resp = client .post(format!("{BASE}/api/v2/trading/order/cancel")) .headers(signed_headers(&payload)) .json(&payload) .send()?; println!("{}", resp.text()?); ``` ``` payload := map[string]any{ "order_id": 123456, "client_order_id": "xxx-yyy-zzzz", } body, _ := json.Marshal(payload) req, _ := http.NewRequest("POST", BASE+"/api/v2/trading/order/cancel", bytes.NewReader(body)) for k, v := range signedHeaders(string(body)) { req.Header.Set(k, v) } req.Header.Set("Content-Type", "application/json") resp, err := http.DefaultClient.Do(req) if err != nil { log.Fatal(err) } defer resp.Body.Close() io.Copy(os.Stdout, resp.Body) ``` ``` String jsonBody = mapper.writeValueAsString(payload); HttpResponse resp = client.send( signedPost("/api/v2/trading/order/cancel", jsonBody), HttpResponse.BodyHandlers.ofString()); ``` ``` const payload: CancelUpstreamOrderRequest = { "order_id": 123456, "client_order_id": "xxx-yyy-zzzz" }; const res = await fetch(`${BASE}/api/v2/trading/order/cancel`, { method: "POST", headers: signedHeaders(payload), body: JSON.stringify(payload), }); const data: OrderSummary = await res.json(); ``` ``` val jsonBody = mapper.writeValueAsString(payload) val request = signedPost("/api/v2/trading/order/cancel", jsonBody) val response = client.send(request, HttpResponse.BodyHandlers.ofString()) println(response.body()) ``` ``` std::string body = R"({ "order_id": 123456, "client_order_id": "xxx-yyy-zzzz" })"; cpr::Response r = cpr::Post( cpr::Url{BASE + "/api/v2/trading/order/cancel"}, signedHeaders(body), cpr::Header{{"Content-Type", "application/json"}}, cpr::Body{body}); std::cout << r.text << std::endl; ``` ``` const payload = { "order_id": 123456, "client_order_id": "xxx-yyy-zzzz" }; const res = await fetch(`${BASE}/api/v2/trading/order/cancel`, { method: "POST", headers: signedHeaders(payload), body: JSON.stringify(payload), }); console.log(await res.json()); ``` **Response** 200 ``` { "order_id": 0, "client_order_id": "ABC-12345^12-10-23", "status": "PENDING_NEW", "created_at": "2024-01-22T22:05:00Z", "message": "string", "error_code": "OTHER" } ``` # Create many multi legs orders POST `https://api.pro.anboto.xyz/api/v2/trading/order/createMany/multilegs` Process a set of new order request and returns a summary for each order, the orders are not linked during execution and this endpoint is for convenience only **ApiKeyAuth** required. ### Body params `orders` array\[[CreateMultiLegsParentOrderRequest](https://api-docs.anboto.xyz/reference/schemas/#createmultilegsparentorderrequest)\] required ### Headers | Header | | | | --------------- | ----------------- | -------- | | `X-API-KEY` | string | required | | `X-TIMESTAMP` | int64 ms | required | | `X-SIGN` | string | required | | `X-RECV-WINDOW` | int, default 5000 | | ### Responses | | | | --- | -------------------------------------------------------------------------------------- | | 201 | Order processed. | | 401 | Unauthorized: missing or unknown API key | | 403 | Forbidden: the API key is read-only (its owner has no trade permission on the account) | | 429 | Rate limit exceeded, retry later | ### Response fields — [OrderSummaryList](https://api-docs.anboto.xyz/reference/schemas/#ordersummarylist) `orders` array\[[OrderSummary](https://api-docs.anboto.xyz/reference/schemas/#ordersummary)\] required The list of order summaries for separate orders. `orders[].order_id` integer The Anboto assigned order identifier `orders[].client_order_id` string A custom string to identify the order Example: `ABC-12345^12-10-23` `orders[].status` [enum](https://api-docs.anboto.xyz/reference/schemas/#orderstatus) The order status — `PENDING_NEW`, `ACCEPTED`, `REJECTED`, `PARTIALLY_FILLED`, `FILLED`, `PENDING_CANCEL`, `CANCELLED`, `PENDING_PAUSE`, … (12 values) `orders[].created_at` date-time required The time in UTC when the order was created Example: `2024-01-22T22:05:00Z` `orders[].message` string Any additional information, usually if the order was rejected `orders[].error_code` [enum](https://api-docs.anboto.xyz/reference/schemas/#apierrorcode) The error code used to describe why an order was rejected. — `OTHER`, `QUANTITY_EXCEED`, `AUTHENTICATION_ERROR`, `INSUFFICIENT_FUNDS`, `RATE_LIMIT_EXCEEDED`, `DDOS_PROTECTION`, `EXCHANGE_NOT_AVAILABLE`, `NETWORK_ERROR`, … (34 values) Example: `INVALID_ORDER` ``` body='{ "orders": [ { "client_order_id": "ABC-12345^12-10-23", "subaccount": "string", "algo": "PAIR", "legs": [ {} ], "start_time": "2024-01-22T22:05:00Z", "end_time": "2024-04-22T22:05:00Z", "params": {} } ] }' curl -X POST "$BASE/api/v2/trading/order/createMany/multilegs" \ -H "X-API-KEY: $API_KEY" -H "X-TIMESTAMP: $ts" \ -H "X-SIGN: $sign" \ -H "Content-Type: application/json" -d "$body" ``` ``` payload = { "orders": [ { "client_order_id": "ABC-12345^12-10-23", "subaccount": "string", "algo": "PAIR", "legs": [ {} ], "start_time": "2024-01-22T22:05:00Z", "end_time": "2024-04-22T22:05:00Z", "params": {} } ] } r = requests.post(f"{BASE}/api/v2/trading/order/createMany/multilegs", data=json.dumps(payload) headers=signed_headers(payload)) print(r.json()) ``` ``` let payload = serde_json::json!({ "orders": [ { "client_order_id": "ABC-12345^12-10-23", "subaccount": "string", "algo": "PAIR", "legs": [ {} ], "start_time": "2024-01-22T22:05:00Z", "end_time": "2024-04-22T22:05:00Z", "params": {} } ] }); let resp = client .post(format!("{BASE}/api/v2/trading/order/createMany/multilegs")) .headers(signed_headers(&payload)) .json(&payload) .send()?; println!("{}", resp.text()?); ``` ``` payload := map[string]any{ "orders": []any{ map[string]any{ "client_order_id": "ABC-12345^12-10-23", "subaccount": "string", "algo": "PAIR", "legs": []any{ map[string]any{}, }, "start_time": "2024-01-22T22:05:00Z", "end_time": "2024-04-22T22:05:00Z", "params": map[string]any{}, }, }, } body, _ := json.Marshal(payload) req, _ := http.NewRequest("POST", BASE+"/api/v2/trading/order/createMany/multilegs", bytes.NewReader(body)) for k, v := range signedHeaders(string(body)) { req.Header.Set(k, v) } req.Header.Set("Content-Type", "application/json") resp, err := http.DefaultClient.Do(req) if err != nil { log.Fatal(err) } defer resp.Body.Close() io.Copy(os.Stdout, resp.Body) ``` ``` String jsonBody = mapper.writeValueAsString(payload); HttpResponse resp = client.send( signedPost("/api/v2/trading/order/createMany/multilegs", jsonBody), HttpResponse.BodyHandlers.ofString()); ``` ``` const payload: CreateManyMultiLegsParentOrdersRequest = { "orders": [ { "client_order_id": "ABC-12345^12-10-23", "subaccount": "string", "algo": "PAIR", "legs": [ {} ], "start_time": "2024-01-22T22:05:00Z", "end_time": "2024-04-22T22:05:00Z", "params": {} } ] }; const res = await fetch(`${BASE}/api/v2/trading/order/createMany/multilegs`, { method: "POST", headers: signedHeaders(payload), body: JSON.stringify(payload), }); const data: OrderSummaryList = await res.json(); ``` ``` val jsonBody = mapper.writeValueAsString(payload) val request = signedPost("/api/v2/trading/order/createMany/multilegs", jsonBody) val response = client.send(request, HttpResponse.BodyHandlers.ofString()) println(response.body()) ``` ``` std::string body = R"({ "orders": [ { "client_order_id": "ABC-12345^12-10-23", "subaccount": "string", "algo": "PAIR", "legs": [ {} ], "start_time": "2024-01-22T22:05:00Z", "end_time": "2024-04-22T22:05:00Z", "params": {} } ] })"; cpr::Response r = cpr::Post( cpr::Url{BASE + "/api/v2/trading/order/createMany/multilegs"}, signedHeaders(body), cpr::Header{{"Content-Type", "application/json"}}, cpr::Body{body}); std::cout << r.text << std::endl; ``` ``` const payload = { "orders": [ { "client_order_id": "ABC-12345^12-10-23", "subaccount": "string", "algo": "PAIR", "legs": [ {} ], "start_time": "2024-01-22T22:05:00Z", "end_time": "2024-04-22T22:05:00Z", "params": {} } ] }; const res = await fetch(`${BASE}/api/v2/trading/order/createMany/multilegs`, { method: "POST", headers: signedHeaders(payload), body: JSON.stringify(payload), }); console.log(await res.json()); ``` **Response** 201 ``` { "orders": [ { "order_id": 0, "client_order_id": "ABC-12345^12-10-23", "status": "PENDING_NEW", "created_at": "2024-01-22T22:05:00Z", "message": "string", "error_code": "OTHER" } ] } ``` # Create many orders POST `https://api.pro.anboto.xyz/api/v2/trading/order/createMany` Process a set of new order request and returns a summary for each order, the orders are not linked during execution and this endpoint is for convenience only **ApiKeyAuth** required. ### Body params `orders` array\[[CreateParentOrderRequest](https://api-docs.anboto.xyz/reference/schemas/#createparentorderrequest)\] required ### Headers | Header | | | | --------------- | ----------------- | -------- | | `X-API-KEY` | string | required | | `X-TIMESTAMP` | int64 ms | required | | `X-SIGN` | string | required | | `X-RECV-WINDOW` | int, default 5000 | | ### Responses | | | | --- | -------------------------------------------------------------------------------------- | | 201 | Order processed. | | 401 | Unauthorized: missing or unknown API key | | 403 | Forbidden: the API key is read-only (its owner has no trade permission on the account) | | 429 | Rate limit exceeded, retry later | ### Response fields — [OrderSummaryList](https://api-docs.anboto.xyz/reference/schemas/#ordersummarylist) `orders` array\[[OrderSummary](https://api-docs.anboto.xyz/reference/schemas/#ordersummary)\] required The list of order summaries for separate orders. `orders[].order_id` integer The Anboto assigned order identifier `orders[].client_order_id` string A custom string to identify the order Example: `ABC-12345^12-10-23` `orders[].status` [enum](https://api-docs.anboto.xyz/reference/schemas/#orderstatus) The order status — `PENDING_NEW`, `ACCEPTED`, `REJECTED`, `PARTIALLY_FILLED`, `FILLED`, `PENDING_CANCEL`, `CANCELLED`, `PENDING_PAUSE`, … (12 values) `orders[].created_at` date-time required The time in UTC when the order was created Example: `2024-01-22T22:05:00Z` `orders[].message` string Any additional information, usually if the order was rejected `orders[].error_code` [enum](https://api-docs.anboto.xyz/reference/schemas/#apierrorcode) The error code used to describe why an order was rejected. — `OTHER`, `QUANTITY_EXCEED`, `AUTHENTICATION_ERROR`, `INSUFFICIENT_FUNDS`, `RATE_LIMIT_EXCEEDED`, `DDOS_PROTECTION`, `EXCHANGE_NOT_AVAILABLE`, `NETWORK_ERROR`, … (34 values) Example: `INVALID_ORDER` ``` body='{ "orders": [ { "client_order_id": "ABC-12345^12-10-23", "exchange": "BINANCE", "subaccount": "string", "symbol": "string", "asset_category": "SPOT", "side": "BUY", "quantity": "string", "strategy": "TWAP", "limit_price": "2205.10", "limit_is_arrival": true, "start_time": "2024-01-22T22:05:00Z", "end_time": "2024-04-22T22:05:00Z", "clip_size_type": "ABSOLUTE", "clip_size_val": "0.01", "params": { "duration_seconds": "120", "trading_style": "PASSIVE", "urgency": "LOW", "pov_ratio": 5, "pov_risk": "LOW", "randomize_amount": true, "would": {}, "trigger": {}, "placement_infos": {}, "reduce_only": true, "start_ladder_price": "string", "end_ladder_price": "string", "ladder_direction": "string", "ladder_profile": "string", "size_skew": 0.0, "ob_imbalance_cancel": true, "ob_imbalance_threshold": "0.75", "price_lock_bps": "5", "limit_is_arrival": true, "limit_bps": "-10", "timer_iceberg_delay": 0.5, "timer_iceberg_delay_min": 0, "timer_iceberg_delay_max": 10, "randomize_iceberg_timer": true, "extend_duration": true } } ] }' curl -X POST "$BASE/api/v2/trading/order/createMany" \ -H "X-API-KEY: $API_KEY" -H "X-TIMESTAMP: $ts" \ -H "X-SIGN: $sign" \ -H "Content-Type: application/json" -d "$body" ``` ``` payload = { "orders": [ { "client_order_id": "ABC-12345^12-10-23", "exchange": "BINANCE", "subaccount": "string", "symbol": "string", "asset_category": "SPOT", "side": "BUY", "quantity": "string", "strategy": "TWAP", "limit_price": "2205.10", "limit_is_arrival": true, "start_time": "2024-01-22T22:05:00Z", "end_time": "2024-04-22T22:05:00Z", "clip_size_type": "ABSOLUTE", "clip_size_val": "0.01", "params": { "duration_seconds": "120", "trading_style": "PASSIVE", "urgency": "LOW", "pov_ratio": 5, "pov_risk": "LOW", "randomize_amount": true, "would": {}, "trigger": {}, "placement_infos": {}, "reduce_only": true, "start_ladder_price": "string", "end_ladder_price": "string", "ladder_direction": "string", "ladder_profile": "string", "size_skew": 0.0, "ob_imbalance_cancel": true, "ob_imbalance_threshold": "0.75", "price_lock_bps": "5", "limit_is_arrival": true, "limit_bps": "-10", "timer_iceberg_delay": 0.5, "timer_iceberg_delay_min": 0, "timer_iceberg_delay_max": 10, "randomize_iceberg_timer": true, "extend_duration": true } } ] } r = requests.post(f"{BASE}/api/v2/trading/order/createMany", data=json.dumps(payload) headers=signed_headers(payload)) print(r.json()) ``` ``` let payload = serde_json::json!({ "orders": [ { "client_order_id": "ABC-12345^12-10-23", "exchange": "BINANCE", "subaccount": "string", "symbol": "string", "asset_category": "SPOT", "side": "BUY", "quantity": "string", "strategy": "TWAP", "limit_price": "2205.10", "limit_is_arrival": true, "start_time": "2024-01-22T22:05:00Z", "end_time": "2024-04-22T22:05:00Z", "clip_size_type": "ABSOLUTE", "clip_size_val": "0.01", "params": { "duration_seconds": "120", "trading_style": "PASSIVE", "urgency": "LOW", "pov_ratio": 5, "pov_risk": "LOW", "randomize_amount": true, "would": {}, "trigger": {}, "placement_infos": {}, "reduce_only": true, "start_ladder_price": "string", "end_ladder_price": "string", "ladder_direction": "string", "ladder_profile": "string", "size_skew": 0.0, "ob_imbalance_cancel": true, "ob_imbalance_threshold": "0.75", "price_lock_bps": "5", "limit_is_arrival": true, "limit_bps": "-10", "timer_iceberg_delay": 0.5, "timer_iceberg_delay_min": 0, "timer_iceberg_delay_max": 10, "randomize_iceberg_timer": true, "extend_duration": true } } ] }); let resp = client .post(format!("{BASE}/api/v2/trading/order/createMany")) .headers(signed_headers(&payload)) .json(&payload) .send()?; println!("{}", resp.text()?); ``` ``` payload := map[string]any{ "orders": []any{ map[string]any{ "client_order_id": "ABC-12345^12-10-23", "exchange": "BINANCE", "subaccount": "string", "symbol": "string", "asset_category": "SPOT", "side": "BUY", "quantity": "string", "strategy": "TWAP", "limit_price": "2205.10", "limit_is_arrival": true, "start_time": "2024-01-22T22:05:00Z", "end_time": "2024-04-22T22:05:00Z", "clip_size_type": "ABSOLUTE", "clip_size_val": "0.01", "params": map[string]any{ "duration_seconds": "120", "trading_style": "PASSIVE", "urgency": "LOW", "pov_ratio": 5, "pov_risk": "LOW", "randomize_amount": true, "would": map[string]any{}, "trigger": map[string]any{}, "placement_infos": map[string]any{}, "reduce_only": true, "start_ladder_price": "string", "end_ladder_price": "string", "ladder_direction": "string", "ladder_profile": "string", "size_skew": 0.0, "ob_imbalance_cancel": true, "ob_imbalance_threshold": "0.75", "price_lock_bps": "5", "limit_is_arrival": true, "limit_bps": "-10", "timer_iceberg_delay": 0.5, "timer_iceberg_delay_min": 0, "timer_iceberg_delay_max": 10, "randomize_iceberg_timer": true, "extend_duration": true, }, }, }, } body, _ := json.Marshal(payload) req, _ := http.NewRequest("POST", BASE+"/api/v2/trading/order/createMany", bytes.NewReader(body)) for k, v := range signedHeaders(string(body)) { req.Header.Set(k, v) } req.Header.Set("Content-Type", "application/json") resp, err := http.DefaultClient.Do(req) if err != nil { log.Fatal(err) } defer resp.Body.Close() io.Copy(os.Stdout, resp.Body) ``` ``` String jsonBody = mapper.writeValueAsString(payload); HttpResponse resp = client.send( signedPost("/api/v2/trading/order/createMany", jsonBody), HttpResponse.BodyHandlers.ofString()); ``` ``` const payload: CreateManyParentOrdersRequest = { "orders": [ { "client_order_id": "ABC-12345^12-10-23", "exchange": "BINANCE", "subaccount": "string", "symbol": "string", "asset_category": "SPOT", "side": "BUY", "quantity": "string", "strategy": "TWAP", "limit_price": "2205.10", "limit_is_arrival": true, "start_time": "2024-01-22T22:05:00Z", "end_time": "2024-04-22T22:05:00Z", "clip_size_type": "ABSOLUTE", "clip_size_val": "0.01", "params": { "duration_seconds": "120", "trading_style": "PASSIVE", "urgency": "LOW", "pov_ratio": 5, "pov_risk": "LOW", "randomize_amount": true, "would": {}, "trigger": {}, "placement_infos": {}, "reduce_only": true, "start_ladder_price": "string", "end_ladder_price": "string", "ladder_direction": "string", "ladder_profile": "string", "size_skew": 0.0, "ob_imbalance_cancel": true, "ob_imbalance_threshold": "0.75", "price_lock_bps": "5", "limit_is_arrival": true, "limit_bps": "-10", "timer_iceberg_delay": 0.5, "timer_iceberg_delay_min": 0, "timer_iceberg_delay_max": 10, "randomize_iceberg_timer": true, "extend_duration": true } } ] }; const res = await fetch(`${BASE}/api/v2/trading/order/createMany`, { method: "POST", headers: signedHeaders(payload), body: JSON.stringify(payload), }); const data: OrderSummaryList = await res.json(); ``` ``` val jsonBody = mapper.writeValueAsString(payload) val request = signedPost("/api/v2/trading/order/createMany", jsonBody) val response = client.send(request, HttpResponse.BodyHandlers.ofString()) println(response.body()) ``` ``` std::string body = R"({ "orders": [ { "client_order_id": "ABC-12345^12-10-23", "exchange": "BINANCE", "subaccount": "string", "symbol": "string", "asset_category": "SPOT", "side": "BUY", "quantity": "string", "strategy": "TWAP", "limit_price": "2205.10", "limit_is_arrival": true, "start_time": "2024-01-22T22:05:00Z", "end_time": "2024-04-22T22:05:00Z", "clip_size_type": "ABSOLUTE", "clip_size_val": "0.01", "params": { "duration_seconds": "120", "trading_style": "PASSIVE", "urgency": "LOW", "pov_ratio": 5, "pov_risk": "LOW", "randomize_amount": true, "would": {}, "trigger": {}, "placement_infos": {}, "reduce_only": true, "start_ladder_price": "string", "end_ladder_price": "string", "ladder_direction": "string", "ladder_profile": "string", "size_skew": 0.0, "ob_imbalance_cancel": true, "ob_imbalance_threshold": "0.75", "price_lock_bps": "5", "limit_is_arrival": true, "limit_bps": "-10", "timer_iceberg_delay": 0.5, "timer_iceberg_delay_min": 0, "timer_iceberg_delay_max": 10, "randomize_iceberg_timer": true, "extend_duration": true } } ] })"; cpr::Response r = cpr::Post( cpr::Url{BASE + "/api/v2/trading/order/createMany"}, signedHeaders(body), cpr::Header{{"Content-Type", "application/json"}}, cpr::Body{body}); std::cout << r.text << std::endl; ``` ``` const payload = { "orders": [ { "client_order_id": "ABC-12345^12-10-23", "exchange": "BINANCE", "subaccount": "string", "symbol": "string", "asset_category": "SPOT", "side": "BUY", "quantity": "string", "strategy": "TWAP", "limit_price": "2205.10", "limit_is_arrival": true, "start_time": "2024-01-22T22:05:00Z", "end_time": "2024-04-22T22:05:00Z", "clip_size_type": "ABSOLUTE", "clip_size_val": "0.01", "params": { "duration_seconds": "120", "trading_style": "PASSIVE", "urgency": "LOW", "pov_ratio": 5, "pov_risk": "LOW", "randomize_amount": true, "would": {}, "trigger": {}, "placement_infos": {}, "reduce_only": true, "start_ladder_price": "string", "end_ladder_price": "string", "ladder_direction": "string", "ladder_profile": "string", "size_skew": 0.0, "ob_imbalance_cancel": true, "ob_imbalance_threshold": "0.75", "price_lock_bps": "5", "limit_is_arrival": true, "limit_bps": "-10", "timer_iceberg_delay": 0.5, "timer_iceberg_delay_min": 0, "timer_iceberg_delay_max": 10, "randomize_iceberg_timer": true, "extend_duration": true } } ] }; const res = await fetch(`${BASE}/api/v2/trading/order/createMany`, { method: "POST", headers: signedHeaders(payload), body: JSON.stringify(payload), }); console.log(await res.json()); ``` **Response** 201 ``` { "orders": [ { "order_id": 0, "client_order_id": "ABC-12345^12-10-23", "status": "PENDING_NEW", "created_at": "2024-01-22T22:05:00Z", "message": "string", "error_code": "OTHER" } ] } ``` # Create multi legs order POST `https://api.pro.anboto.xyz/api/v2/trading/order/create_multiLegs` Process a new order request and return order response **ApiKeyAuth** required. ### Body params `client_order_id` string A custom string to identify the order Example: `ABC-12345^12-10-23` `subaccount` string The sub-account under which to trade the order `algo` [enum](https://api-docs.anboto.xyz/reference/schemas/#multilegsalgo) required The execution strategy for the order. — `PAIR` `legs` array\[[CreateOrderLegRequest](https://api-docs.anboto.xyz/reference/schemas/#createorderlegrequest)\] required The order legs `start_time` string The start time in UTC Example: `2024-01-22T22:05:00Z` `end_time` string The end time in UTC Example: `2024-04-22T22:05:00Z` `params` [MultiLegsOrderParams](https://api-docs.anboto.xyz/reference/schemas/#multilegsorderparams) The advanced order parameters to modify the execution behavior. ### Headers | Header | | | | --------------- | ----------------- | -------- | | `X-API-KEY` | string | required | | `X-TIMESTAMP` | int64 ms | required | | `X-SIGN` | string | required | | `X-RECV-WINDOW` | int, default 5000 | | ### Responses | | | | --- | -------------------------------------------------------------------------------------- | | 201 | Order created successfully | | 401 | Unauthorized: missing or unknown API key | | 403 | Forbidden: the API key is read-only (its owner has no trade permission on the account) | | 429 | Rate limit exceeded, retry later | ### Response fields — [OrderSummary](https://api-docs.anboto.xyz/reference/schemas/#ordersummary) `order_id` integer The Anboto assigned order identifier `client_order_id` string A custom string to identify the order Example: `ABC-12345^12-10-23` `status` [enum](https://api-docs.anboto.xyz/reference/schemas/#orderstatus) The order status — `PENDING_NEW`, `ACCEPTED`, `REJECTED`, `PARTIALLY_FILLED`, `FILLED`, `PENDING_CANCEL`, `CANCELLED`, `PENDING_PAUSE`, … (12 values) `created_at` date-time required The time in UTC when the order was created Example: `2024-01-22T22:05:00Z` `message` string Any additional information, usually if the order was rejected `error_code` [enum](https://api-docs.anboto.xyz/reference/schemas/#apierrorcode) The error code used to describe why an order was rejected. — `OTHER`, `QUANTITY_EXCEED`, `AUTHENTICATION_ERROR`, `INSUFFICIENT_FUNDS`, `RATE_LIMIT_EXCEEDED`, `DDOS_PROTECTION`, `EXCHANGE_NOT_AVAILABLE`, `NETWORK_ERROR`, … (34 values) Example: `INVALID_ORDER` ``` body='{ "client_order_id": "ABC-12345^12-10-23", "subaccount": "string", "algo": "PAIR", "legs": [ { "exchange": "BINANCE", "symbol": "string", "asset_category": "SPOT", "side": "BUY", "target_value": "12.0", "ccy": "USD", "limit_price": "2205.10", "strategy": "TWAP", "clip_size_type": "ABSOLUTE", "clip_size_val": "0.01", "params": { "duration_seconds": "120", "trading_style": "PASSIVE", "urgency": "LOW", "randomize_amount": true, "would": {}, "trigger": {}, "placement_infos": {}, "is_leading": true, "timer_iceberg_delay": 0.5, "timer_iceberg_delay_min": 0, "timer_iceberg_delay_max": 10, "randomize_iceberg_timer": true, "extend_duration": true } } ], "start_time": "2024-01-22T22:05:00Z", "end_time": "2024-04-22T22:05:00Z", "params": {} }' curl -X POST "$BASE/api/v2/trading/order/create_multiLegs" \ -H "X-API-KEY: $API_KEY" -H "X-TIMESTAMP: $ts" \ -H "X-SIGN: $sign" \ -H "Content-Type: application/json" -d "$body" ``` ``` payload = { "client_order_id": "ABC-12345^12-10-23", "subaccount": "string", "algo": "PAIR", "legs": [ { "exchange": "BINANCE", "symbol": "string", "asset_category": "SPOT", "side": "BUY", "target_value": "12.0", "ccy": "USD", "limit_price": "2205.10", "strategy": "TWAP", "clip_size_type": "ABSOLUTE", "clip_size_val": "0.01", "params": { "duration_seconds": "120", "trading_style": "PASSIVE", "urgency": "LOW", "randomize_amount": true, "would": {}, "trigger": {}, "placement_infos": {}, "is_leading": true, "timer_iceberg_delay": 0.5, "timer_iceberg_delay_min": 0, "timer_iceberg_delay_max": 10, "randomize_iceberg_timer": true, "extend_duration": true } } ], "start_time": "2024-01-22T22:05:00Z", "end_time": "2024-04-22T22:05:00Z", "params": {} } r = requests.post(f"{BASE}/api/v2/trading/order/create_multiLegs", data=json.dumps(payload) headers=signed_headers(payload)) print(r.json()) ``` ``` let payload = serde_json::json!({ "client_order_id": "ABC-12345^12-10-23", "subaccount": "string", "algo": "PAIR", "legs": [ { "exchange": "BINANCE", "symbol": "string", "asset_category": "SPOT", "side": "BUY", "target_value": "12.0", "ccy": "USD", "limit_price": "2205.10", "strategy": "TWAP", "clip_size_type": "ABSOLUTE", "clip_size_val": "0.01", "params": { "duration_seconds": "120", "trading_style": "PASSIVE", "urgency": "LOW", "randomize_amount": true, "would": {}, "trigger": {}, "placement_infos": {}, "is_leading": true, "timer_iceberg_delay": 0.5, "timer_iceberg_delay_min": 0, "timer_iceberg_delay_max": 10, "randomize_iceberg_timer": true, "extend_duration": true } } ], "start_time": "2024-01-22T22:05:00Z", "end_time": "2024-04-22T22:05:00Z", "params": {} }); let resp = client .post(format!("{BASE}/api/v2/trading/order/create_multiLegs")) .headers(signed_headers(&payload)) .json(&payload) .send()?; println!("{}", resp.text()?); ``` ``` payload := map[string]any{ "client_order_id": "ABC-12345^12-10-23", "subaccount": "string", "algo": "PAIR", "legs": []any{ map[string]any{ "exchange": "BINANCE", "symbol": "string", "asset_category": "SPOT", "side": "BUY", "target_value": "12.0", "ccy": "USD", "limit_price": "2205.10", "strategy": "TWAP", "clip_size_type": "ABSOLUTE", "clip_size_val": "0.01", "params": map[string]any{ "duration_seconds": "120", "trading_style": "PASSIVE", "urgency": "LOW", "randomize_amount": true, "would": map[string]any{}, "trigger": map[string]any{}, "placement_infos": map[string]any{}, "is_leading": true, "timer_iceberg_delay": 0.5, "timer_iceberg_delay_min": 0, "timer_iceberg_delay_max": 10, "randomize_iceberg_timer": true, "extend_duration": true, }, }, }, "start_time": "2024-01-22T22:05:00Z", "end_time": "2024-04-22T22:05:00Z", "params": map[string]any{}, } body, _ := json.Marshal(payload) req, _ := http.NewRequest("POST", BASE+"/api/v2/trading/order/create_multiLegs", bytes.NewReader(body)) for k, v := range signedHeaders(string(body)) { req.Header.Set(k, v) } req.Header.Set("Content-Type", "application/json") resp, err := http.DefaultClient.Do(req) if err != nil { log.Fatal(err) } defer resp.Body.Close() io.Copy(os.Stdout, resp.Body) ``` ``` String jsonBody = mapper.writeValueAsString(payload); HttpResponse resp = client.send( signedPost("/api/v2/trading/order/create_multiLegs", jsonBody), HttpResponse.BodyHandlers.ofString()); ``` ``` const payload: CreateMultiLegsParentOrderRequest = { "client_order_id": "ABC-12345^12-10-23", "subaccount": "string", "algo": "PAIR", "legs": [ { "exchange": "BINANCE", "symbol": "string", "asset_category": "SPOT", "side": "BUY", "target_value": "12.0", "ccy": "USD", "limit_price": "2205.10", "strategy": "TWAP", "clip_size_type": "ABSOLUTE", "clip_size_val": "0.01", "params": { "duration_seconds": "120", "trading_style": "PASSIVE", "urgency": "LOW", "randomize_amount": true, "would": {}, "trigger": {}, "placement_infos": {}, "is_leading": true, "timer_iceberg_delay": 0.5, "timer_iceberg_delay_min": 0, "timer_iceberg_delay_max": 10, "randomize_iceberg_timer": true, "extend_duration": true } } ], "start_time": "2024-01-22T22:05:00Z", "end_time": "2024-04-22T22:05:00Z", "params": {} }; const res = await fetch(`${BASE}/api/v2/trading/order/create_multiLegs`, { method: "POST", headers: signedHeaders(payload), body: JSON.stringify(payload), }); const data: OrderSummary = await res.json(); ``` ``` val jsonBody = mapper.writeValueAsString(payload) val request = signedPost("/api/v2/trading/order/create_multiLegs", jsonBody) val response = client.send(request, HttpResponse.BodyHandlers.ofString()) println(response.body()) ``` ``` std::string body = R"({ "client_order_id": "ABC-12345^12-10-23", "subaccount": "string", "algo": "PAIR", "legs": [ { "exchange": "BINANCE", "symbol": "string", "asset_category": "SPOT", "side": "BUY", "target_value": "12.0", "ccy": "USD", "limit_price": "2205.10", "strategy": "TWAP", "clip_size_type": "ABSOLUTE", "clip_size_val": "0.01", "params": { "duration_seconds": "120", "trading_style": "PASSIVE", "urgency": "LOW", "randomize_amount": true, "would": {}, "trigger": {}, "placement_infos": {}, "is_leading": true, "timer_iceberg_delay": 0.5, "timer_iceberg_delay_min": 0, "timer_iceberg_delay_max": 10, "randomize_iceberg_timer": true, "extend_duration": true } } ], "start_time": "2024-01-22T22:05:00Z", "end_time": "2024-04-22T22:05:00Z", "params": {} })"; cpr::Response r = cpr::Post( cpr::Url{BASE + "/api/v2/trading/order/create_multiLegs"}, signedHeaders(body), cpr::Header{{"Content-Type", "application/json"}}, cpr::Body{body}); std::cout << r.text << std::endl; ``` ``` const payload = { "client_order_id": "ABC-12345^12-10-23", "subaccount": "string", "algo": "PAIR", "legs": [ { "exchange": "BINANCE", "symbol": "string", "asset_category": "SPOT", "side": "BUY", "target_value": "12.0", "ccy": "USD", "limit_price": "2205.10", "strategy": "TWAP", "clip_size_type": "ABSOLUTE", "clip_size_val": "0.01", "params": { "duration_seconds": "120", "trading_style": "PASSIVE", "urgency": "LOW", "randomize_amount": true, "would": {}, "trigger": {}, "placement_infos": {}, "is_leading": true, "timer_iceberg_delay": 0.5, "timer_iceberg_delay_min": 0, "timer_iceberg_delay_max": 10, "randomize_iceberg_timer": true, "extend_duration": true } } ], "start_time": "2024-01-22T22:05:00Z", "end_time": "2024-04-22T22:05:00Z", "params": {} }; const res = await fetch(`${BASE}/api/v2/trading/order/create_multiLegs`, { method: "POST", headers: signedHeaders(payload), body: JSON.stringify(payload), }); console.log(await res.json()); ``` **Response** 201 ``` { "order_id": 0, "client_order_id": "ABC-12345^12-10-23", "status": "PENDING_NEW", "created_at": "2024-01-22T22:05:00Z", "message": "string", "error_code": "OTHER" } ``` # Create order POST `https://api.pro.anboto.xyz/api/v2/trading/order/create` Process a new order request and return order response **ApiKeyAuth** required. ### Body params `client_order_id` string A custom string to identify the order Example: `ABC-12345^12-10-23` `exchange` [enum](https://api-docs.anboto.xyz/reference/schemas/#tradingexchange) required The exchanges available for order placement via the API — `BINANCE`, `HUOBI`, `GATEIO`, `KRAKEN`, `KUCOIN`, `OKX`, `BYBIT`, `BITGET`, … (17 values) `subaccount` string The sub-account under which to trade the order `symbol` string required The symbol using Anboto symbology, e.g. BTC/USDT `asset_category` [enum](https://api-docs.anboto.xyz/reference/schemas/#assetcategory) required The Asset category of the order. — `SPOT`, `FUTURE` Example: `SPOT` `side` [enum](https://api-docs.anboto.xyz/reference/schemas/#side) required The side of the book to trade. — `BUY`, `SELL` `quantity` string required The quantity to trade as a exchange trade-able decimal value, e.g. 0.015 `strategy` [enum](https://api-docs.anboto.xyz/reference/schemas/#executionstrategy) required The execution strategy for the order. — `TWAP`, `VWAP`, `ICEBERG`, `POV`, `MARKET`, `LIMIT`, `IS`, `SCALE` `limit_price` string The exchange valid limit price for the order Example: `2205.10` `limit_is_arrival` boolean Use the arrival price (the midpoint when Anboto accepts the order) as the limit price; params.limit_bps shifts it. Mutually exclusive with limit_price. `start_time` string The start time in UTC Example: `2024-01-22T22:05:00Z` `end_time` string The end time in UTC Example: `2024-04-22T22:05:00Z` `clip_size_type` [enum](https://api-docs.anboto.xyz/reference/schemas/#clipsizetype) The clip size for the child orders. The default is AUTOMATIC — `ABSOLUTE`, `PERCENTAGE`, `AUTOMATIC`, `ORDER_COUNT` Example: `AUTOMATIC` · Default: `AUTOMATIC` `clip_size_val` string The clip size value, required if the type is ABSOLUTE or PERCENTAGE Example: `0.01` `params` [OrderParams](https://api-docs.anboto.xyz/reference/schemas/#orderparams) The advanced order parameters to modify the execution behavior. ### Headers | Header | | | | --------------- | ----------------- | -------- | | `X-API-KEY` | string | required | | `X-TIMESTAMP` | int64 ms | required | | `X-SIGN` | string | required | | `X-RECV-WINDOW` | int, default 5000 | | ### Responses | | | | --- | -------------------------------------------------------------------------------------- | | 201 | Order created successfully | | 401 | Unauthorized: missing or unknown API key | | 403 | Forbidden: the API key is read-only (its owner has no trade permission on the account) | | 429 | Rate limit exceeded, retry later | ### Response fields — [OrderSummary](https://api-docs.anboto.xyz/reference/schemas/#ordersummary) `order_id` integer The Anboto assigned order identifier `client_order_id` string A custom string to identify the order Example: `ABC-12345^12-10-23` `status` [enum](https://api-docs.anboto.xyz/reference/schemas/#orderstatus) The order status — `PENDING_NEW`, `ACCEPTED`, `REJECTED`, `PARTIALLY_FILLED`, `FILLED`, `PENDING_CANCEL`, `CANCELLED`, `PENDING_PAUSE`, … (12 values) `created_at` date-time required The time in UTC when the order was created Example: `2024-01-22T22:05:00Z` `message` string Any additional information, usually if the order was rejected `error_code` [enum](https://api-docs.anboto.xyz/reference/schemas/#apierrorcode) The error code used to describe why an order was rejected. — `OTHER`, `QUANTITY_EXCEED`, `AUTHENTICATION_ERROR`, `INSUFFICIENT_FUNDS`, `RATE_LIMIT_EXCEEDED`, `DDOS_PROTECTION`, `EXCHANGE_NOT_AVAILABLE`, `NETWORK_ERROR`, … (34 values) Example: `INVALID_ORDER` ``` body='{ "client_order_id": "ABC-12345^12-10-23", "exchange": "BINANCE", "subaccount": "string", "symbol": "string", "asset_category": "SPOT", "side": "BUY", "quantity": "string", "strategy": "TWAP", "limit_price": "2205.10", "limit_is_arrival": true, "start_time": "2024-01-22T22:05:00Z", "end_time": "2024-04-22T22:05:00Z", "clip_size_type": "ABSOLUTE", "clip_size_val": "0.01", "params": { "duration_seconds": "120", "trading_style": "PASSIVE", "urgency": "LOW", "pov_ratio": 5, "pov_risk": "LOW", "randomize_amount": true, "would": { "would_price": "string", "would_pct": "string", "would_style": "PASSIVE", "would_is_arrival": true, "would_bps": "5" }, "trigger": { "trigger_price": "string", "trigger_condition": "ABOVE" }, "placement_infos": { "placement_mode": "DEFAULT", "placement": "string", "cancel": "string", "depth_mode": "LEVEL" }, "reduce_only": true, "start_ladder_price": "string", "end_ladder_price": "string", "ladder_direction": "string", "ladder_profile": "string", "size_skew": 0.0, "ob_imbalance_cancel": true, "ob_imbalance_threshold": "0.75", "price_lock_bps": "5", "limit_is_arrival": true, "limit_bps": "-10", "timer_iceberg_delay": 0.5, "timer_iceberg_delay_min": 0, "timer_iceberg_delay_max": 10, "randomize_iceberg_timer": true, "extend_duration": true } }' curl -X POST "$BASE/api/v2/trading/order/create" \ -H "X-API-KEY: $API_KEY" -H "X-TIMESTAMP: $ts" \ -H "X-SIGN: $sign" \ -H "Content-Type: application/json" -d "$body" ``` ``` payload = { "client_order_id": "ABC-12345^12-10-23", "exchange": "BINANCE", "subaccount": "string", "symbol": "string", "asset_category": "SPOT", "side": "BUY", "quantity": "string", "strategy": "TWAP", "limit_price": "2205.10", "limit_is_arrival": true, "start_time": "2024-01-22T22:05:00Z", "end_time": "2024-04-22T22:05:00Z", "clip_size_type": "ABSOLUTE", "clip_size_val": "0.01", "params": { "duration_seconds": "120", "trading_style": "PASSIVE", "urgency": "LOW", "pov_ratio": 5, "pov_risk": "LOW", "randomize_amount": true, "would": { "would_price": "string", "would_pct": "string", "would_style": "PASSIVE", "would_is_arrival": true, "would_bps": "5" }, "trigger": { "trigger_price": "string", "trigger_condition": "ABOVE" }, "placement_infos": { "placement_mode": "DEFAULT", "placement": "string", "cancel": "string", "depth_mode": "LEVEL" }, "reduce_only": true, "start_ladder_price": "string", "end_ladder_price": "string", "ladder_direction": "string", "ladder_profile": "string", "size_skew": 0.0, "ob_imbalance_cancel": true, "ob_imbalance_threshold": "0.75", "price_lock_bps": "5", "limit_is_arrival": true, "limit_bps": "-10", "timer_iceberg_delay": 0.5, "timer_iceberg_delay_min": 0, "timer_iceberg_delay_max": 10, "randomize_iceberg_timer": true, "extend_duration": true } } r = requests.post(f"{BASE}/api/v2/trading/order/create", data=json.dumps(payload) headers=signed_headers(payload)) print(r.json()) ``` ``` let payload = serde_json::json!({ "client_order_id": "ABC-12345^12-10-23", "exchange": "BINANCE", "subaccount": "string", "symbol": "string", "asset_category": "SPOT", "side": "BUY", "quantity": "string", "strategy": "TWAP", "limit_price": "2205.10", "limit_is_arrival": true, "start_time": "2024-01-22T22:05:00Z", "end_time": "2024-04-22T22:05:00Z", "clip_size_type": "ABSOLUTE", "clip_size_val": "0.01", "params": { "duration_seconds": "120", "trading_style": "PASSIVE", "urgency": "LOW", "pov_ratio": 5, "pov_risk": "LOW", "randomize_amount": true, "would": { "would_price": "string", "would_pct": "string", "would_style": "PASSIVE", "would_is_arrival": true, "would_bps": "5" }, "trigger": { "trigger_price": "string", "trigger_condition": "ABOVE" }, "placement_infos": { "placement_mode": "DEFAULT", "placement": "string", "cancel": "string", "depth_mode": "LEVEL" }, "reduce_only": true, "start_ladder_price": "string", "end_ladder_price": "string", "ladder_direction": "string", "ladder_profile": "string", "size_skew": 0.0, "ob_imbalance_cancel": true, "ob_imbalance_threshold": "0.75", "price_lock_bps": "5", "limit_is_arrival": true, "limit_bps": "-10", "timer_iceberg_delay": 0.5, "timer_iceberg_delay_min": 0, "timer_iceberg_delay_max": 10, "randomize_iceberg_timer": true, "extend_duration": true } }); let resp = client .post(format!("{BASE}/api/v2/trading/order/create")) .headers(signed_headers(&payload)) .json(&payload) .send()?; println!("{}", resp.text()?); ``` ``` payload := map[string]any{ "client_order_id": "ABC-12345^12-10-23", "exchange": "BINANCE", "subaccount": "string", "symbol": "string", "asset_category": "SPOT", "side": "BUY", "quantity": "string", "strategy": "TWAP", "limit_price": "2205.10", "limit_is_arrival": true, "start_time": "2024-01-22T22:05:00Z", "end_time": "2024-04-22T22:05:00Z", "clip_size_type": "ABSOLUTE", "clip_size_val": "0.01", "params": map[string]any{ "duration_seconds": "120", "trading_style": "PASSIVE", "urgency": "LOW", "pov_ratio": 5, "pov_risk": "LOW", "randomize_amount": true, "would": map[string]any{ "would_price": "string", "would_pct": "string", "would_style": "PASSIVE", "would_is_arrival": true, "would_bps": "5", }, "trigger": map[string]any{ "trigger_price": "string", "trigger_condition": "ABOVE", }, "placement_infos": map[string]any{ "placement_mode": "DEFAULT", "placement": "string", "cancel": "string", "depth_mode": "LEVEL", }, "reduce_only": true, "start_ladder_price": "string", "end_ladder_price": "string", "ladder_direction": "string", "ladder_profile": "string", "size_skew": 0.0, "ob_imbalance_cancel": true, "ob_imbalance_threshold": "0.75", "price_lock_bps": "5", "limit_is_arrival": true, "limit_bps": "-10", "timer_iceberg_delay": 0.5, "timer_iceberg_delay_min": 0, "timer_iceberg_delay_max": 10, "randomize_iceberg_timer": true, "extend_duration": true, }, } body, _ := json.Marshal(payload) req, _ := http.NewRequest("POST", BASE+"/api/v2/trading/order/create", bytes.NewReader(body)) for k, v := range signedHeaders(string(body)) { req.Header.Set(k, v) } req.Header.Set("Content-Type", "application/json") resp, err := http.DefaultClient.Do(req) if err != nil { log.Fatal(err) } defer resp.Body.Close() io.Copy(os.Stdout, resp.Body) ``` ``` String jsonBody = mapper.writeValueAsString(payload); HttpResponse resp = client.send( signedPost("/api/v2/trading/order/create", jsonBody), HttpResponse.BodyHandlers.ofString()); ``` ``` const payload: CreateParentOrderRequest = { "client_order_id": "ABC-12345^12-10-23", "exchange": "BINANCE", "subaccount": "string", "symbol": "string", "asset_category": "SPOT", "side": "BUY", "quantity": "string", "strategy": "TWAP", "limit_price": "2205.10", "limit_is_arrival": true, "start_time": "2024-01-22T22:05:00Z", "end_time": "2024-04-22T22:05:00Z", "clip_size_type": "ABSOLUTE", "clip_size_val": "0.01", "params": { "duration_seconds": "120", "trading_style": "PASSIVE", "urgency": "LOW", "pov_ratio": 5, "pov_risk": "LOW", "randomize_amount": true, "would": { "would_price": "string", "would_pct": "string", "would_style": "PASSIVE", "would_is_arrival": true, "would_bps": "5" }, "trigger": { "trigger_price": "string", "trigger_condition": "ABOVE" }, "placement_infos": { "placement_mode": "DEFAULT", "placement": "string", "cancel": "string", "depth_mode": "LEVEL" }, "reduce_only": true, "start_ladder_price": "string", "end_ladder_price": "string", "ladder_direction": "string", "ladder_profile": "string", "size_skew": 0.0, "ob_imbalance_cancel": true, "ob_imbalance_threshold": "0.75", "price_lock_bps": "5", "limit_is_arrival": true, "limit_bps": "-10", "timer_iceberg_delay": 0.5, "timer_iceberg_delay_min": 0, "timer_iceberg_delay_max": 10, "randomize_iceberg_timer": true, "extend_duration": true } }; const res = await fetch(`${BASE}/api/v2/trading/order/create`, { method: "POST", headers: signedHeaders(payload), body: JSON.stringify(payload), }); const data: OrderSummary = await res.json(); ``` ``` val jsonBody = mapper.writeValueAsString(payload) val request = signedPost("/api/v2/trading/order/create", jsonBody) val response = client.send(request, HttpResponse.BodyHandlers.ofString()) println(response.body()) ``` ``` std::string body = R"({ "client_order_id": "ABC-12345^12-10-23", "exchange": "BINANCE", "subaccount": "string", "symbol": "string", "asset_category": "SPOT", "side": "BUY", "quantity": "string", "strategy": "TWAP", "limit_price": "2205.10", "limit_is_arrival": true, "start_time": "2024-01-22T22:05:00Z", "end_time": "2024-04-22T22:05:00Z", "clip_size_type": "ABSOLUTE", "clip_size_val": "0.01", "params": { "duration_seconds": "120", "trading_style": "PASSIVE", "urgency": "LOW", "pov_ratio": 5, "pov_risk": "LOW", "randomize_amount": true, "would": { "would_price": "string", "would_pct": "string", "would_style": "PASSIVE", "would_is_arrival": true, "would_bps": "5" }, "trigger": { "trigger_price": "string", "trigger_condition": "ABOVE" }, "placement_infos": { "placement_mode": "DEFAULT", "placement": "string", "cancel": "string", "depth_mode": "LEVEL" }, "reduce_only": true, "start_ladder_price": "string", "end_ladder_price": "string", "ladder_direction": "string", "ladder_profile": "string", "size_skew": 0.0, "ob_imbalance_cancel": true, "ob_imbalance_threshold": "0.75", "price_lock_bps": "5", "limit_is_arrival": true, "limit_bps": "-10", "timer_iceberg_delay": 0.5, "timer_iceberg_delay_min": 0, "timer_iceberg_delay_max": 10, "randomize_iceberg_timer": true, "extend_duration": true } })"; cpr::Response r = cpr::Post( cpr::Url{BASE + "/api/v2/trading/order/create"}, signedHeaders(body), cpr::Header{{"Content-Type", "application/json"}}, cpr::Body{body}); std::cout << r.text << std::endl; ``` ``` const payload = { "client_order_id": "ABC-12345^12-10-23", "exchange": "BINANCE", "subaccount": "string", "symbol": "string", "asset_category": "SPOT", "side": "BUY", "quantity": "string", "strategy": "TWAP", "limit_price": "2205.10", "limit_is_arrival": true, "start_time": "2024-01-22T22:05:00Z", "end_time": "2024-04-22T22:05:00Z", "clip_size_type": "ABSOLUTE", "clip_size_val": "0.01", "params": { "duration_seconds": "120", "trading_style": "PASSIVE", "urgency": "LOW", "pov_ratio": 5, "pov_risk": "LOW", "randomize_amount": true, "would": { "would_price": "string", "would_pct": "string", "would_style": "PASSIVE", "would_is_arrival": true, "would_bps": "5" }, "trigger": { "trigger_price": "string", "trigger_condition": "ABOVE" }, "placement_infos": { "placement_mode": "DEFAULT", "placement": "string", "cancel": "string", "depth_mode": "LEVEL" }, "reduce_only": true, "start_ladder_price": "string", "end_ladder_price": "string", "ladder_direction": "string", "ladder_profile": "string", "size_skew": 0.0, "ob_imbalance_cancel": true, "ob_imbalance_threshold": "0.75", "price_lock_bps": "5", "limit_is_arrival": true, "limit_bps": "-10", "timer_iceberg_delay": 0.5, "timer_iceberg_delay_min": 0, "timer_iceberg_delay_max": 10, "randomize_iceberg_timer": true, "extend_duration": true } }; const res = await fetch(`${BASE}/api/v2/trading/order/create`, { method: "POST", headers: signedHeaders(payload), body: JSON.stringify(payload), }); console.log(await res.json()); ``` **Response** 201 ``` { "order_id": 0, "client_order_id": "ABC-12345^12-10-23", "status": "PENDING_NEW", "created_at": "2024-01-22T22:05:00Z", "message": "string", "error_code": "OTHER" } ``` # Create POST `https://api.pro.anboto.xyz/api/v2/strategies/campaigns/create` A delta-neutral long+short pair on Papertrade, repeated until stopped. 409 while the team already runs a campaign (one at a time per account), or while one in error still holds legs. **ApiKeyAuth** required. ### Body params `type` string required Campaign type; today only paper_farm Default: `paper_farm` `exchange_id` string required The venue to farm on; today only papertrade Default: `papertrade` `symbol` string required Anboto symbol, BTC/USDC:USDC or ETH/USDC:USDC Example: `BTC/USDC:USDC` `leverage` integer required Leverage of each leg, 1-1000 (the leverage guard caps it well below 1000 in practice) `margin_per_leg` number required Margin to post per leg at the start of a cycle, in USDC (>= 10) `target_move_bps` integer required Winning-leg move, in basis points, that closes a cycle (50-100) `max_cycles` integer Stop after this many cycles; omit or null for unlimited `budget_usdc` number Stop once this much USDC has been spent; omit or null for no cap `stop` [StrategyStopRules](https://api-docs.anboto.xyz/reference/schemas/#strategystoprules) Stop conditions the campaign watches on its own, besides an explicit stop/kill ### Headers | Header | | | | --------------- | ----------------- | -------- | | `X-API-KEY` | string | required | | `X-TIMESTAMP` | int64 ms | required | | `X-SIGN` | string | required | | `X-RECV-WINDOW` | int, default 5000 | | ### Responses | | | | --- | ------------------------------------------------------------------------------------------------------------------------------- | | 201 | The campaign, started | | 400 | Invalid parameter, or the leverage guard rejected the combination, `{"code", "error", "errors"?}` | | 401 | Unauthorized: missing or unknown API key | | 403 | Forbidden: the API key is read-only, or the paper_farm_bot feature is not enabled for this team, `{"code", "error", "errors"?}` | | 409 | The team already has an active campaign, `{"code", "error", "errors"?}` | | 429 | Rate limit exceeded, retry later, `{"code", "error", "errors"?}` | | 503 | The strategies service is unavailable, `{"code", "error", "errors"?}` | ### Response fields — [StrategyCampaign](https://api-docs.anboto.xyz/reference/schemas/#strategycampaign) `id` string Campaign id (UUID) `type` string Campaign type; today always paper_farm `status` enum running | paused | stopped | done | error — `running`, `paused`, `stopped`, `done`, `error` `stopping` boolean A graceful stop or a hard kill is under way. Independent of status: can be true while status stays error (the open legs are being closed before the campaign reaches stopped) `phase` string Cycle phase the runner is in: idle, opening, open, closing or settling `stop_reason` string Why a stopped/done campaign ended: cycles_done, budget_spent, session_key_expiring, queued_share, user_stop or user_kill. Empty while still running `cycles_done` integer Cycles completed so far `cycles_planned` integer max_cycles from create, or null for unlimited `paper_minted` number Total PAPER minted by this campaign's losing legs `usdc_converted` number Total USDC spent converting minted PAPER (haircut + fee) `queued_usdc` number Profit queued to fund a future cycle's margin instead of being paid out `haircut_paid` number Total haircut paid converting PAPER to USDC `fees_paid` number Total trading fees paid by this campaign `current_legs` array\[[StrategyCampaignLeg](https://api-docs.anboto.xyz/reference/schemas/#strategycampaignleg)\] Open legs of the current cycle (0 while idle, up to 2 while open) `current_legs[].position_id` string The venue's position id, or null while the open is still unconfirmed `current_legs[].side` string long or short `current_legs[].entry` number Entry (mark) price the leg opened at `current_legs[].move_pct` number Signed move since entry, in percent, from this leg's point of view `current_legs[].bust` number This leg's liquidation (bust) price `current_legs[].size` number Position size `current_legs[].margin` number Margin posted for this leg, in USDC `current_legs[].leverage` integer Leverage of this leg `current_legs[].mark_price` number Latest mark price used to watch this leg `current_legs[].parent_order_id` string The order id that opened this leg `current_legs[].opened_at` date-time UTC time the leg opened, ISO 8601 `last_cycle` [StrategyCampaignCycle](https://api-docs.anboto.xyz/reference/schemas/#strategycampaigncycle) The campaign's most recently closed cycle `last_cycle.pnl_usdc` number Net result of the cycle, in USDC (can be negative) `last_cycle.paper` number PAPER minted by the losing leg of this cycle `last_cycle.closed_at` date-time UTC time both legs were closed, ISO 8601 `last_cycle.multileg_order_id` string The multileg (or paired single) order id the close went through, when known `last_error` string Why the campaign is in error; empty otherwise `symbol` string Anboto symbol being farmed, e.g. BTC/USDC:USDC `leverage` integer Leverage of each leg `margin_per_leg` number Margin posted per leg at the start of a cycle, in USDC `target_move_bps` integer Winning-leg move, in basis points, that closes the cycle `budget_usdc` number budget_usdc from create, or null for no spend cap `stop` [StrategyStopRules](https://api-docs.anboto.xyz/reference/schemas/#strategystoprules) Stop conditions the campaign watches on its own, besides an explicit stop/kill `stop.queued_share_pct` number Stop once this percent (0-100) of a new cycle's margin would come from queued profit rather than fresh budget. Null or omitted: off `stop.stop_before_key_expiry` boolean Stop gracefully once the Papertrade session key has under an hour left, rather than risk a cycle stuck open past expiry Default: `true` `stop.hard_kill_on_stop` boolean If a stop rule fires mid-cycle, close both legs at market now instead of waiting for the target Default: `false` `created_at` date-time UTC time the campaign was created, ISO 8601 `started_at` date-time UTC time the campaign started, ISO 8601 `stopped_at` date-time UTC time the campaign stopped, ISO 8601, or null while still running ``` body='{ "type": "string", "exchange_id": "string", "symbol": "BTC/USDC:USDC", "leverage": 0, "margin_per_leg": 0.0, "target_move_bps": 0, "max_cycles": 0, "budget_usdc": 0.0, "stop": { "queued_share_pct": 0.0, "stop_before_key_expiry": true, "hard_kill_on_stop": true } }' curl -X POST "$BASE/api/v2/strategies/campaigns/create" \ -H "X-API-KEY: $API_KEY" -H "X-TIMESTAMP: $ts" \ -H "X-SIGN: $sign" \ -H "Content-Type: application/json" -d "$body" ``` ``` payload = { "type": "string", "exchange_id": "string", "symbol": "BTC/USDC:USDC", "leverage": 0, "margin_per_leg": 0.0, "target_move_bps": 0, "max_cycles": 0, "budget_usdc": 0.0, "stop": { "queued_share_pct": 0.0, "stop_before_key_expiry": true, "hard_kill_on_stop": true } } r = requests.post(f"{BASE}/api/v2/strategies/campaigns/create", data=json.dumps(payload) headers=signed_headers(payload)) print(r.json()) ``` ``` let payload = serde_json::json!({ "type": "string", "exchange_id": "string", "symbol": "BTC/USDC:USDC", "leverage": 0, "margin_per_leg": 0.0, "target_move_bps": 0, "max_cycles": 0, "budget_usdc": 0.0, "stop": { "queued_share_pct": 0.0, "stop_before_key_expiry": true, "hard_kill_on_stop": true } }); let resp = client .post(format!("{BASE}/api/v2/strategies/campaigns/create")) .headers(signed_headers(&payload)) .json(&payload) .send()?; println!("{}", resp.text()?); ``` ``` payload := map[string]any{ "type": "string", "exchange_id": "string", "symbol": "BTC/USDC:USDC", "leverage": 0, "margin_per_leg": 0.0, "target_move_bps": 0, "max_cycles": 0, "budget_usdc": 0.0, "stop": map[string]any{ "queued_share_pct": 0.0, "stop_before_key_expiry": true, "hard_kill_on_stop": true, }, } body, _ := json.Marshal(payload) req, _ := http.NewRequest("POST", BASE+"/api/v2/strategies/campaigns/create", bytes.NewReader(body)) for k, v := range signedHeaders(string(body)) { req.Header.Set(k, v) } req.Header.Set("Content-Type", "application/json") resp, err := http.DefaultClient.Do(req) if err != nil { log.Fatal(err) } defer resp.Body.Close() io.Copy(os.Stdout, resp.Body) ``` ``` String jsonBody = mapper.writeValueAsString(payload); HttpResponse resp = client.send( signedPost("/api/v2/strategies/campaigns/create", jsonBody), HttpResponse.BodyHandlers.ofString()); ``` ``` const payload: CreateStrategyCampaignRequest = { "type": "string", "exchange_id": "string", "symbol": "BTC/USDC:USDC", "leverage": 0, "margin_per_leg": 0.0, "target_move_bps": 0, "max_cycles": 0, "budget_usdc": 0.0, "stop": { "queued_share_pct": 0.0, "stop_before_key_expiry": true, "hard_kill_on_stop": true } }; const res = await fetch(`${BASE}/api/v2/strategies/campaigns/create`, { method: "POST", headers: signedHeaders(payload), body: JSON.stringify(payload), }); const data: StrategyCampaign = await res.json(); ``` ``` val jsonBody = mapper.writeValueAsString(payload) val request = signedPost("/api/v2/strategies/campaigns/create", jsonBody) val response = client.send(request, HttpResponse.BodyHandlers.ofString()) println(response.body()) ``` ``` std::string body = R"({ "type": "string", "exchange_id": "string", "symbol": "BTC/USDC:USDC", "leverage": 0, "margin_per_leg": 0.0, "target_move_bps": 0, "max_cycles": 0, "budget_usdc": 0.0, "stop": { "queued_share_pct": 0.0, "stop_before_key_expiry": true, "hard_kill_on_stop": true } })"; cpr::Response r = cpr::Post( cpr::Url{BASE + "/api/v2/strategies/campaigns/create"}, signedHeaders(body), cpr::Header{{"Content-Type", "application/json"}}, cpr::Body{body}); std::cout << r.text << std::endl; ``` ``` const payload = { "type": "string", "exchange_id": "string", "symbol": "BTC/USDC:USDC", "leverage": 0, "margin_per_leg": 0.0, "target_move_bps": 0, "max_cycles": 0, "budget_usdc": 0.0, "stop": { "queued_share_pct": 0.0, "stop_before_key_expiry": true, "hard_kill_on_stop": true } }; const res = await fetch(`${BASE}/api/v2/strategies/campaigns/create`, { method: "POST", headers: signedHeaders(payload), body: JSON.stringify(payload), }); console.log(await res.json()); ``` **Response** 201 ``` { "id": "string", "type": "string", "status": "running", "stopping": true, "phase": "string", "stop_reason": "string", "cycles_done": 0, "cycles_planned": 0, "paper_minted": 0.0, "usdc_converted": 0.0, "queued_usdc": 0.0, "haircut_paid": 0.0, "fees_paid": 0.0, "current_legs": [ { "position_id": "string", "side": "string", "entry": 0.0, "move_pct": 0.0, "bust": 0.0, "size": 0.0, "margin": 0.0, "leverage": 0, "mark_price": 0.0, "parent_order_id": "string", "opened_at": "string" } ], "last_cycle": { "pnl_usdc": 0.0, "paper": 0.0, "closed_at": "string", "multileg_order_id": "string" }, "last_error": "string", "symbol": "string", "leverage": 0, "margin_per_leg": 0.0, "target_move_bps": 0, "budget_usdc": 0.0, "stop": { "queued_share_pct": 0.0, "stop_before_key_expiry": true, "hard_kill_on_stop": true }, "created_at": "string", "started_at": "string", "stopped_at": "string" } ``` # Exchanges GET `https://api.pro.anboto.xyz/api/v2/data/exchanges` Return a list of exchanges available to trade **ApiKeyAuth** required. ### Headers | Header | | | | --------------- | ----------------- | -------- | | `X-API-KEY` | string | required | | `X-TIMESTAMP` | int64 ms | required | | `X-SIGN` | string | required | | `X-RECV-WINDOW` | int, default 5000 | | ### Responses | | | | --- | ---------------------------------------- | | 200 | The exchanges. | | 401 | Unauthorized: missing or unknown API key | | 429 | Rate limit exceeded, retry later | ``` curl -X GET "$BASE/api/v2/data/exchanges" \ -H "X-API-KEY: $API_KEY" -H "X-TIMESTAMP: $ts" \ -H "X-SIGN: $sign" ``` ``` r = requests.get(f"{BASE}/api/v2/data/exchanges", headers=signed_headers_query({})) print(r.json()) ``` ``` let resp = client .get(format!("{BASE}/api/v2/data/exchanges")) .headers(signed_headers_query(¶ms)) .send()?; println!("{}", resp.text()?); ``` ``` req, _ := http.NewRequest("GET", BASE+"/api/v2/data/exchanges", nil) for k, v := range signedHeadersQuery(req.URL.Query()) { req.Header.Set(k, v) } resp, err := http.DefaultClient.Do(req) if err != nil { log.Fatal(err) } defer resp.Body.Close() io.Copy(os.Stdout, resp.Body) ``` ``` HttpResponse resp = client.send( signedGet("/api/v2/data/exchanges"), HttpResponse.BodyHandlers.ofString()); ``` ``` const res = await fetch(`${BASE}/api/v2/data/exchanges`, { method: "GET", headers: signedHeadersQuery(params), }); const data = await res.json(); ``` ``` val request = signedGet("/api/v2/data/exchanges") val response = client.send(request, HttpResponse.BodyHandlers.ofString()) println(response.body()) ``` ``` cpr::Response r = cpr::Get( cpr::Url{BASE + "/api/v2/data/exchanges"}, signedHeadersQuery(params)); std::cout << r.text << std::endl; ``` ``` const res = await fetch(`${BASE}/api/v2/data/exchanges`, { method: "GET", headers: signedHeadersQuery(params), }); console.log(await res.json()); ``` **Response** 200 ``` "string" ``` # Find orders GET `https://api.pro.anboto.xyz/api/v2/trading/order/find` Only matched order within 3 days will be return **ApiKeyAuth** required. ### Query params `startMs` integer The start time for the query as ms since epoch `endMs` integer The end time for the query as ms since epoch `limit` integer The maximum number of orders to return in the results `include_trades` boolean Whether to include the fills (trades) of the matching orders `include_fees` boolean Whether to include aggregated fees per currency for the matching orders ### Headers | Header | | | | --------------- | ----------------- | -------- | | `X-API-KEY` | string | required | | `X-TIMESTAMP` | int64 ms | required | | `X-SIGN` | string | required | | `X-RECV-WINDOW` | int, default 5000 | | ### Responses | | | | --- | ---------------------------------------- | | 200 | The list of matching orders. | | 401 | Unauthorized: missing or unknown API key | | 429 | Rate limit exceeded, retry later | ### Response fields — [OrderDetailsList](https://api-docs.anboto.xyz/reference/schemas/#orderdetailslist) `orders` array\[[OrderDetails](https://api-docs.anboto.xyz/reference/schemas/#orderdetails)\] required The list of order details for separate orders. `orders[].order_id` integer The Anboto generated order id Example: `123456` `orders[].client_order_id` string The client provided order id Example: `xxx-yyy-zzz` `orders[].symbol` string The order symbol in Anboto's symbology `orders[].status` [enum](https://api-docs.anboto.xyz/reference/schemas/#orderstatus) The order status — `PENDING_NEW`, `ACCEPTED`, `REJECTED`, `PARTIALLY_FILLED`, `FILLED`, `PENDING_CANCEL`, `CANCELLED`, `PENDING_PAUSE`, … (12 values) `orders[].asset_class` [enum](https://api-docs.anboto.xyz/reference/schemas/#assetcategory) The Asset category of the order. — `SPOT`, `FUTURE` Example: `SPOT` `orders[].exchange` [enum](https://api-docs.anboto.xyz/reference/schemas/#tradingexchange) The exchanges available for order placement via the API — `BINANCE`, `HUOBI`, `GATEIO`, `KRAKEN`, `KUCOIN`, `OKX`, `BYBIT`, `BITGET`, … (17 values) `orders[].strategy` [enum](https://api-docs.anboto.xyz/reference/schemas/#executionstrategy) The execution strategy for the order. — `TWAP`, `VWAP`, `ICEBERG`, `POV`, `MARKET`, `LIMIT`, `IS`, `SCALE` Example: `VWAP` `orders[].start_time` number The time when the order start trading from epoch time in ms `orders[].end_time` number The scheduled end of the execution from epoch time in ms while the order is working (e.g. start_time + duration for a TWAP); the time the order reached its terminal state once finished `orders[].quantity` number The total quantity of the parent order in base asset, as placed. Absent for value-target (notional) orders, see target_value Example: `6` `orders[].filled_quantity` number required The absolute amount of the order quantity filled Example: `0` `orders[].leaves_quantity` number required The absolute amount of the parent order quantity remaining to be filled (quantity - filled_quantity, 0 once the order is terminal). This is the parent order's remainder, never the leaves of the child order currently working it Example: `0` `orders[].progress` number Execution progress of the parent order between 0 and 1: filled_quantity / quantity, or filled notional / target_value for value-target orders. Same computation as the WebSocket order topic orderProgress; 1 once FILLED. Absent when the parent order is not known Example: `0.1783` `orders[].side` [enum](https://api-docs.anboto.xyz/reference/schemas/#side) The side of the book to trade. — `BUY`, `SELL` `orders[].last_quantity` number required The last qty received in a fill from the exchange Example: `0` `orders[].last_price` number required The last price executed on the exchange Example: `0` `orders[].average_price` number required The average execution price of the order Example: `0` `orders[].limit_price` number The limit price of the parent order, if one was set `orders[].clip_size_type` [enum](https://api-docs.anboto.xyz/reference/schemas/#clipsizetype) The clip size for the child orders. The default is AUTOMATIC — `ABSOLUTE`, `PERCENTAGE`, `AUTOMATIC`, `ORDER_COUNT` `orders[].clip_size_val` number The clip size value of the parent order, as placed `orders[].target_value` number The target notional of a value-target order (e.g. a multi-leg order leg); quantity is absent for such orders `orders[].params` [OrderParams](https://api-docs.anboto.xyz/reference/schemas/#orderparams) The advanced order parameters to modify the execution behavior. `orders[].trades` array\[[TradeDetails](https://api-docs.anboto.xyz/reference/schemas/#tradedetails)\] The list of trades associated with this order when include_trades=true `orders[].trades[].trade_id` string The trade id assigned by the exchange, or the Anboto platform trade id when no exchange trade id was captured Example: `1204004183` `orders[].trades[].symbol` string required The symbol of the fill in Anboto's symbology Example: `BTC/USDT:USDT` `orders[].trades[].exchange_order_id` string The exchange order id of the child order the fill belongs to Example: `151990408` `orders[].trades[].client_order_id` string The client order id of the child order the fill belongs to `orders[].trades[].quantity` number required The absolute amount filled by this trade, in base asset Example: `0.5` `orders[].trades[].price` number required The traded price Example: `92.91` `orders[].trades[].direction` enum The direction of the trade — `BUY`, `SELL` Example: `BUY` `orders[].trades[].maker_or_taker` enum Whether the fill was made as maker or taker — `MAKER`, `TAKER` Example: `MAKER` `orders[].trades[].exec_time` integer The execution time of the trade as ms since epoch Example: `1758276000000` `orders[].trades[].fee` number The fee charged on the trade, in fee_currency Example: `0.0021` `orders[].trades[].fee_currency` string The asset the fee was charged in Example: `USDT` `orders[].trades[].parent_order_id` integer The Anboto id of the parent order the fill belongs to (the order_id of the enclosing order) Example: `596990285759373312` `orders[].trades[].child_order_id` integer The Anboto id of the child (slice) order that executed on the exchange; the WebSocket trade topic carries it as order_id Example: `596990290020118528` `orders[].fees_infos` object Aggregated fees per currency when include_fees=true ``` curl -X GET "$BASE/api/v2/trading/order/find?startMs=0" \ -H "X-API-KEY: $API_KEY" -H "X-TIMESTAMP: $ts" \ -H "X-SIGN: $sign" ``` ``` params = {"startMs": ..., "endMs": ..., "limit": ..., "include_trades": ..., "include_fees": ...} r = requests.get(f"{BASE}/api/v2/trading/order/find", params=params headers=signed_headers_query(params)) print(r.json()) ``` ``` let resp = client .get(format!("{BASE}/api/v2/trading/order/find?startMs=0")) .headers(signed_headers_query(¶ms)) .send()?; println!("{}", resp.text()?); ``` ``` req, _ := http.NewRequest("GET", BASE+"/api/v2/trading/order/find?startMs=0", nil) for k, v := range signedHeadersQuery(req.URL.Query()) { req.Header.Set(k, v) } resp, err := http.DefaultClient.Do(req) if err != nil { log.Fatal(err) } defer resp.Body.Close() io.Copy(os.Stdout, resp.Body) ``` ``` HttpResponse resp = client.send( signedGet("/api/v2/trading/order/find?startMs=0"), HttpResponse.BodyHandlers.ofString()); ``` ``` const res = await fetch(`${BASE}/api/v2/trading/order/find?startMs=0`, { method: "GET", headers: signedHeadersQuery(params), }); const data: OrderDetailsList = await res.json(); ``` ``` val request = signedGet("/api/v2/trading/order/find?startMs=0") val response = client.send(request, HttpResponse.BodyHandlers.ofString()) println(response.body()) ``` ``` cpr::Response r = cpr::Get( cpr::Url{BASE + "/api/v2/trading/order/find?startMs=0"}, signedHeadersQuery(params)); std::cout << r.text << std::endl; ``` ``` const res = await fetch(`${BASE}/api/v2/trading/order/find?startMs=0`, { method: "GET", headers: signedHeadersQuery(params), }); console.log(await res.json()); ``` **Response** 200 ``` { "orders": [ { "order_id": 123456, "client_order_id": "xxx-yyy-zzz", "symbol": "string", "status": "PENDING_NEW", "asset_class": "SPOT", "exchange": "BINANCE", "strategy": "TWAP", "start_time": 0.0, "end_time": 0.0, "quantity": 6, "filled_quantity": 0, "leaves_quantity": 0, "progress": 0.1783, "side": "BUY", "last_quantity": 0, "last_price": 0, "average_price": 0, "limit_price": 0.0, "clip_size_type": "ABSOLUTE", "clip_size_val": 0.0, "target_value": 0.0, "params": { "duration_seconds": "120", "trading_style": "PASSIVE", "urgency": "LOW", "pov_ratio": 5, "pov_risk": "LOW", "randomize_amount": true, "would": {}, "trigger": {}, "placement_infos": {}, "reduce_only": true, "start_ladder_price": "string", "end_ladder_price": "string", "ladder_direction": "string", "ladder_profile": "string", "size_skew": 0.0, "ob_imbalance_cancel": true, "ob_imbalance_threshold": "0.75", "price_lock_bps": "5", "limit_is_arrival": true, "limit_bps": "-10", "timer_iceberg_delay": 0.5, "timer_iceberg_delay_min": 0, "timer_iceberg_delay_max": 10, "randomize_iceberg_timer": true, "extend_duration": true }, "trades": [ {} ], "fees_infos": {} } ] } ``` # Flows GET `https://api.pro.anboto.xyz/api/v2/portfolio/flows` The flows the daily PnL subtracts, deduplicated and signed: `net_flow_usd` is a flow's contribution to `net_flows` (positive in, negative out; 0 with `counted_in_pnl: false` for transfers within one account and for unknown directions). When the asset could not be priced, `usd_value` and `net_flow_usd` are null (`counted_in_pnl: false`; transfers within one account stay 0) and the flow is counted in `totals.unpriced_count`. The window is half-open, \[startMs, endMs): a flow at exactly endMs is not returned, so the next window starts at `to_ms`. Oldest first; pass `next_cursor` back as `cursor` for the next page; `totals` always cover the whole window. **ApiKeyAuth** required. ### Query params `accounts` string Comma-separated accounts: `binance` = every account on Binance (main and subaccounts), `binance:` = the main account only, `binance:Sub1` = that subaccount. Omit for every account of the team. At most 20 items. Unlike /api/v2/trading/\*, a missing subaccount means all accounts. Sign the raw value, e.g. `accounts=binance:,bybit:Sub1`. Example: `binance` `startMs` integer Start, ms since epoch (inclusive). Defaults to 30 days before endMs. Must be before endMs `endMs` integer End, ms since epoch (exclusive: a flow at exactly endMs is not returned). Defaults to now; at most 4102444800000 (2100-01-01). The window spans at most 366 days `types` string Comma-separated flow types: deposit, withdrawal, internal_transfer. Default all Example: `deposit,withdrawal` `external` boolean true: only flows that cross the team's boundary (deposits, withdrawals); false: only transfers inside the team. Default both `limit` integer Flows per page, 1 to 500 (default 500) Default: `500` `cursor` string `next_cursor` of the previous page ### Headers | Header | | | | --------------- | ----------------- | -------- | | `X-API-KEY` | string | required | | `X-TIMESTAMP` | int64 ms | required | | `X-SIGN` | string | required | | `X-RECV-WINDOW` | int, default 5000 | | ### Responses | | | | --- | ---------------------------------------- | | 200 | The flows | | 400 | Invalid parameter, | | 401 | Unauthorized: missing or unknown API key | | 429 | Rate limit exceeded, retry later | | 503 | The portfolio service is unavailable, | ### Response fields — [PortfolioFlowsResponse](https://api-docs.anboto.xyz/reference/schemas/#portfolioflowsresponse) `from_ms` integer required Start of the window, ms since epoch (inclusive) `to_ms` integer required End of the window, ms since epoch (exclusive): a flow at exactly to_ms is not in this window. Pass it as startMs to read the next window `flows` array\[[FlowRecord](https://api-docs.anboto.xyz/reference/schemas/#flowrecord)\] required Flows of this page, oldest first `flows[].id` string required Stable identifier of the flow `flows[].time` integer required Event time, ms since epoch `flows[].exchange` string required `flows[].subaccount` string required "" is the main account `flows[].type` enum required `deposit`, `withdrawal`, `internal_transfer` `flows[].direction` enum required Direction for this account — `in`, `out`, `internal`, `unknown` `flows[].external` boolean required True for flows that cross the team's boundary (deposits and withdrawals) `flows[].asset` string required `flows[].qty` number required Absolute amount of the asset, with every stored decimal digit `flows[].usd_value` number required USD value at the event time; null when the asset could not be priced `flows[].net_flow_usd` number required Signed contribution to the total-scope net_flows of the daily PnL (positive in, negative out). 0 for transfers within one account (whatever the price) and for unknown directions. null when the asset could not be priced: the flow is then not in the USD totals and is counted in totals.unpriced_count. counted_in_pnl is false whenever net_flow_usd is 0 for those reasons or null `flows[].counted_in_pnl` boolean required Whether the flow moves net_flows of the daily PnL: true when net_flow_usd is not null and direction is in or out `flows[].source` string required Exchange history the flow was read from, e.g. binance_deposit, binance_sub_transfer `totals` [FlowTotals](https://api-docs.anboto.xyz/reference/schemas/#flowtotals) required Sums of net_flow_usd over the whole window and selection `totals.deposits_usd` number required Sum of deposits (≥ 0) `totals.withdrawals_usd` number required Sum of withdrawals, signed (≤ 0) `totals.net_external_usd` number required deposits_usd + withdrawals_usd `totals.net_internal_usd` number required Net of internal transfers counted in PnL (non-zero when the selection is part of the team) `totals.unpriced_count` integer required Flows whose net_flow_usd is null (unpriced); they are not in the USD sums `next_cursor` string required Pass as `cursor` to read the next page; null on the last page ``` curl -X GET "$BASE/api/v2/portfolio/flows?accounts=string" \ -H "X-API-KEY: $API_KEY" -H "X-TIMESTAMP: $ts" \ -H "X-SIGN: $sign" ``` ``` params = {"accounts": ..., "startMs": ..., "endMs": ..., "types": ..., "external": ..., "limit": ..., "cursor": ...} r = requests.get(f"{BASE}/api/v2/portfolio/flows", params=params headers=signed_headers_query(params)) print(r.json()) ``` ``` let resp = client .get(format!("{BASE}/api/v2/portfolio/flows?accounts=string")) .headers(signed_headers_query(¶ms)) .send()?; println!("{}", resp.text()?); ``` ``` req, _ := http.NewRequest("GET", BASE+"/api/v2/portfolio/flows?accounts=string", nil) for k, v := range signedHeadersQuery(req.URL.Query()) { req.Header.Set(k, v) } resp, err := http.DefaultClient.Do(req) if err != nil { log.Fatal(err) } defer resp.Body.Close() io.Copy(os.Stdout, resp.Body) ``` ``` HttpResponse resp = client.send( signedGet("/api/v2/portfolio/flows?accounts=string"), HttpResponse.BodyHandlers.ofString()); ``` ``` const res = await fetch(`${BASE}/api/v2/portfolio/flows?accounts=string`, { method: "GET", headers: signedHeadersQuery(params), }); const data: PortfolioFlowsResponse = await res.json(); ``` ``` val request = signedGet("/api/v2/portfolio/flows?accounts=string") val response = client.send(request, HttpResponse.BodyHandlers.ofString()) println(response.body()) ``` ``` cpr::Response r = cpr::Get( cpr::Url{BASE + "/api/v2/portfolio/flows?accounts=string"}, signedHeadersQuery(params)); std::cout << r.text << std::endl; ``` ``` const res = await fetch(`${BASE}/api/v2/portfolio/flows?accounts=string`, { method: "GET", headers: signedHeadersQuery(params), }); console.log(await res.json()); ``` **Response** 200 ``` { "from_ms": 0, "to_ms": 0, "flows": [ { "id": "string", "time": 0, "exchange": "string", "subaccount": "string", "type": "deposit", "direction": "in", "external": true, "asset": "string", "qty": 0.0, "usd_value": 0.0, "net_flow_usd": 0.0, "counted_in_pnl": true, "source": "string" } ], "totals": { "deposits_usd": 0.0, "withdrawals_usd": 0.0, "net_external_usd": 0.0, "net_internal_usd": 0.0, "unpriced_count": 0 }, "next_cursor": "string" } ``` # Funding rate history GET `https://api.pro.anboto.xyz/api/v2/data/fundingRateHistory` Return the funding rate history for a symbol on an exchange. Both 'exchange' and 'symbol' are required. **ApiKeyAuth** required. ### Query params `exchange` string The exchange to return funding rate history for `symbol` string The symbol to return funding rate history for ### Headers | Header | | | | --------------- | ----------------- | -------- | | `X-API-KEY` | string | required | | `X-TIMESTAMP` | int64 ms | required | | `X-SIGN` | string | required | | `X-RECV-WINDOW` | int, default 5000 | | ### Responses | | | | --- | ---------------------------------------- | | 200 | The last funding rates. | | 401 | Unauthorized: missing or unknown API key | | 429 | Rate limit exceeded, retry later | ### Response fields — [FundingRate](https://api-docs.anboto.xyz/reference/schemas/#fundingrate) `exchange` string required `symbol` string required `time` date-time required `nextTime` date-time required `rate` number required `nextRate` number `markPrice` number ``` curl -X GET "$BASE/api/v2/data/fundingRateHistory?exchange=string" \ -H "X-API-KEY: $API_KEY" -H "X-TIMESTAMP: $ts" \ -H "X-SIGN: $sign" ``` ``` params = {"exchange": ..., "symbol": ...} r = requests.get(f"{BASE}/api/v2/data/fundingRateHistory", params=params headers=signed_headers_query(params)) print(r.json()) ``` ``` let resp = client .get(format!("{BASE}/api/v2/data/fundingRateHistory?exchange=string")) .headers(signed_headers_query(¶ms)) .send()?; println!("{}", resp.text()?); ``` ``` req, _ := http.NewRequest("GET", BASE+"/api/v2/data/fundingRateHistory?exchange=string", nil) for k, v := range signedHeadersQuery(req.URL.Query()) { req.Header.Set(k, v) } resp, err := http.DefaultClient.Do(req) if err != nil { log.Fatal(err) } defer resp.Body.Close() io.Copy(os.Stdout, resp.Body) ``` ``` HttpResponse resp = client.send( signedGet("/api/v2/data/fundingRateHistory?exchange=string"), HttpResponse.BodyHandlers.ofString()); ``` ``` const res = await fetch(`${BASE}/api/v2/data/fundingRateHistory?exchange=string`, { method: "GET", headers: signedHeadersQuery(params), }); const data: FundingRate = await res.json(); ``` ``` val request = signedGet("/api/v2/data/fundingRateHistory?exchange=string") val response = client.send(request, HttpResponse.BodyHandlers.ofString()) println(response.body()) ``` ``` cpr::Response r = cpr::Get( cpr::Url{BASE + "/api/v2/data/fundingRateHistory?exchange=string"}, signedHeadersQuery(params)); std::cout << r.text << std::endl; ``` ``` const res = await fetch(`${BASE}/api/v2/data/fundingRateHistory?exchange=string`, { method: "GET", headers: signedHeadersQuery(params), }); console.log(await res.json()); ``` **Response** 200 ``` { "exchange": "string", "symbol": "string", "time": "string", "nextTime": "string", "rate": 0.0, "nextRate": 0.0, "markPrice": 0.0 } ``` # Get account margin GET `https://api.pro.anboto.xyz/api/v2/trading/margin` Account value is `equity`, which already includes unrealised PnL. `position_value` is exposure, not money. `remaining_cushion`, `liq_distance`, and `vol_cover` measure margin the same way on every exchange; they are absent for Binance portfolio-margin and Kraken accounts, and when price history is missing. `raw_margin_ratio` is the exchange's own account ratio, as the exchange reports it. Fields the exchange does not report are omitted. An exchange without support, or a venue-side failure, returns 400 with {"error": "..."}. **ApiKeyAuth** required. ### Query params `exchange` [enum](https://api-docs.anboto.xyz/reference/schemas/#tradingexchange) required The exchange — `BINANCE`, `HUOBI`, `GATEIO`, `KRAKEN`, `KUCOIN`, `OKX`, `BYBIT`, `BITGET`, `WOO`, `MEXC`, `BULLISH`, `B2C2`, `COINBASE_PRIME`, `COINBASE_INTL`, … (17 values) `subaccount` string Sub-account ### Headers | Header | | | | --------------- | ----------------- | -------- | | `X-API-KEY` | string | required | | `X-TIMESTAMP` | int64 ms | required | | `X-SIGN` | string | required | | `X-RECV-WINDOW` | int, default 5000 | | ### Responses | | | | --- | ------------------------------------------------------------------------ | | 200 | The account margin summary | | 400 | The exchange does not support a margin summary, or the venue call failed | | 401 | Unauthorized: missing or unknown API key | | 429 | Rate limit exceeded, retry later | ### Response fields — [AccountMarginResponse](https://api-docs.anboto.xyz/reference/schemas/#accountmarginresponse) `equity` number Account equity: wallet balance plus unrealised PnL `balance` number Wallet balance, excluding unrealised PnL `unrealized_pnl` number Unrealised PnL across open positions `position_value` number Total notional of open positions (exposure, not account value) `total_initial_margin` number Initial margin locked by open positions `total_maint_margin` number Maintenance margin requirement `total_order_margin` number Margin locked by open orders, where the exchange reports it separately `margin_ratio` number Maintenance margin over equity, normalised to 0..1 (liquidation approached at 1) `raw_margin_ratio` number Venue-native account margin ratio as sent (conventions differ). Omitted when the venue has no native account ratio. `raw_margin_field` string Venue JSON key for raw_margin_ratio, e.g. uniMMR, mgnRatio, accountMMRate. `remaining_cushion` number 1 minus margin_ratio. Negative once equity is already below maintenance margin. `liq_distance` number (equity − maintenance margin) / notional. Absent for Binance portfolio-margin and Kraken accounts. `vol_cover` number Pessimistic volatility cover: (equity − maintenance margin) / Σ(|notional| × σ). Absent for Binance portfolio-margin and Kraken accounts, with no open positions, or when price history is missing. `vol_sigma_window` string Label for the σ window used in vol_cover, e.g. 24h `margin_estimated` boolean True when maintenance margin was estimated (Lighter) rather than reported by the venue `effective_leverage` number Position value over equity `available_balance` number Balance available to open new positions `account_mode` string Exchange account mode, where reported (for example cross or isolated) ``` curl -X GET "$BASE/api/v2/trading/margin?exchange=BINANCE" \ -H "X-API-KEY: $API_KEY" -H "X-TIMESTAMP: $ts" \ -H "X-SIGN: $sign" ``` ``` params = {"exchange": ..., "subaccount": ...} r = requests.get(f"{BASE}/api/v2/trading/margin", params=params headers=signed_headers_query(params)) print(r.json()) ``` ``` let resp = client .get(format!("{BASE}/api/v2/trading/margin?exchange=BINANCE")) .headers(signed_headers_query(¶ms)) .send()?; println!("{}", resp.text()?); ``` ``` req, _ := http.NewRequest("GET", BASE+"/api/v2/trading/margin?exchange=BINANCE", nil) for k, v := range signedHeadersQuery(req.URL.Query()) { req.Header.Set(k, v) } resp, err := http.DefaultClient.Do(req) if err != nil { log.Fatal(err) } defer resp.Body.Close() io.Copy(os.Stdout, resp.Body) ``` ``` HttpResponse resp = client.send( signedGet("/api/v2/trading/margin?exchange=BINANCE"), HttpResponse.BodyHandlers.ofString()); ``` ``` const res = await fetch(`${BASE}/api/v2/trading/margin?exchange=BINANCE`, { method: "GET", headers: signedHeadersQuery(params), }); const data: AccountMarginResponse = await res.json(); ``` ``` val request = signedGet("/api/v2/trading/margin?exchange=BINANCE") val response = client.send(request, HttpResponse.BodyHandlers.ofString()) println(response.body()) ``` ``` cpr::Response r = cpr::Get( cpr::Url{BASE + "/api/v2/trading/margin?exchange=BINANCE"}, signedHeadersQuery(params)); std::cout << r.text << std::endl; ``` ``` const res = await fetch(`${BASE}/api/v2/trading/margin?exchange=BINANCE`, { method: "GET", headers: signedHeadersQuery(params), }); console.log(await res.json()); ``` **Response** 200 ``` { "equity": 0.0, "balance": 0.0, "unrealized_pnl": 0.0, "position_value": 0.0, "total_initial_margin": 0.0, "total_maint_margin": 0.0, "total_order_margin": 0.0, "margin_ratio": 0.0, "raw_margin_ratio": 0.0, "raw_margin_field": "string", "remaining_cushion": 0.0, "liq_distance": 0.0, "vol_cover": 0.0, "vol_sigma_window": "string", "margin_estimated": true, "effective_leverage": 0.0, "available_balance": 0.0, "account_mode": "string" } ``` # Get balance GET `https://api.pro.anboto.xyz/api/v2/trading/balance` shows the asset balance > 0 **ApiKeyAuth** required. ### Query params `exchange` [enum](https://api-docs.anboto.xyz/reference/schemas/#tradingexchange) required The exchange — `BINANCE`, `HUOBI`, `GATEIO`, `KRAKEN`, `KUCOIN`, `OKX`, `BYBIT`, `BITGET`, `WOO`, `MEXC`, `BULLISH`, `B2C2`, `COINBASE_PRIME`, `COINBASE_INTL`, … (17 values) `subaccount` string Sub-account ### Headers | Header | | | | --------------- | ----------------- | -------- | | `X-API-KEY` | string | required | | `X-TIMESTAMP` | int64 ms | required | | `X-SIGN` | string | required | | `X-RECV-WINDOW` | int, default 5000 | | ### Responses | | | | --- | ---------------------------------------- | | 200 | The list of asset balance > 0 | | 401 | Unauthorized: missing or unknown API key | | 429 | Rate limit exceeded, retry later | ### Response fields `[].balance` number The total balance of the asset `[].free` number The balance available for trading `[].symbol` string The asset symbol Example: `BTC` ``` curl -X GET "$BASE/api/v2/trading/balance?exchange=BINANCE" \ -H "X-API-KEY: $API_KEY" -H "X-TIMESTAMP: $ts" \ -H "X-SIGN: $sign" ``` ``` params = {"exchange": ..., "subaccount": ...} r = requests.get(f"{BASE}/api/v2/trading/balance", params=params headers=signed_headers_query(params)) print(r.json()) ``` ``` let resp = client .get(format!("{BASE}/api/v2/trading/balance?exchange=BINANCE")) .headers(signed_headers_query(¶ms)) .send()?; println!("{}", resp.text()?); ``` ``` req, _ := http.NewRequest("GET", BASE+"/api/v2/trading/balance?exchange=BINANCE", nil) for k, v := range signedHeadersQuery(req.URL.Query()) { req.Header.Set(k, v) } resp, err := http.DefaultClient.Do(req) if err != nil { log.Fatal(err) } defer resp.Body.Close() io.Copy(os.Stdout, resp.Body) ``` ``` HttpResponse resp = client.send( signedGet("/api/v2/trading/balance?exchange=BINANCE"), HttpResponse.BodyHandlers.ofString()); ``` ``` const res = await fetch(`${BASE}/api/v2/trading/balance?exchange=BINANCE`, { method: "GET", headers: signedHeadersQuery(params), }); const data = await res.json(); ``` ``` val request = signedGet("/api/v2/trading/balance?exchange=BINANCE") val response = client.send(request, HttpResponse.BodyHandlers.ofString()) println(response.body()) ``` ``` cpr::Response r = cpr::Get( cpr::Url{BASE + "/api/v2/trading/balance?exchange=BINANCE"}, signedHeadersQuery(params)); std::cout << r.text << std::endl; ``` ``` const res = await fetch(`${BASE}/api/v2/trading/balance?exchange=BINANCE`, { method: "GET", headers: signedHeadersQuery(params), }); console.log(await res.json()); ``` **Response** 200 ``` [ { "balance": 0.0, "free": 0.0, "symbol": "BTC" } ] ``` # Get open orders GET `https://api.pro.anboto.xyz/api/v2/trading/order/open` All orders that are not in a terminal state will be returned **ApiKeyAuth** required. ### Query params `include_trades` boolean Whether to include the fills (trades) of the open orders, default false `include_fees` boolean Whether to include aggregated fees per currency for the open orders, default false ### Headers | Header | | | | --------------- | ----------------- | -------- | | `X-API-KEY` | string | required | | `X-TIMESTAMP` | int64 ms | required | | `X-SIGN` | string | required | | `X-RECV-WINDOW` | int, default 5000 | | ### Responses | | | | --- | ---------------------------------------- | | 200 | The list of open orders. | | 401 | Unauthorized: missing or unknown API key | | 429 | Rate limit exceeded, retry later | ### Response fields — [OrderDetailsList](https://api-docs.anboto.xyz/reference/schemas/#orderdetailslist) `orders` array\[[OrderDetails](https://api-docs.anboto.xyz/reference/schemas/#orderdetails)\] required The list of order details for separate orders. `orders[].order_id` integer The Anboto generated order id Example: `123456` `orders[].client_order_id` string The client provided order id Example: `xxx-yyy-zzz` `orders[].symbol` string The order symbol in Anboto's symbology `orders[].status` [enum](https://api-docs.anboto.xyz/reference/schemas/#orderstatus) The order status — `PENDING_NEW`, `ACCEPTED`, `REJECTED`, `PARTIALLY_FILLED`, `FILLED`, `PENDING_CANCEL`, `CANCELLED`, `PENDING_PAUSE`, … (12 values) `orders[].asset_class` [enum](https://api-docs.anboto.xyz/reference/schemas/#assetcategory) The Asset category of the order. — `SPOT`, `FUTURE` Example: `SPOT` `orders[].exchange` [enum](https://api-docs.anboto.xyz/reference/schemas/#tradingexchange) The exchanges available for order placement via the API — `BINANCE`, `HUOBI`, `GATEIO`, `KRAKEN`, `KUCOIN`, `OKX`, `BYBIT`, `BITGET`, … (17 values) `orders[].strategy` [enum](https://api-docs.anboto.xyz/reference/schemas/#executionstrategy) The execution strategy for the order. — `TWAP`, `VWAP`, `ICEBERG`, `POV`, `MARKET`, `LIMIT`, `IS`, `SCALE` Example: `VWAP` `orders[].start_time` number The time when the order start trading from epoch time in ms `orders[].end_time` number The scheduled end of the execution from epoch time in ms while the order is working (e.g. start_time + duration for a TWAP); the time the order reached its terminal state once finished `orders[].quantity` number The total quantity of the parent order in base asset, as placed. Absent for value-target (notional) orders, see target_value Example: `6` `orders[].filled_quantity` number required The absolute amount of the order quantity filled Example: `0` `orders[].leaves_quantity` number required The absolute amount of the parent order quantity remaining to be filled (quantity - filled_quantity, 0 once the order is terminal). This is the parent order's remainder, never the leaves of the child order currently working it Example: `0` `orders[].progress` number Execution progress of the parent order between 0 and 1: filled_quantity / quantity, or filled notional / target_value for value-target orders. Same computation as the WebSocket order topic orderProgress; 1 once FILLED. Absent when the parent order is not known Example: `0.1783` `orders[].side` [enum](https://api-docs.anboto.xyz/reference/schemas/#side) The side of the book to trade. — `BUY`, `SELL` `orders[].last_quantity` number required The last qty received in a fill from the exchange Example: `0` `orders[].last_price` number required The last price executed on the exchange Example: `0` `orders[].average_price` number required The average execution price of the order Example: `0` `orders[].limit_price` number The limit price of the parent order, if one was set `orders[].clip_size_type` [enum](https://api-docs.anboto.xyz/reference/schemas/#clipsizetype) The clip size for the child orders. The default is AUTOMATIC — `ABSOLUTE`, `PERCENTAGE`, `AUTOMATIC`, `ORDER_COUNT` `orders[].clip_size_val` number The clip size value of the parent order, as placed `orders[].target_value` number The target notional of a value-target order (e.g. a multi-leg order leg); quantity is absent for such orders `orders[].params` [OrderParams](https://api-docs.anboto.xyz/reference/schemas/#orderparams) The advanced order parameters to modify the execution behavior. `orders[].trades` array\[[TradeDetails](https://api-docs.anboto.xyz/reference/schemas/#tradedetails)\] The list of trades associated with this order when include_trades=true `orders[].trades[].trade_id` string The trade id assigned by the exchange, or the Anboto platform trade id when no exchange trade id was captured Example: `1204004183` `orders[].trades[].symbol` string required The symbol of the fill in Anboto's symbology Example: `BTC/USDT:USDT` `orders[].trades[].exchange_order_id` string The exchange order id of the child order the fill belongs to Example: `151990408` `orders[].trades[].client_order_id` string The client order id of the child order the fill belongs to `orders[].trades[].quantity` number required The absolute amount filled by this trade, in base asset Example: `0.5` `orders[].trades[].price` number required The traded price Example: `92.91` `orders[].trades[].direction` enum The direction of the trade — `BUY`, `SELL` Example: `BUY` `orders[].trades[].maker_or_taker` enum Whether the fill was made as maker or taker — `MAKER`, `TAKER` Example: `MAKER` `orders[].trades[].exec_time` integer The execution time of the trade as ms since epoch Example: `1758276000000` `orders[].trades[].fee` number The fee charged on the trade, in fee_currency Example: `0.0021` `orders[].trades[].fee_currency` string The asset the fee was charged in Example: `USDT` `orders[].trades[].parent_order_id` integer The Anboto id of the parent order the fill belongs to (the order_id of the enclosing order) Example: `596990285759373312` `orders[].trades[].child_order_id` integer The Anboto id of the child (slice) order that executed on the exchange; the WebSocket trade topic carries it as order_id Example: `596990290020118528` `orders[].fees_infos` object Aggregated fees per currency when include_fees=true ``` curl -X GET "$BASE/api/v2/trading/order/open?include_trades=True" \ -H "X-API-KEY: $API_KEY" -H "X-TIMESTAMP: $ts" \ -H "X-SIGN: $sign" ``` ``` params = {"include_trades": ..., "include_fees": ...} r = requests.get(f"{BASE}/api/v2/trading/order/open", params=params headers=signed_headers_query(params)) print(r.json()) ``` ``` let resp = client .get(format!("{BASE}/api/v2/trading/order/open?include_trades=True")) .headers(signed_headers_query(¶ms)) .send()?; println!("{}", resp.text()?); ``` ``` req, _ := http.NewRequest("GET", BASE+"/api/v2/trading/order/open?include_trades=True", nil) for k, v := range signedHeadersQuery(req.URL.Query()) { req.Header.Set(k, v) } resp, err := http.DefaultClient.Do(req) if err != nil { log.Fatal(err) } defer resp.Body.Close() io.Copy(os.Stdout, resp.Body) ``` ``` HttpResponse resp = client.send( signedGet("/api/v2/trading/order/open?include_trades=True"), HttpResponse.BodyHandlers.ofString()); ``` ``` const res = await fetch(`${BASE}/api/v2/trading/order/open?include_trades=True`, { method: "GET", headers: signedHeadersQuery(params), }); const data: OrderDetailsList = await res.json(); ``` ``` val request = signedGet("/api/v2/trading/order/open?include_trades=True") val response = client.send(request, HttpResponse.BodyHandlers.ofString()) println(response.body()) ``` ``` cpr::Response r = cpr::Get( cpr::Url{BASE + "/api/v2/trading/order/open?include_trades=True"}, signedHeadersQuery(params)); std::cout << r.text << std::endl; ``` ``` const res = await fetch(`${BASE}/api/v2/trading/order/open?include_trades=True`, { method: "GET", headers: signedHeadersQuery(params), }); console.log(await res.json()); ``` **Response** 200 ``` { "orders": [ { "order_id": 123456, "client_order_id": "xxx-yyy-zzz", "symbol": "string", "status": "PENDING_NEW", "asset_class": "SPOT", "exchange": "BINANCE", "strategy": "TWAP", "start_time": 0.0, "end_time": 0.0, "quantity": 6, "filled_quantity": 0, "leaves_quantity": 0, "progress": 0.1783, "side": "BUY", "last_quantity": 0, "last_price": 0, "average_price": 0, "limit_price": 0.0, "clip_size_type": "ABSOLUTE", "clip_size_val": 0.0, "target_value": 0.0, "params": { "duration_seconds": "120", "trading_style": "PASSIVE", "urgency": "LOW", "pov_ratio": 5, "pov_risk": "LOW", "randomize_amount": true, "would": {}, "trigger": {}, "placement_infos": {}, "reduce_only": true, "start_ladder_price": "string", "end_ladder_price": "string", "ladder_direction": "string", "ladder_profile": "string", "size_skew": 0.0, "ob_imbalance_cancel": true, "ob_imbalance_threshold": "0.75", "price_lock_bps": "5", "limit_is_arrival": true, "limit_bps": "-10", "timer_iceberg_delay": 0.5, "timer_iceberg_delay_min": 0, "timer_iceberg_delay_max": 10, "randomize_iceberg_timer": true, "extend_duration": true }, "trades": [ {} ], "fees_infos": {} } ] } ``` # Get orders GET `https://api.pro.anboto.xyz/api/v2/trading/order/byId` Either orderIds or clientOrderIds has to be provided for matching **ApiKeyAuth** required. ### Query params `orderIds` array[integer] The list of anboto generated order ids `clientOrderIds` array[string] The list of client generated order ids `include_trades` boolean Whether to include trades for the matching orders `include_fees` boolean Whether to include aggregated fees per currency for the matching orders ### Headers | Header | | | | --------------- | ----------------- | -------- | | `X-API-KEY` | string | required | | `X-TIMESTAMP` | int64 ms | required | | `X-SIGN` | string | required | | `X-RECV-WINDOW` | int, default 5000 | | ### Responses | | | | --- | ---------------------------------------- | | 200 | return a list of matching orders | | 401 | Unauthorized: missing or unknown API key | | 429 | Rate limit exceeded, retry later | ### Response fields — [OrderDetailsList](https://api-docs.anboto.xyz/reference/schemas/#orderdetailslist) `orders` array\[[OrderDetails](https://api-docs.anboto.xyz/reference/schemas/#orderdetails)\] required The list of order details for separate orders. `orders[].order_id` integer The Anboto generated order id Example: `123456` `orders[].client_order_id` string The client provided order id Example: `xxx-yyy-zzz` `orders[].symbol` string The order symbol in Anboto's symbology `orders[].status` [enum](https://api-docs.anboto.xyz/reference/schemas/#orderstatus) The order status — `PENDING_NEW`, `ACCEPTED`, `REJECTED`, `PARTIALLY_FILLED`, `FILLED`, `PENDING_CANCEL`, `CANCELLED`, `PENDING_PAUSE`, … (12 values) `orders[].asset_class` [enum](https://api-docs.anboto.xyz/reference/schemas/#assetcategory) The Asset category of the order. — `SPOT`, `FUTURE` Example: `SPOT` `orders[].exchange` [enum](https://api-docs.anboto.xyz/reference/schemas/#tradingexchange) The exchanges available for order placement via the API — `BINANCE`, `HUOBI`, `GATEIO`, `KRAKEN`, `KUCOIN`, `OKX`, `BYBIT`, `BITGET`, … (17 values) `orders[].strategy` [enum](https://api-docs.anboto.xyz/reference/schemas/#executionstrategy) The execution strategy for the order. — `TWAP`, `VWAP`, `ICEBERG`, `POV`, `MARKET`, `LIMIT`, `IS`, `SCALE` Example: `VWAP` `orders[].start_time` number The time when the order start trading from epoch time in ms `orders[].end_time` number The scheduled end of the execution from epoch time in ms while the order is working (e.g. start_time + duration for a TWAP); the time the order reached its terminal state once finished `orders[].quantity` number The total quantity of the parent order in base asset, as placed. Absent for value-target (notional) orders, see target_value Example: `6` `orders[].filled_quantity` number required The absolute amount of the order quantity filled Example: `0` `orders[].leaves_quantity` number required The absolute amount of the parent order quantity remaining to be filled (quantity - filled_quantity, 0 once the order is terminal). This is the parent order's remainder, never the leaves of the child order currently working it Example: `0` `orders[].progress` number Execution progress of the parent order between 0 and 1: filled_quantity / quantity, or filled notional / target_value for value-target orders. Same computation as the WebSocket order topic orderProgress; 1 once FILLED. Absent when the parent order is not known Example: `0.1783` `orders[].side` [enum](https://api-docs.anboto.xyz/reference/schemas/#side) The side of the book to trade. — `BUY`, `SELL` `orders[].last_quantity` number required The last qty received in a fill from the exchange Example: `0` `orders[].last_price` number required The last price executed on the exchange Example: `0` `orders[].average_price` number required The average execution price of the order Example: `0` `orders[].limit_price` number The limit price of the parent order, if one was set `orders[].clip_size_type` [enum](https://api-docs.anboto.xyz/reference/schemas/#clipsizetype) The clip size for the child orders. The default is AUTOMATIC — `ABSOLUTE`, `PERCENTAGE`, `AUTOMATIC`, `ORDER_COUNT` `orders[].clip_size_val` number The clip size value of the parent order, as placed `orders[].target_value` number The target notional of a value-target order (e.g. a multi-leg order leg); quantity is absent for such orders `orders[].params` [OrderParams](https://api-docs.anboto.xyz/reference/schemas/#orderparams) The advanced order parameters to modify the execution behavior. `orders[].trades` array\[[TradeDetails](https://api-docs.anboto.xyz/reference/schemas/#tradedetails)\] The list of trades associated with this order when include_trades=true `orders[].trades[].trade_id` string The trade id assigned by the exchange, or the Anboto platform trade id when no exchange trade id was captured Example: `1204004183` `orders[].trades[].symbol` string required The symbol of the fill in Anboto's symbology Example: `BTC/USDT:USDT` `orders[].trades[].exchange_order_id` string The exchange order id of the child order the fill belongs to Example: `151990408` `orders[].trades[].client_order_id` string The client order id of the child order the fill belongs to `orders[].trades[].quantity` number required The absolute amount filled by this trade, in base asset Example: `0.5` `orders[].trades[].price` number required The traded price Example: `92.91` `orders[].trades[].direction` enum The direction of the trade — `BUY`, `SELL` Example: `BUY` `orders[].trades[].maker_or_taker` enum Whether the fill was made as maker or taker — `MAKER`, `TAKER` Example: `MAKER` `orders[].trades[].exec_time` integer The execution time of the trade as ms since epoch Example: `1758276000000` `orders[].trades[].fee` number The fee charged on the trade, in fee_currency Example: `0.0021` `orders[].trades[].fee_currency` string The asset the fee was charged in Example: `USDT` `orders[].trades[].parent_order_id` integer The Anboto id of the parent order the fill belongs to (the order_id of the enclosing order) Example: `596990285759373312` `orders[].trades[].child_order_id` integer The Anboto id of the child (slice) order that executed on the exchange; the WebSocket trade topic carries it as order_id Example: `596990290020118528` `orders[].fees_infos` object Aggregated fees per currency when include_fees=true ``` curl -X GET "$BASE/api/v2/trading/order/byId?orderIds=..." \ -H "X-API-KEY: $API_KEY" -H "X-TIMESTAMP: $ts" \ -H "X-SIGN: $sign" ``` ``` params = {"orderIds": ..., "clientOrderIds": ..., "include_trades": ..., "include_fees": ...} r = requests.get(f"{BASE}/api/v2/trading/order/byId", params=params headers=signed_headers_query(params)) print(r.json()) ``` ``` let resp = client .get(format!("{BASE}/api/v2/trading/order/byId?orderIds=...")) .headers(signed_headers_query(¶ms)) .send()?; println!("{}", resp.text()?); ``` ``` req, _ := http.NewRequest("GET", BASE+"/api/v2/trading/order/byId?orderIds=...", nil) for k, v := range signedHeadersQuery(req.URL.Query()) { req.Header.Set(k, v) } resp, err := http.DefaultClient.Do(req) if err != nil { log.Fatal(err) } defer resp.Body.Close() io.Copy(os.Stdout, resp.Body) ``` ``` HttpResponse resp = client.send( signedGet("/api/v2/trading/order/byId?orderIds=..."), HttpResponse.BodyHandlers.ofString()); ``` ``` const res = await fetch(`${BASE}/api/v2/trading/order/byId?orderIds=...`, { method: "GET", headers: signedHeadersQuery(params), }); const data: OrderDetailsList = await res.json(); ``` ``` val request = signedGet("/api/v2/trading/order/byId?orderIds=...") val response = client.send(request, HttpResponse.BodyHandlers.ofString()) println(response.body()) ``` ``` cpr::Response r = cpr::Get( cpr::Url{BASE + "/api/v2/trading/order/byId?orderIds=..."}, signedHeadersQuery(params)); std::cout << r.text << std::endl; ``` ``` const res = await fetch(`${BASE}/api/v2/trading/order/byId?orderIds=...`, { method: "GET", headers: signedHeadersQuery(params), }); console.log(await res.json()); ``` **Response** 200 ``` { "orders": [ { "order_id": 123456, "client_order_id": "xxx-yyy-zzz", "symbol": "string", "status": "PENDING_NEW", "asset_class": "SPOT", "exchange": "BINANCE", "strategy": "TWAP", "start_time": 0.0, "end_time": 0.0, "quantity": 6, "filled_quantity": 0, "leaves_quantity": 0, "progress": 0.1783, "side": "BUY", "last_quantity": 0, "last_price": 0, "average_price": 0, "limit_price": 0.0, "clip_size_type": "ABSOLUTE", "clip_size_val": 0.0, "target_value": 0.0, "params": { "duration_seconds": "120", "trading_style": "PASSIVE", "urgency": "LOW", "pov_ratio": 5, "pov_risk": "LOW", "randomize_amount": true, "would": {}, "trigger": {}, "placement_infos": {}, "reduce_only": true, "start_ladder_price": "string", "end_ladder_price": "string", "ladder_direction": "string", "ladder_profile": "string", "size_skew": 0.0, "ob_imbalance_cancel": true, "ob_imbalance_threshold": "0.75", "price_lock_bps": "5", "limit_is_arrival": true, "limit_bps": "-10", "timer_iceberg_delay": 0.5, "timer_iceberg_delay_min": 0, "timer_iceberg_delay_max": 10, "randomize_iceberg_timer": true, "extend_duration": true }, "trades": [ {} ], "fees_infos": {} } ] } ``` # Get position GET `https://api.pro.anboto.xyz/api/v2/trading/position` shows the asset position != 0 **ApiKeyAuth** required. ### Query params `exchange` [enum](https://api-docs.anboto.xyz/reference/schemas/#tradingexchange) required The exchange — `BINANCE`, `HUOBI`, `GATEIO`, `KRAKEN`, `KUCOIN`, `OKX`, `BYBIT`, `BITGET`, `WOO`, `MEXC`, `BULLISH`, `B2C2`, `COINBASE_PRIME`, `COINBASE_INTL`, … (17 values) `subaccount` string Sub-account ### Headers | Header | | | | --------------- | ----------------- | -------- | | `X-API-KEY` | string | required | | `X-TIMESTAMP` | int64 ms | required | | `X-SIGN` | string | required | | `X-RECV-WINDOW` | int, default 5000 | | ### Responses | | | | --- | ---------------------------------------- | | 200 | The list of asset positions != 0 | | 401 | Unauthorized: missing or unknown API key | | 429 | Rate limit exceeded, retry later | ### Response fields `[].collateral` number The collateral amount for the position `[].contracts` number The number of contracts `[].entryPrice` number The average entry price `[].leverage` number The position leverage `[].liquidationPrice` number The liquidation price `[].marginMode` enum The margin mode of the position — `CROSS`, `ISOLATED` `[].markPrice` number The current mark price `[].notional` number The notional value of the position `[].side` enum The position side — `LONG`, `SHORT`, `BOTH` `[].symbol` string The trading symbol `[].timestamp` integer Unix timestamp in milliseconds `[].unrealizedPnl` number The unrealized profit and loss ``` curl -X GET "$BASE/api/v2/trading/position?exchange=BINANCE" \ -H "X-API-KEY: $API_KEY" -H "X-TIMESTAMP: $ts" \ -H "X-SIGN: $sign" ``` ``` params = {"exchange": ..., "subaccount": ...} r = requests.get(f"{BASE}/api/v2/trading/position", params=params headers=signed_headers_query(params)) print(r.json()) ``` ``` let resp = client .get(format!("{BASE}/api/v2/trading/position?exchange=BINANCE")) .headers(signed_headers_query(¶ms)) .send()?; println!("{}", resp.text()?); ``` ``` req, _ := http.NewRequest("GET", BASE+"/api/v2/trading/position?exchange=BINANCE", nil) for k, v := range signedHeadersQuery(req.URL.Query()) { req.Header.Set(k, v) } resp, err := http.DefaultClient.Do(req) if err != nil { log.Fatal(err) } defer resp.Body.Close() io.Copy(os.Stdout, resp.Body) ``` ``` HttpResponse resp = client.send( signedGet("/api/v2/trading/position?exchange=BINANCE"), HttpResponse.BodyHandlers.ofString()); ``` ``` const res = await fetch(`${BASE}/api/v2/trading/position?exchange=BINANCE`, { method: "GET", headers: signedHeadersQuery(params), }); const data = await res.json(); ``` ``` val request = signedGet("/api/v2/trading/position?exchange=BINANCE") val response = client.send(request, HttpResponse.BodyHandlers.ofString()) println(response.body()) ``` ``` cpr::Response r = cpr::Get( cpr::Url{BASE + "/api/v2/trading/position?exchange=BINANCE"}, signedHeadersQuery(params)); std::cout << r.text << std::endl; ``` ``` const res = await fetch(`${BASE}/api/v2/trading/position?exchange=BINANCE`, { method: "GET", headers: signedHeadersQuery(params), }); console.log(await res.json()); ``` **Response** 200 ``` [ { "collateral": 0.0, "contracts": 0.0, "entryPrice": 0.0, "leverage": 0.0, "liquidationPrice": 0.0, "marginMode": "CROSS", "markPrice": 0.0, "notional": 0.0, "side": "LONG", "symbol": "string", "timestamp": 0, "unrealizedPnl": 0.0 } ] ``` # Get user trades GET `https://api.pro.anboto.xyz/api/v2/trading/userTrades` Either orderIds or clientOrderIds has to be provided for matching **ApiKeyAuth** required. ### Query params `exchange` [enum](https://api-docs.anboto.xyz/reference/schemas/#tradingexchange) required The exchange — `BINANCE`, `HUOBI`, `GATEIO`, `KRAKEN`, `KUCOIN`, `OKX`, `BYBIT`, `BITGET`, `WOO`, `MEXC`, `BULLISH`, `B2C2`, `COINBASE_PRIME`, `COINBASE_INTL`, … (17 values) `subaccount` string Sub-account `orderIds` array[integer] The list of anboto generated order ids `clientOrderIds` array[string] The list of client generated order ids ### Headers | Header | | | | --------------- | ----------------- | -------- | | `X-API-KEY` | string | required | | `X-TIMESTAMP` | int64 ms | required | | `X-SIGN` | string | required | | `X-RECV-WINDOW` | int, default 5000 | | ### Responses | | | | --- | ---------------------------------------- | | 200 | A list of matching trades. | | 401 | Unauthorized: missing or unknown API key | | 429 | Rate limit exceeded, retry later | ### Response fields — [TradeDetailsList](https://api-docs.anboto.xyz/reference/schemas/#tradedetailslist) `trades` array\[[TradeDetails](https://api-docs.anboto.xyz/reference/schemas/#tradedetails)\] required The list of trade details `trades[].trade_id` string The trade id assigned by the exchange, or the Anboto platform trade id when no exchange trade id was captured Example: `1204004183` `trades[].symbol` string required The symbol of the fill in Anboto's symbology Example: `BTC/USDT:USDT` `trades[].exchange_order_id` string The exchange order id of the child order the fill belongs to Example: `151990408` `trades[].client_order_id` string The client order id of the child order the fill belongs to `trades[].quantity` number required The absolute amount filled by this trade, in base asset Example: `0.5` `trades[].price` number required The traded price Example: `92.91` `trades[].direction` enum The direction of the trade — `BUY`, `SELL` Example: `BUY` `trades[].maker_or_taker` enum Whether the fill was made as maker or taker — `MAKER`, `TAKER` Example: `MAKER` `trades[].exec_time` integer The execution time of the trade as ms since epoch Example: `1758276000000` `trades[].fee` number The fee charged on the trade, in fee_currency Example: `0.0021` `trades[].fee_currency` string The asset the fee was charged in Example: `USDT` `trades[].parent_order_id` integer The Anboto id of the parent order the fill belongs to (the order_id of the enclosing order) Example: `596990285759373312` `trades[].child_order_id` integer The Anboto id of the child (slice) order that executed on the exchange; the WebSocket trade topic carries it as order_id Example: `596990290020118528` ``` curl -X GET "$BASE/api/v2/trading/userTrades?exchange=BINANCE" \ -H "X-API-KEY: $API_KEY" -H "X-TIMESTAMP: $ts" \ -H "X-SIGN: $sign" ``` ``` params = {"exchange": ..., "subaccount": ..., "orderIds": ..., "clientOrderIds": ...} r = requests.get(f"{BASE}/api/v2/trading/userTrades", params=params headers=signed_headers_query(params)) print(r.json()) ``` ``` let resp = client .get(format!("{BASE}/api/v2/trading/userTrades?exchange=BINANCE")) .headers(signed_headers_query(¶ms)) .send()?; println!("{}", resp.text()?); ``` ``` req, _ := http.NewRequest("GET", BASE+"/api/v2/trading/userTrades?exchange=BINANCE", nil) for k, v := range signedHeadersQuery(req.URL.Query()) { req.Header.Set(k, v) } resp, err := http.DefaultClient.Do(req) if err != nil { log.Fatal(err) } defer resp.Body.Close() io.Copy(os.Stdout, resp.Body) ``` ``` HttpResponse resp = client.send( signedGet("/api/v2/trading/userTrades?exchange=BINANCE"), HttpResponse.BodyHandlers.ofString()); ``` ``` const res = await fetch(`${BASE}/api/v2/trading/userTrades?exchange=BINANCE`, { method: "GET", headers: signedHeadersQuery(params), }); const data: TradeDetailsList = await res.json(); ``` ``` val request = signedGet("/api/v2/trading/userTrades?exchange=BINANCE") val response = client.send(request, HttpResponse.BodyHandlers.ofString()) println(response.body()) ``` ``` cpr::Response r = cpr::Get( cpr::Url{BASE + "/api/v2/trading/userTrades?exchange=BINANCE"}, signedHeadersQuery(params)); std::cout << r.text << std::endl; ``` ``` const res = await fetch(`${BASE}/api/v2/trading/userTrades?exchange=BINANCE`, { method: "GET", headers: signedHeadersQuery(params), }); console.log(await res.json()); ``` **Response** 200 ``` { "trades": [ { "trade_id": "1204004183", "symbol": "BTC/USDT:USDT", "exchange_order_id": "151990408", "client_order_id": "string", "quantity": 0.5, "price": 92.91, "direction": "BUY", "maker_or_taker": "MAKER", "exec_time": 1758276000000, "fee": 0.0021, "fee_currency": "USDT", "parent_order_id": 596990285759373312, "child_order_id": 596990290020118528 } ] } ``` # Instruments GET `https://api.pro.anboto.xyz/api/v2/data/instruments` Return all instruments based on filter parameters **ApiKeyAuth** required. ### Query params `exchange` string Return all instruments on this exchange for each asset `symbol` string Return instrument with this symbol ### Headers | Header | | | | --------------- | ----------------- | -------- | | `X-API-KEY` | string | required | | `X-TIMESTAMP` | int64 ms | required | | `X-SIGN` | string | required | | `X-RECV-WINDOW` | int, default 5000 | | ### Responses | | | | --- | ---------------------------------------- | | 200 | The instruments | | 401 | Unauthorized: missing or unknown API key | | 429 | Rate limit exceeded, retry later | ### Response fields — [Instrument](https://api-docs.anboto.xyz/reference/schemas/#instrument) `exchange` [enum](https://api-docs.anboto.xyz/reference/schemas/#exchangecode) required Platform exchange identifier (all venues, including ones not tradable via the API) — `BINANCE`, `HUOBI`, `COINBASE_ADV`, `GATEIO`, `KRAKEN`, `KUCOIN`, `OKX`, `BYBIT`, … (19 values) `symbol` string required `baseAsset` string required `quoteAsset` string required `exchangeSymbol` string required `exchangeAssetClass` string required `assetClass` [enum](https://api-docs.anboto.xyz/reference/schemas/#assetclass) required `UNDEFINED`, `SPOT`, `FUTURE`, `OPTION`, `CFD` `quantityPrecision` integer `pricePrecision` integer `maxQuantityLimit` number `minQuantityLimit` number `minCostLimit` number `maxCostLimit` number `contractSize` number `minMarketLimit` number `maxMarketLimit` number `minPriceLimit` number `maxPriceLimit` number `enabled` boolean required `timestamp` date-time required `priceSignificantFigure` integer `quantitySignificantFigure` integer `assetId` string ``` curl -X GET "$BASE/api/v2/data/instruments?exchange=string" \ -H "X-API-KEY: $API_KEY" -H "X-TIMESTAMP: $ts" \ -H "X-SIGN: $sign" ``` ``` params = {"exchange": ..., "symbol": ...} r = requests.get(f"{BASE}/api/v2/data/instruments", params=params headers=signed_headers_query(params)) print(r.json()) ``` ``` let resp = client .get(format!("{BASE}/api/v2/data/instruments?exchange=string")) .headers(signed_headers_query(¶ms)) .send()?; println!("{}", resp.text()?); ``` ``` req, _ := http.NewRequest("GET", BASE+"/api/v2/data/instruments?exchange=string", nil) for k, v := range signedHeadersQuery(req.URL.Query()) { req.Header.Set(k, v) } resp, err := http.DefaultClient.Do(req) if err != nil { log.Fatal(err) } defer resp.Body.Close() io.Copy(os.Stdout, resp.Body) ``` ``` HttpResponse resp = client.send( signedGet("/api/v2/data/instruments?exchange=string"), HttpResponse.BodyHandlers.ofString()); ``` ``` const res = await fetch(`${BASE}/api/v2/data/instruments?exchange=string`, { method: "GET", headers: signedHeadersQuery(params), }); const data: Instrument = await res.json(); ``` ``` val request = signedGet("/api/v2/data/instruments?exchange=string") val response = client.send(request, HttpResponse.BodyHandlers.ofString()) println(response.body()) ``` ``` cpr::Response r = cpr::Get( cpr::Url{BASE + "/api/v2/data/instruments?exchange=string"}, signedHeadersQuery(params)); std::cout << r.text << std::endl; ``` ``` const res = await fetch(`${BASE}/api/v2/data/instruments?exchange=string`, { method: "GET", headers: signedHeadersQuery(params), }); console.log(await res.json()); ``` **Response** 200 ``` { "exchange": "BINANCE", "symbol": "string", "baseAsset": "string", "quoteAsset": "string", "exchangeSymbol": "string", "exchangeAssetClass": "string", "assetClass": "UNDEFINED", "quantityPrecision": 0, "pricePrecision": 0, "maxQuantityLimit": 0.0, "minQuantityLimit": 0.0, "minCostLimit": 0.0, "maxCostLimit": 0.0, "contractSize": 0.0, "minMarketLimit": 0.0, "maxMarketLimit": 0.0, "minPriceLimit": 0.0, "maxPriceLimit": 0.0, "enabled": true, "timestamp": "string", "priceSignificantFigure": 0, "quantitySignificantFigure": 0, "assetId": "string" } ``` # Kill POST `https://api.pro.anboto.xyz/api/v2/strategies/campaigns/kill` Close every open leg at market now, then the campaign reaches stopped. Valid from any status, including error. **ApiKeyAuth** required. ### Body params `campaign_id` string required The campaign's id (UUID) ### Headers | Header | | | | --------------- | ----------------- | -------- | | `X-API-KEY` | string | required | | `X-TIMESTAMP` | int64 ms | required | | `X-SIGN` | string | required | | `X-RECV-WINDOW` | int, default 5000 | | ### Responses | | | | --- | ------------------------------------------------------------------------ | | 202 | The kill was accepted; the campaign closes asynchronously | | 400 | campaign_id is missing or not a valid id, `{"code", "error", "errors"?}` | | 401 | Unauthorized: missing or unknown API key | | 403 | Forbidden: the API key is read-only, `{"code", "error", "errors"?}` | | 404 | No such campaign on this account, `{"code", "error", "errors"?}` | | 429 | Rate limit exceeded, retry later, `{"code", "error", "errors"?}` | | 503 | The strategies service is unavailable, `{"code", "error", "errors"?}` | ### Response fields — [StrategyCampaign](https://api-docs.anboto.xyz/reference/schemas/#strategycampaign) `id` string Campaign id (UUID) `type` string Campaign type; today always paper_farm `status` enum running | paused | stopped | done | error — `running`, `paused`, `stopped`, `done`, `error` `stopping` boolean A graceful stop or a hard kill is under way. Independent of status: can be true while status stays error (the open legs are being closed before the campaign reaches stopped) `phase` string Cycle phase the runner is in: idle, opening, open, closing or settling `stop_reason` string Why a stopped/done campaign ended: cycles_done, budget_spent, session_key_expiring, queued_share, user_stop or user_kill. Empty while still running `cycles_done` integer Cycles completed so far `cycles_planned` integer max_cycles from create, or null for unlimited `paper_minted` number Total PAPER minted by this campaign's losing legs `usdc_converted` number Total USDC spent converting minted PAPER (haircut + fee) `queued_usdc` number Profit queued to fund a future cycle's margin instead of being paid out `haircut_paid` number Total haircut paid converting PAPER to USDC `fees_paid` number Total trading fees paid by this campaign `current_legs` array\[[StrategyCampaignLeg](https://api-docs.anboto.xyz/reference/schemas/#strategycampaignleg)\] Open legs of the current cycle (0 while idle, up to 2 while open) `current_legs[].position_id` string The venue's position id, or null while the open is still unconfirmed `current_legs[].side` string long or short `current_legs[].entry` number Entry (mark) price the leg opened at `current_legs[].move_pct` number Signed move since entry, in percent, from this leg's point of view `current_legs[].bust` number This leg's liquidation (bust) price `current_legs[].size` number Position size `current_legs[].margin` number Margin posted for this leg, in USDC `current_legs[].leverage` integer Leverage of this leg `current_legs[].mark_price` number Latest mark price used to watch this leg `current_legs[].parent_order_id` string The order id that opened this leg `current_legs[].opened_at` date-time UTC time the leg opened, ISO 8601 `last_cycle` [StrategyCampaignCycle](https://api-docs.anboto.xyz/reference/schemas/#strategycampaigncycle) The campaign's most recently closed cycle `last_cycle.pnl_usdc` number Net result of the cycle, in USDC (can be negative) `last_cycle.paper` number PAPER minted by the losing leg of this cycle `last_cycle.closed_at` date-time UTC time both legs were closed, ISO 8601 `last_cycle.multileg_order_id` string The multileg (or paired single) order id the close went through, when known `last_error` string Why the campaign is in error; empty otherwise `symbol` string Anboto symbol being farmed, e.g. BTC/USDC:USDC `leverage` integer Leverage of each leg `margin_per_leg` number Margin posted per leg at the start of a cycle, in USDC `target_move_bps` integer Winning-leg move, in basis points, that closes the cycle `budget_usdc` number budget_usdc from create, or null for no spend cap `stop` [StrategyStopRules](https://api-docs.anboto.xyz/reference/schemas/#strategystoprules) Stop conditions the campaign watches on its own, besides an explicit stop/kill `stop.queued_share_pct` number Stop once this percent (0-100) of a new cycle's margin would come from queued profit rather than fresh budget. Null or omitted: off `stop.stop_before_key_expiry` boolean Stop gracefully once the Papertrade session key has under an hour left, rather than risk a cycle stuck open past expiry Default: `true` `stop.hard_kill_on_stop` boolean If a stop rule fires mid-cycle, close both legs at market now instead of waiting for the target Default: `false` `created_at` date-time UTC time the campaign was created, ISO 8601 `started_at` date-time UTC time the campaign started, ISO 8601 `stopped_at` date-time UTC time the campaign stopped, ISO 8601, or null while still running ``` body='{ "campaign_id": "string" }' curl -X POST "$BASE/api/v2/strategies/campaigns/kill" \ -H "X-API-KEY: $API_KEY" -H "X-TIMESTAMP: $ts" \ -H "X-SIGN: $sign" \ -H "Content-Type: application/json" -d "$body" ``` ``` payload = { "campaign_id": "string" } r = requests.post(f"{BASE}/api/v2/strategies/campaigns/kill", data=json.dumps(payload) headers=signed_headers(payload)) print(r.json()) ``` ``` let payload = serde_json::json!({ "campaign_id": "string" }); let resp = client .post(format!("{BASE}/api/v2/strategies/campaigns/kill")) .headers(signed_headers(&payload)) .json(&payload) .send()?; println!("{}", resp.text()?); ``` ``` payload := map[string]any{ "campaign_id": "string", } body, _ := json.Marshal(payload) req, _ := http.NewRequest("POST", BASE+"/api/v2/strategies/campaigns/kill", bytes.NewReader(body)) for k, v := range signedHeaders(string(body)) { req.Header.Set(k, v) } req.Header.Set("Content-Type", "application/json") resp, err := http.DefaultClient.Do(req) if err != nil { log.Fatal(err) } defer resp.Body.Close() io.Copy(os.Stdout, resp.Body) ``` ``` String jsonBody = mapper.writeValueAsString(payload); HttpResponse resp = client.send( signedPost("/api/v2/strategies/campaigns/kill", jsonBody), HttpResponse.BodyHandlers.ofString()); ``` ``` const payload: StrategyCampaignActionRequest = { "campaign_id": "string" }; const res = await fetch(`${BASE}/api/v2/strategies/campaigns/kill`, { method: "POST", headers: signedHeaders(payload), body: JSON.stringify(payload), }); const data: StrategyCampaign = await res.json(); ``` ``` val jsonBody = mapper.writeValueAsString(payload) val request = signedPost("/api/v2/strategies/campaigns/kill", jsonBody) val response = client.send(request, HttpResponse.BodyHandlers.ofString()) println(response.body()) ``` ``` std::string body = R"({ "campaign_id": "string" })"; cpr::Response r = cpr::Post( cpr::Url{BASE + "/api/v2/strategies/campaigns/kill"}, signedHeaders(body), cpr::Header{{"Content-Type", "application/json"}}, cpr::Body{body}); std::cout << r.text << std::endl; ``` ``` const payload = { "campaign_id": "string" }; const res = await fetch(`${BASE}/api/v2/strategies/campaigns/kill`, { method: "POST", headers: signedHeaders(payload), body: JSON.stringify(payload), }); console.log(await res.json()); ``` **Response** 202 ``` { "id": "string", "type": "string", "status": "running", "stopping": true, "phase": "string", "stop_reason": "string", "cycles_done": 0, "cycles_planned": 0, "paper_minted": 0.0, "usdc_converted": 0.0, "queued_usdc": 0.0, "haircut_paid": 0.0, "fees_paid": 0.0, "current_legs": [ { "position_id": "string", "side": "string", "entry": 0.0, "move_pct": 0.0, "bust": 0.0, "size": 0.0, "margin": 0.0, "leverage": 0, "mark_price": 0.0, "parent_order_id": "string", "opened_at": "string" } ], "last_cycle": { "pnl_usdc": 0.0, "paper": 0.0, "closed_at": "string", "multileg_order_id": "string" }, "last_error": "string", "symbol": "string", "leverage": 0, "margin_per_leg": 0.0, "target_move_bps": 0, "budget_usdc": 0.0, "stop": { "queued_share_pct": 0.0, "stop_before_key_expiry": true, "hard_kill_on_stop": true }, "created_at": "string", "started_at": "string", "stopped_at": "string" } ``` # Last funding rates GET `https://api.pro.anboto.xyz/api/v2/data/lastFundingRates` Return all funding rates based on filter parameters **ApiKeyAuth** required. ### Query params `exchange` string Return last funding rates on this exchange for each asset `symbol` string Return last funding rates for this asset on each exchange ### Headers | Header | | | | --------------- | ----------------- | -------- | | `X-API-KEY` | string | required | | `X-TIMESTAMP` | int64 ms | required | | `X-SIGN` | string | required | | `X-RECV-WINDOW` | int, default 5000 | | ### Responses | | | | --- | ---------------------------------------- | | 200 | The last funding rates. | | 401 | Unauthorized: missing or unknown API key | | 429 | Rate limit exceeded, retry later | ### Response fields — [FundingRate](https://api-docs.anboto.xyz/reference/schemas/#fundingrate) `exchange` string required `symbol` string required `time` date-time required `nextTime` date-time required `rate` number required `nextRate` number `markPrice` number ``` curl -X GET "$BASE/api/v2/data/lastFundingRates?exchange=string" \ -H "X-API-KEY: $API_KEY" -H "X-TIMESTAMP: $ts" \ -H "X-SIGN: $sign" ``` ``` params = {"exchange": ..., "symbol": ...} r = requests.get(f"{BASE}/api/v2/data/lastFundingRates", params=params headers=signed_headers_query(params)) print(r.json()) ``` ``` let resp = client .get(format!("{BASE}/api/v2/data/lastFundingRates?exchange=string")) .headers(signed_headers_query(¶ms)) .send()?; println!("{}", resp.text()?); ``` ``` req, _ := http.NewRequest("GET", BASE+"/api/v2/data/lastFundingRates?exchange=string", nil) for k, v := range signedHeadersQuery(req.URL.Query()) { req.Header.Set(k, v) } resp, err := http.DefaultClient.Do(req) if err != nil { log.Fatal(err) } defer resp.Body.Close() io.Copy(os.Stdout, resp.Body) ``` ``` HttpResponse resp = client.send( signedGet("/api/v2/data/lastFundingRates?exchange=string"), HttpResponse.BodyHandlers.ofString()); ``` ``` const res = await fetch(`${BASE}/api/v2/data/lastFundingRates?exchange=string`, { method: "GET", headers: signedHeadersQuery(params), }); const data: FundingRate = await res.json(); ``` ``` val request = signedGet("/api/v2/data/lastFundingRates?exchange=string") val response = client.send(request, HttpResponse.BodyHandlers.ofString()) println(response.body()) ``` ``` cpr::Response r = cpr::Get( cpr::Url{BASE + "/api/v2/data/lastFundingRates?exchange=string"}, signedHeadersQuery(params)); std::cout << r.text << std::endl; ``` ``` const res = await fetch(`${BASE}/api/v2/data/lastFundingRates?exchange=string`, { method: "GET", headers: signedHeadersQuery(params), }); console.log(await res.json()); ``` **Response** 200 ``` { "exchange": "string", "symbol": "string", "time": "string", "nextTime": "string", "rate": 0.0, "nextRate": 0.0, "markPrice": 0.0 } ``` # Ledger GET `https://api.pro.anboto.xyz/api/v2/portfolio/pnl/ledger` Income from the exchange's own history: realized PnL, funding, commissions, rebates and other income, in USD. Signs are from the account's point of view: + is income, − is cost. `net` is the net realized PnL of futures (Net realized (futures)). Spot income is trading fees only: they are in `commission` and `fee_rebate` but not in `net`, and spot rows (and a spot-only selection's `totals`) have null `realized_pnl`, `funding`, `other` and `net`, never 0. `coverage` gives the ingestion status per account; venues without ingestion are listed there as `unsupported` and are never reported as zero. Today's figures are provisional. Results are paged: pass `next_cursor` back as `cursor`; `totals` always cover the whole window. **ApiKeyAuth** required. ### Query params `accounts` string Comma-separated accounts: `binance` = every account on Binance (main and subaccounts), `binance:` = the main account only, `binance:Sub1` = that subaccount. Omit for every account of the team. At most 20 items. Unlike /api/v2/trading/\*, a missing subaccount means all accounts. Sign the raw value, e.g. `accounts=binance:,bybit:Sub1`. Example: `binance:` `groupBy` enum Row grouping: day, symbol or day_symbol (default) — `day`, `symbol`, `day_symbol` Default: `day_symbol` `symbol` string Only this Anboto symbol, e.g. BTC/USDT:USDT (futures) or BTC/USDT (spot) `market` enum Only this market: spot or future — `spot`, `future` `period` string Window ending at endDate: `d`, week, month, quarter or year. Default 30d. Ignored when startDate is given `startDate` date First day, YYYY-MM-DD (UTC, inclusive) `endDate` date Last day, YYYY-MM-DD (UTC, inclusive). Defaults to today; at most today. The window spans at most 366 days `limit` integer Rows per page, 1 to 5000 (default 1000) Default: `1000` `cursor` string `next_cursor` of the previous page ### Headers | Header | | | | --------------- | ----------------- | -------- | | `X-API-KEY` | string | required | | `X-TIMESTAMP` | int64 ms | required | | `X-SIGN` | string | required | | `X-RECV-WINDOW` | int, default 5000 | | ### Responses | | | | --- | ---------------------------------------- | | 200 | The income ledger | | 400 | Invalid parameter, | | 401 | Unauthorized: missing or unknown API key | | 429 | Rate limit exceeded, retry later | | 503 | The portfolio service is unavailable, | ### Response fields — [PortfolioLedgerResponse](https://api-docs.anboto.xyz/reference/schemas/#portfolioledgerresponse) `as_of` date-time required UTC time of the newest ingested income data `from_date` date required First day of the window (YYYY-MM-DD, UTC) `to_date` date required Last day of the window (YYYY-MM-DD, UTC); today's figures are provisional `group_by` enum required Grouping of `rows` — `day`, `symbol`, `day_symbol` `currency` string required Currency of every money value Example: `USD` `coverage` array\[[LedgerCoverage](https://api-docs.anboto.xyz/reference/schemas/#ledgercoverage)\] required Ingestion status per account and market. Unsupported venues are listed here, not reported as zero `coverage[].exchange` string required `coverage[].subaccount` string required "" is the main account; null means every account on the exchange `coverage[].market` enum required `spot`, `future` `coverage[].status` enum required `complete`, `partial`, `unsupported` `coverage[].ingested_through` date-time required UTC time up to which income is ingested `coverage[].reason` string required Why the account is partial or unsupported, e.g. exchange_not_supported, key_invalid `totals` [LedgerTotals](https://api-docs.anboto.xyz/reference/schemas/#ledgertotals) required Income components in USD. net is the net realized PnL of the futures scopes only: spot trading fees are in commission and fee_rebate but not in net. Every value is null when no day of the window is covered `totals.realized_pnl` number required Realized trading PnL; null when the selection has no futures scope `totals.funding` number required Funding: positive when received; null when the selection has no futures scope `totals.commission` number required Trading fees (≤ 0) `totals.fee_rebate` number required Fee rebates (≥ 0) `totals.interest` number required Margin interest: not ingested, 0 `totals.other` number required Other PnL-relevant income; null when the selection has no futures scope `totals.net` number required Net realized (futures): the sum of the futures components. Spot trading fees are in commission and fee_rebate but not in net, so with a spot scope in the selection net is not the sum of the values above. Null when the selection has no futures scope `unpriced_assets` array[string] Assets with income rows that could not be valued in USD; those amounts are missing from the USD figures `rows` array\[[LedgerRow](https://api-docs.anboto.xyz/reference/schemas/#ledgerrow)\] required One row per day, symbol or day and symbol, depending on group_by `rows[].date` date required UTC day (YYYY-MM-DD); null when group_by is symbol `rows[].exchange` string required `rows[].subaccount` string required "" is the main account `rows[].symbol` string required Anboto symbol, e.g. BTC/USDT:USDT (futures) or BTC/USDT (spot); null when group_by is day or for income without a symbol `rows[].market` enum required `spot`, `future` `rows[].realized_pnl` number required Realized trading PnL; null for market spot (trading fees only), never 0 `rows[].funding` number required Funding; null for market spot (trading fees only), never 0 `rows[].commission` number required Trading fees (≤ 0), spot and futures `rows[].fee_rebate` number required Fee rebates (≥ 0), spot and futures `rows[].interest` number required Margin interest: not ingested, 0 `rows[].other` number required Other PnL-relevant income; null for market spot (trading fees only), never 0 `rows[].net` number required Net realized (futures): sum of the row's components. Null for market spot: spot trading fees are in commission and fee_rebate only, never in net `next_cursor` string required Pass as `cursor` to read the next page; null on the last page ``` curl -X GET "$BASE/api/v2/portfolio/pnl/ledger?accounts=string" \ -H "X-API-KEY: $API_KEY" -H "X-TIMESTAMP: $ts" \ -H "X-SIGN: $sign" ``` ``` params = {"accounts": ..., "groupBy": ..., "symbol": ..., "market": ..., "period": ..., "startDate": ..., "endDate": ..., "limit": ..., "cursor": ...} r = requests.get(f"{BASE}/api/v2/portfolio/pnl/ledger", params=params headers=signed_headers_query(params)) print(r.json()) ``` ``` let resp = client .get(format!("{BASE}/api/v2/portfolio/pnl/ledger?accounts=string")) .headers(signed_headers_query(¶ms)) .send()?; println!("{}", resp.text()?); ``` ``` req, _ := http.NewRequest("GET", BASE+"/api/v2/portfolio/pnl/ledger?accounts=string", nil) for k, v := range signedHeadersQuery(req.URL.Query()) { req.Header.Set(k, v) } resp, err := http.DefaultClient.Do(req) if err != nil { log.Fatal(err) } defer resp.Body.Close() io.Copy(os.Stdout, resp.Body) ``` ``` HttpResponse resp = client.send( signedGet("/api/v2/portfolio/pnl/ledger?accounts=string"), HttpResponse.BodyHandlers.ofString()); ``` ``` const res = await fetch(`${BASE}/api/v2/portfolio/pnl/ledger?accounts=string`, { method: "GET", headers: signedHeadersQuery(params), }); const data: PortfolioLedgerResponse = await res.json(); ``` ``` val request = signedGet("/api/v2/portfolio/pnl/ledger?accounts=string") val response = client.send(request, HttpResponse.BodyHandlers.ofString()) println(response.body()) ``` ``` cpr::Response r = cpr::Get( cpr::Url{BASE + "/api/v2/portfolio/pnl/ledger?accounts=string"}, signedHeadersQuery(params)); std::cout << r.text << std::endl; ``` ``` const res = await fetch(`${BASE}/api/v2/portfolio/pnl/ledger?accounts=string`, { method: "GET", headers: signedHeadersQuery(params), }); console.log(await res.json()); ``` **Response** 200 ``` { "as_of": "string", "from_date": "string", "to_date": "string", "group_by": "day", "currency": "USD", "coverage": [ { "exchange": "string", "subaccount": "string", "market": "spot", "status": "complete", "ingested_through": "string", "reason": "string" } ], "totals": { "realized_pnl": 0.0, "funding": 0.0, "commission": 0.0, "fee_rebate": 0.0, "interest": 0.0, "other": 0.0, "net": 0.0 }, "unpriced_assets": [ "string" ], "rows": [ { "date": "string", "exchange": "string", "subaccount": "string", "symbol": "string", "market": "spot", "realized_pnl": 0.0, "funding": 0.0, "commission": 0.0, "fee_rebate": 0.0, "interest": 0.0, "other": 0.0, "net": 0.0 } ], "next_cursor": "string" } ``` # Listen key GET `https://api.pro.anboto.xyz/api/v2/trading/listenKey` Returns a listenKey (JWT, valid 1 hour) to authenticate on wss:///api/v2/ws?listenKey=. See the WebSocket API documentation (asynapi.yml). **ApiKeyAuth** required. ### Headers | Header | | | | --------------- | ----------------- | -------- | | `X-API-KEY` | string | required | | `X-TIMESTAMP` | int64 ms | required | | `X-SIGN` | string | required | | `X-RECV-WINDOW` | int, default 5000 | | ### Responses | | | | --- | ---------------------------------------- | | 200 | The listenKey token | | 401 | Unauthorized: missing or unknown API key | | 429 | Rate limit exceeded, retry later | ``` curl -X GET "$BASE/api/v2/trading/listenKey" \ -H "X-API-KEY: $API_KEY" -H "X-TIMESTAMP: $ts" \ -H "X-SIGN: $sign" ``` ``` r = requests.get(f"{BASE}/api/v2/trading/listenKey", headers=signed_headers_query({})) print(r.json()) ``` ``` let resp = client .get(format!("{BASE}/api/v2/trading/listenKey")) .headers(signed_headers_query(¶ms)) .send()?; println!("{}", resp.text()?); ``` ``` req, _ := http.NewRequest("GET", BASE+"/api/v2/trading/listenKey", nil) for k, v := range signedHeadersQuery(req.URL.Query()) { req.Header.Set(k, v) } resp, err := http.DefaultClient.Do(req) if err != nil { log.Fatal(err) } defer resp.Body.Close() io.Copy(os.Stdout, resp.Body) ``` ``` HttpResponse resp = client.send( signedGet("/api/v2/trading/listenKey"), HttpResponse.BodyHandlers.ofString()); ``` ``` const res = await fetch(`${BASE}/api/v2/trading/listenKey`, { method: "GET", headers: signedHeadersQuery(params), }); const data = await res.json(); ``` ``` val request = signedGet("/api/v2/trading/listenKey") val response = client.send(request, HttpResponse.BodyHandlers.ofString()) println(response.body()) ``` ``` cpr::Response r = cpr::Get( cpr::Url{BASE + "/api/v2/trading/listenKey"}, signedHeadersQuery(params)); std::cout << r.text << std::endl; ``` ``` const res = await fetch(`${BASE}/api/v2/trading/listenKey`, { method: "GET", headers: signedHeadersQuery(params), }); console.log(await res.json()); ``` **Response** 200 ``` "string" ``` # Pause POST `https://api.pro.anboto.xyz/api/v2/strategies/campaigns/pause` No new cycle starts; the open one still closes at its target. **ApiKeyAuth** required. ### Body params `campaign_id` string required The campaign's id (UUID) ### Headers | Header | | | | --------------- | ----------------- | -------- | | `X-API-KEY` | string | required | | `X-TIMESTAMP` | int64 ms | required | | `X-SIGN` | string | required | | `X-RECV-WINDOW` | int, default 5000 | | ### Responses | | | | --- | ----------------------------------------------------------------------------------------- | | 200 | The campaign, paused | | 400 | campaign_id is missing or not a valid id, `{"code", "error", "errors"?}` | | 401 | Unauthorized: missing or unknown API key | | 403 | Forbidden: the API key is read-only, `{"code", "error", "errors"?}` | | 404 | No such campaign on this account, `{"code", "error", "errors"?}` | | 409 | Not a valid transition from the campaign's current status, `{"code", "error", "errors"?}` | | 429 | Rate limit exceeded, retry later, `{"code", "error", "errors"?}` | | 503 | The strategies service is unavailable, `{"code", "error", "errors"?}` | ### Response fields — [StrategyCampaign](https://api-docs.anboto.xyz/reference/schemas/#strategycampaign) `id` string Campaign id (UUID) `type` string Campaign type; today always paper_farm `status` enum running | paused | stopped | done | error — `running`, `paused`, `stopped`, `done`, `error` `stopping` boolean A graceful stop or a hard kill is under way. Independent of status: can be true while status stays error (the open legs are being closed before the campaign reaches stopped) `phase` string Cycle phase the runner is in: idle, opening, open, closing or settling `stop_reason` string Why a stopped/done campaign ended: cycles_done, budget_spent, session_key_expiring, queued_share, user_stop or user_kill. Empty while still running `cycles_done` integer Cycles completed so far `cycles_planned` integer max_cycles from create, or null for unlimited `paper_minted` number Total PAPER minted by this campaign's losing legs `usdc_converted` number Total USDC spent converting minted PAPER (haircut + fee) `queued_usdc` number Profit queued to fund a future cycle's margin instead of being paid out `haircut_paid` number Total haircut paid converting PAPER to USDC `fees_paid` number Total trading fees paid by this campaign `current_legs` array\[[StrategyCampaignLeg](https://api-docs.anboto.xyz/reference/schemas/#strategycampaignleg)\] Open legs of the current cycle (0 while idle, up to 2 while open) `current_legs[].position_id` string The venue's position id, or null while the open is still unconfirmed `current_legs[].side` string long or short `current_legs[].entry` number Entry (mark) price the leg opened at `current_legs[].move_pct` number Signed move since entry, in percent, from this leg's point of view `current_legs[].bust` number This leg's liquidation (bust) price `current_legs[].size` number Position size `current_legs[].margin` number Margin posted for this leg, in USDC `current_legs[].leverage` integer Leverage of this leg `current_legs[].mark_price` number Latest mark price used to watch this leg `current_legs[].parent_order_id` string The order id that opened this leg `current_legs[].opened_at` date-time UTC time the leg opened, ISO 8601 `last_cycle` [StrategyCampaignCycle](https://api-docs.anboto.xyz/reference/schemas/#strategycampaigncycle) The campaign's most recently closed cycle `last_cycle.pnl_usdc` number Net result of the cycle, in USDC (can be negative) `last_cycle.paper` number PAPER minted by the losing leg of this cycle `last_cycle.closed_at` date-time UTC time both legs were closed, ISO 8601 `last_cycle.multileg_order_id` string The multileg (or paired single) order id the close went through, when known `last_error` string Why the campaign is in error; empty otherwise `symbol` string Anboto symbol being farmed, e.g. BTC/USDC:USDC `leverage` integer Leverage of each leg `margin_per_leg` number Margin posted per leg at the start of a cycle, in USDC `target_move_bps` integer Winning-leg move, in basis points, that closes the cycle `budget_usdc` number budget_usdc from create, or null for no spend cap `stop` [StrategyStopRules](https://api-docs.anboto.xyz/reference/schemas/#strategystoprules) Stop conditions the campaign watches on its own, besides an explicit stop/kill `stop.queued_share_pct` number Stop once this percent (0-100) of a new cycle's margin would come from queued profit rather than fresh budget. Null or omitted: off `stop.stop_before_key_expiry` boolean Stop gracefully once the Papertrade session key has under an hour left, rather than risk a cycle stuck open past expiry Default: `true` `stop.hard_kill_on_stop` boolean If a stop rule fires mid-cycle, close both legs at market now instead of waiting for the target Default: `false` `created_at` date-time UTC time the campaign was created, ISO 8601 `started_at` date-time UTC time the campaign started, ISO 8601 `stopped_at` date-time UTC time the campaign stopped, ISO 8601, or null while still running ``` body='{ "campaign_id": "string" }' curl -X POST "$BASE/api/v2/strategies/campaigns/pause" \ -H "X-API-KEY: $API_KEY" -H "X-TIMESTAMP: $ts" \ -H "X-SIGN: $sign" \ -H "Content-Type: application/json" -d "$body" ``` ``` payload = { "campaign_id": "string" } r = requests.post(f"{BASE}/api/v2/strategies/campaigns/pause", data=json.dumps(payload) headers=signed_headers(payload)) print(r.json()) ``` ``` let payload = serde_json::json!({ "campaign_id": "string" }); let resp = client .post(format!("{BASE}/api/v2/strategies/campaigns/pause")) .headers(signed_headers(&payload)) .json(&payload) .send()?; println!("{}", resp.text()?); ``` ``` payload := map[string]any{ "campaign_id": "string", } body, _ := json.Marshal(payload) req, _ := http.NewRequest("POST", BASE+"/api/v2/strategies/campaigns/pause", bytes.NewReader(body)) for k, v := range signedHeaders(string(body)) { req.Header.Set(k, v) } req.Header.Set("Content-Type", "application/json") resp, err := http.DefaultClient.Do(req) if err != nil { log.Fatal(err) } defer resp.Body.Close() io.Copy(os.Stdout, resp.Body) ``` ``` String jsonBody = mapper.writeValueAsString(payload); HttpResponse resp = client.send( signedPost("/api/v2/strategies/campaigns/pause", jsonBody), HttpResponse.BodyHandlers.ofString()); ``` ``` const payload: StrategyCampaignActionRequest = { "campaign_id": "string" }; const res = await fetch(`${BASE}/api/v2/strategies/campaigns/pause`, { method: "POST", headers: signedHeaders(payload), body: JSON.stringify(payload), }); const data: StrategyCampaign = await res.json(); ``` ``` val jsonBody = mapper.writeValueAsString(payload) val request = signedPost("/api/v2/strategies/campaigns/pause", jsonBody) val response = client.send(request, HttpResponse.BodyHandlers.ofString()) println(response.body()) ``` ``` std::string body = R"({ "campaign_id": "string" })"; cpr::Response r = cpr::Post( cpr::Url{BASE + "/api/v2/strategies/campaigns/pause"}, signedHeaders(body), cpr::Header{{"Content-Type", "application/json"}}, cpr::Body{body}); std::cout << r.text << std::endl; ``` ``` const payload = { "campaign_id": "string" }; const res = await fetch(`${BASE}/api/v2/strategies/campaigns/pause`, { method: "POST", headers: signedHeaders(payload), body: JSON.stringify(payload), }); console.log(await res.json()); ``` **Response** 200 ``` { "id": "string", "type": "string", "status": "running", "stopping": true, "phase": "string", "stop_reason": "string", "cycles_done": 0, "cycles_planned": 0, "paper_minted": 0.0, "usdc_converted": 0.0, "queued_usdc": 0.0, "haircut_paid": 0.0, "fees_paid": 0.0, "current_legs": [ { "position_id": "string", "side": "string", "entry": 0.0, "move_pct": 0.0, "bust": 0.0, "size": 0.0, "margin": 0.0, "leverage": 0, "mark_price": 0.0, "parent_order_id": "string", "opened_at": "string" } ], "last_cycle": { "pnl_usdc": 0.0, "paper": 0.0, "closed_at": "string", "multileg_order_id": "string" }, "last_error": "string", "symbol": "string", "leverage": 0, "margin_per_leg": 0.0, "target_move_bps": 0, "budget_usdc": 0.0, "stop": { "queued_share_pct": 0.0, "stop_before_key_expiry": true, "hard_kill_on_stop": true }, "created_at": "string", "started_at": "string", "stopped_at": "string" } ``` # Pnl GET `https://api.pro.anboto.xyz/api/v2/portfolio/pnl` Daily PnL from equity closes at 00:00 UTC, net of deposits and withdrawals: the same figures as the PnL page of the trading UI. `total` covers the whole selection; with `groupBy`, `groups` splits it per exchange or account (money values add up to the total, ratios do not). Every `*_pct` value is in percent. `period_return_pct` is a simple return, not time-weighted; `equity_prev` in each point gives the denominator for a time-weighted return. `nav_usd` and `today_pnl` come from live equity (`as_of`). Exchanges without daily PnL coverage are listed in `uncovered_exchanges` and never counted as zero. Scope spot or future is recomputed per day and limited to 366 days. **ApiKeyAuth** required. ### Query params `accounts` string Comma-separated accounts: `binance` = every account on Binance (main and subaccounts), `binance:` = the main account only, `binance:Sub1` = that subaccount. Omit for every account of the team. At most 20 items. Unlike /api/v2/trading/\*, a missing subaccount means all accounts. Sign the raw value, e.g. `accounts=binance:,bybit:Sub1`. Example: `binance:,bybit:Sub1` `scope` enum Wallet scope: total (default), spot or future — `total`, `spot`, `future` Default: `total` `groupBy` enum Split the result into `groups`: none (default), exchange or account — `none`, `exchange`, `account` Default: `none` `period` string Window ending at endDate: `d` (N from 1 to 3660), week, month, quarter or year. Default 30d. Ignored when startDate is given Example: `90d` `startDate` date First day, YYYY-MM-DD (UTC, inclusive) `endDate` date Last day, YYYY-MM-DD (UTC, inclusive). At most today. The series ends yesterday at the latest, the last closed day: the default, and the day an endDate of today is answered up to (`to_date` gives the applied end; today's PnL so far is `today_pnl`). The window spans at most 3660 days, or 366 days for scope spot or future ### Headers | Header | | | | --------------- | ----------------- | -------- | | `X-API-KEY` | string | required | | `X-TIMESTAMP` | int64 ms | required | | `X-SIGN` | string | required | | `X-RECV-WINDOW` | int, default 5000 | | ### Responses | | | | --- | ---------------------------------------- | | 200 | The daily PnL | | 400 | Invalid parameter, | | 401 | Unauthorized: missing or unknown API key | | 429 | Rate limit exceeded, retry later | | 503 | The portfolio service is unavailable, | ### Response fields — [PortfolioPnlResponse](https://api-docs.anboto.xyz/reference/schemas/#portfoliopnlresponse) `as_of` date-time required UTC time of the newest live equity snapshot used for today_pnl; null when none was available `nav_usd` number required Net asset value of the selection now: the sum of each account's newest live equity snapshot (at most 3 days old; for scope spot or future, that wallet's equity), in USD. Null when no snapshot was available `from_date` date required First day of the window (YYYY-MM-DD, UTC), as applied `to_date` date required Last day of the window (YYYY-MM-DD, UTC), as applied. Days are closed at 00:00 UTC, so this is at most yesterday `scope` enum required Wallet scope — `total`, `spot`, `future` `group_by` enum required Grouping of `groups` — `none`, `exchange`, `account` `currency` string required Currency of every money value Example: `USD` `accounts` array\[[PortfolioAccountRef](https://api-docs.anboto.xyz/reference/schemas/#portfolioaccountref)\] required The resolved account selection; null when the request covered every account of the team `accounts[].exchange` string required Exchange code, e.g. binance `accounts[].subaccount` string required Subaccount name; "" is the main account and null means every account on the exchange `uncovered_exchanges` array[string] Requested or connected exchanges without daily PnL coverage. They are left out of every figure, never counted as zero `total` [PnlSummary](https://api-docs.anboto.xyz/reference/schemas/#pnlsummary) required PnL figures and daily series of a selection `total.today_pnl` number required PnL since 00:00 UTC from live equity; null when no live snapshot exists or a flow today could not be priced `total.cumulative_pnl` number required Sum of daily_pnl over the window `total.period_return_pct` number required Simple return over the window in percent: cumulative_pnl over the first flow-adjusted equity (not time-weighted) `total.since_inception_pnl` number required PnL since the selection's first closed day `total.since_inception_return_pct` number required Simple return since inception, in percent `total.since_inception_date` date required First closed day of the selection (YYYY-MM-DD) `total.sharpe` number required Sharpe ratio of the daily returns, annualised with √365; null with fewer than 2 points `total.max_drawdown_pct` number required Largest peak-to-trough drawdown in the window, in percent (≤ 0) `total.estimated` boolean True when at least one day in the window is estimated rather than closed from snapshots `total.reconstructed_range` [PnlDateRange](https://api-docs.anboto.xyz/reference/schemas/#pnldaterange) required First and last UTC day of a run of PnL points `total.point_count` integer required Number of points in series `total.series` array\[[PnlPoint](https://api-docs.anboto.xyz/reference/schemas/#pnlpoint)\] required One point per UTC day, oldest first. Days without comparable data are skipped `total.series[].date` date required UTC day (YYYY-MM-DD) `total.series[].daily_pnl` number required PnL of the day, net of deposits and withdrawals `total.series[].net_flows` number required Net external flows of the day: positive for deposits, negative for withdrawals `total.series[].equity_close` number required Equity at the day's close (00:00 UTC of the next day) `total.series[].equity_prev` number Equity at the previous close; the denominator of a time-weighted return `total.series[].daily_return_pct` number required daily_pnl over the flow-adjusted previous equity, in percent `total.series[].drawdown_pct` number required Drawdown from the running peak, in percent (≤ 0) `total.series[].daily_unrealized_pnl` number required Change of unrealised PnL over the day, where the exchange reports it `total.series[].unrealized_pnl_close` number required Unrealised PnL at the close, where the exchange reports it `total.series[].quality` enum required ok, or estimated when the close was not taken from a snapshot — `ok`, `estimated` `total.series[].reconstructed` boolean required True when the day's close or the previous close was rebuilt from the account's fills, income history and daily mark prices, for days before its first stored daily close. quality is estimated on those days `groups` array\[[PnlGroup](https://api-docs.anboto.xyz/reference/schemas/#pnlgroup)\] One entry per exchange or account; present only when group_by is not none. Money values add up to `total`; ratios (returns, sharpe, drawdown) do not `groups[].key` [PnlGroupKey](https://api-docs.anboto.xyz/reference/schemas/#pnlgroupkey) required Identity of a PnL group `groups[].as_of` date-time required UTC time of the newest live snapshot used for this group's today_pnl `groups[].today_pnl` number required Group PnL since 00:00 UTC; null when not available for this group `groups[].cumulative_pnl` number required Sum of the group's daily_pnl over the window `groups[].period_return_pct` number required Simple return of the group over the window, in percent `groups[].since_inception_pnl` number required `groups[].since_inception_return_pct` number required `groups[].since_inception_date` date required `groups[].sharpe` number required `groups[].max_drawdown_pct` number required In percent (≤ 0) `groups[].estimated` boolean True when at least one of the group's days is estimated `groups[].reconstructed_range` [PnlDateRange](https://api-docs.anboto.xyz/reference/schemas/#pnldaterange) required First and last UTC day of a run of PnL points `groups[].point_count` integer required Number of points in series `groups[].series` array\[[PnlPoint](https://api-docs.anboto.xyz/reference/schemas/#pnlpoint)\] required Only the days of total.series on which the group had data; a missing day contributed 0 `groups[].series[].date` date required UTC day (YYYY-MM-DD) `groups[].series[].daily_pnl` number required PnL of the day, net of deposits and withdrawals `groups[].series[].net_flows` number required Net external flows of the day: positive for deposits, negative for withdrawals `groups[].series[].equity_close` number required Equity at the day's close (00:00 UTC of the next day) `groups[].series[].equity_prev` number Equity at the previous close; the denominator of a time-weighted return `groups[].series[].daily_return_pct` number required daily_pnl over the flow-adjusted previous equity, in percent `groups[].series[].drawdown_pct` number required Drawdown from the running peak, in percent (≤ 0) `groups[].series[].daily_unrealized_pnl` number required Change of unrealised PnL over the day, where the exchange reports it `groups[].series[].unrealized_pnl_close` number required Unrealised PnL at the close, where the exchange reports it `groups[].series[].quality` enum required ok, or estimated when the close was not taken from a snapshot — `ok`, `estimated` `groups[].series[].reconstructed` boolean required True when the day's close or the previous close was rebuilt from the account's fills, income history and daily mark prices, for days before its first stored daily close. quality is estimated on those days ``` curl -X GET "$BASE/api/v2/portfolio/pnl?accounts=string" \ -H "X-API-KEY: $API_KEY" -H "X-TIMESTAMP: $ts" \ -H "X-SIGN: $sign" ``` ``` params = {"accounts": ..., "scope": ..., "groupBy": ..., "period": ..., "startDate": ..., "endDate": ...} r = requests.get(f"{BASE}/api/v2/portfolio/pnl", params=params headers=signed_headers_query(params)) print(r.json()) ``` ``` let resp = client .get(format!("{BASE}/api/v2/portfolio/pnl?accounts=string")) .headers(signed_headers_query(¶ms)) .send()?; println!("{}", resp.text()?); ``` ``` req, _ := http.NewRequest("GET", BASE+"/api/v2/portfolio/pnl?accounts=string", nil) for k, v := range signedHeadersQuery(req.URL.Query()) { req.Header.Set(k, v) } resp, err := http.DefaultClient.Do(req) if err != nil { log.Fatal(err) } defer resp.Body.Close() io.Copy(os.Stdout, resp.Body) ``` ``` HttpResponse resp = client.send( signedGet("/api/v2/portfolio/pnl?accounts=string"), HttpResponse.BodyHandlers.ofString()); ``` ``` const res = await fetch(`${BASE}/api/v2/portfolio/pnl?accounts=string`, { method: "GET", headers: signedHeadersQuery(params), }); const data: PortfolioPnlResponse = await res.json(); ``` ``` val request = signedGet("/api/v2/portfolio/pnl?accounts=string") val response = client.send(request, HttpResponse.BodyHandlers.ofString()) println(response.body()) ``` ``` cpr::Response r = cpr::Get( cpr::Url{BASE + "/api/v2/portfolio/pnl?accounts=string"}, signedHeadersQuery(params)); std::cout << r.text << std::endl; ``` ``` const res = await fetch(`${BASE}/api/v2/portfolio/pnl?accounts=string`, { method: "GET", headers: signedHeadersQuery(params), }); console.log(await res.json()); ``` **Response** 200 ``` { "as_of": "string", "nav_usd": 0.0, "from_date": "string", "to_date": "string", "scope": "total", "group_by": "none", "currency": "USD", "accounts": [ { "exchange": "string", "subaccount": "string" } ], "uncovered_exchanges": [ "string" ], "total": { "today_pnl": 0.0, "cumulative_pnl": 0.0, "period_return_pct": 0.0, "since_inception_pnl": 0.0, "since_inception_return_pct": 0.0, "since_inception_date": "string", "sharpe": 0.0, "max_drawdown_pct": 0.0, "estimated": true, "reconstructed_range": { "first_date": "string", "last_date": "string" }, "point_count": 0, "series": [ { "date": "string", "daily_pnl": 0.0, "net_flows": 0.0, "equity_close": 0.0, "equity_prev": 0.0, "daily_return_pct": 0.0, "drawdown_pct": 0.0, "daily_unrealized_pnl": 0.0, "unrealized_pnl_close": 0.0, "quality": "ok", "reconstructed": true } ] }, "groups": [ { "key": { "exchange": "string", "subaccount": "string", "market": "string" }, "as_of": "string", "today_pnl": 0.0, "cumulative_pnl": 0.0, "period_return_pct": 0.0, "since_inception_pnl": 0.0, "since_inception_return_pct": 0.0, "since_inception_date": "string", "sharpe": 0.0, "max_drawdown_pct": 0.0, "estimated": true, "reconstructed_range": { "first_date": "string", "last_date": "string" }, "point_count": 0, "series": [ {} ] } ] } ``` # Pre trade analysis GET `https://api.pro.anboto.xyz/api/v2/data/preTradeAnalysis` Market impact of an order before it is placed, computed from Anboto's live market snapshot (the same analysis as the trading UI): participation in the 5m volume and in the order book, impact tier LOW / MEDIUM / HIGH for TWAP / VWAP / IS at the given duration, the shortest low / medium impact durations, sweep price, slippage and share of the 24h volume. For POV, give `povRatio`: the impact tier at that participation, the estimated time to fill and the low / medium / high participation presets (`pov`). `cost_estimate` gives the expected slippage, price move and market risk from a market-impact model (uncalibrated estimate). `supported: false` with `missing` explains when the venue or symbol cannot be analysed (e.g. `exchange_not_supported`, `timeout`); `market` and `execution` are then null when no snapshot could be read or it is stale. The first call for a symbol can take a few seconds while the snapshot is built; later calls are immediate. **ApiKeyAuth** required. ### Query params `exchange` string Exchange, e.g. binance, bybit, okx `assetClass` string Asset class: spot or future `symbol` string Anboto symbol, e.g. BTC/USDT:USDT `quantity` string Order quantity in base units (coins) `strategy` string Strategy: twap, vwap, is, pov, iceberg, limit, market… `side` string buy or sell; needed for the sweep price and slippage `durationSeconds` string Execution duration in seconds (TWAP / VWAP / IS) `povRatio` string POV participation in percent of market volume, 0.01 to 33; required for pov ### Headers | Header | | | | --------------- | ----------------- | -------- | | `X-API-KEY` | string | required | | `X-TIMESTAMP` | int64 ms | required | | `X-SIGN` | string | required | | `X-RECV-WINDOW` | int, default 5000 | | ### Responses | | | | --- | ------------------------------------------------------ | | 200 | The analysis. | | 400 | Invalid parameter | | 401 | Unauthorized: missing or unknown API key | | 429 | Rate limit exceeded, retry later | | 503 | Pre-trade analysis is not available on this deployment | ### Response fields — [PreTradeAnalysis](https://api-docs.anboto.xyz/reference/schemas/#pretradeanalysis) `supported` boolean required False when the venue or symbol cannot be analysed; see missing `missing` array[string] required Inputs that could not be sourced (e.g. deep_book, ohlcv_1m) or why the analysis is unavailable (disabled, exchange_not_supported, timeout, rejected, error, stale) `snapshot_timestamp` integer Epoch ms of the market snapshot used; null when no snapshot could be read (disabled, exchange_not_supported, timeout, rejected, error) `market` object `impact` [PreTradeImpact](https://api-docs.anboto.xyz/reference/schemas/#pretradeimpact) Participation and impact tier at the requested duration `impact.tier` enum Null when no duration was given — `LOW`, `MEDIUM`, `HIGH` `impact.duration_seconds` integer `impact.volume_participation_pct` number Percent of the median 5-minute volume `impact.order_book_participation_pct` number Percent of the book depth within 20 bps, per minute `impact.book_safe` boolean The book depth can absorb the flow `impact.model` [PreTradeImpactModel](https://api-docs.anboto.xyz/reference/schemas/#pretradeimpactmodel) required Participation at a reference duration; pct(D) = pct × reference_duration_seconds / D. Volume participation above medium_pct is MEDIUM and above high_pct is HIGH, with the low order book thresholds while the order book participation is below low_order_book_participation_pct `execution` object `advice` [PreTradeAdvice](https://api-docs.anboto.xyz/reference/schemas/#pretradeadvice) Advised durations, on Anboto's duration ladder `advice.safe_duration_seconds` integer Shortest duration rated LOW `advice.moderate_duration_seconds` integer Shortest duration rated MEDIUM or better `pov` [PreTradePov](https://api-docs.anboto.xyz/reference/schemas/#pretradepov) POV model. At a participation p the order trades k = p / (1 - 2p) of everyone else's volume, because the engine counts its own fills. The impact tier depends on p alone: pace_vs_market_pct above medium_pct is MEDIUM, above high_pct is HIGH, whatever the book depth. The quantity only sets the time to fill. `pov.pov_ratio_pct` number required Requested participation, percent of market volume `pov.pace_vs_market_pct` number required Order flow as a share of the rest of the market (k) `pov.share_of_total_pct` number required Order flow as a share of all market volume, own fills included `pov.estimated_fill_seconds` integer Time to fill the quantity if market volume stays at its recent median 5-minute volume. An estimate only: POV speeds up when volume rises and slows down when it falls; passive and hybrid styles, or a limit price, can be slower `pov.estimated_fill_seconds_24h` integer Same at the 24h average volume `pov.thresholds` [PreTradeThresholds](https://api-docs.anboto.xyz/reference/schemas/#pretradethresholds) required `pov.safe_pov_pct` number Largest ladder participation rated LOW `pov.moderate_pov_pct` number Largest ladder participation rated MEDIUM or better `pov.high_pov_pct` number Smallest ladder participation rated HIGH `cost_estimate` [PreTradeCostEstimate](https://api-docs.anboto.xyz/reference/schemas/#pretradecostestimate) Expected execution cost from a market-impact model (Almgren, Thum, Hauptmann and Li, 2005) with its published coefficients, in basis points of the arrival price. Assumes normal liquidity: market makers refill the book and nobody trades heavily against the order. calibrated is false until the coefficients are fitted on Anboto fills. `cost_estimate.slippage_bps` number required Expected average execution price against arrival `cost_estimate.price_move_bps` number required Expected price move by the end of the execution `cost_estimate.permanent_bps` number required Part of the move expected to remain after the order `cost_estimate.market_risk_bps` number required One standard deviation of the market's own move over the execution time `cost_estimate.horizon_seconds` integer required Execution time assumed: the duration, or the POV time to fill `cost_estimate.pace_pct` number required Order flow as a share of the rest of the market `cost_estimate.model` string required `cost_estimate.calibrated` boolean required ``` curl -X GET "$BASE/api/v2/data/preTradeAnalysis?exchange=string" \ -H "X-API-KEY: $API_KEY" -H "X-TIMESTAMP: $ts" \ -H "X-SIGN: $sign" ``` ``` params = {"exchange": ..., "assetClass": ..., "symbol": ..., "quantity": ..., "strategy": ..., "side": ..., "durationSeconds": ..., "povRatio": ...} r = requests.get(f"{BASE}/api/v2/data/preTradeAnalysis", params=params headers=signed_headers_query(params)) print(r.json()) ``` ``` let resp = client .get(format!("{BASE}/api/v2/data/preTradeAnalysis?exchange=string")) .headers(signed_headers_query(¶ms)) .send()?; println!("{}", resp.text()?); ``` ``` req, _ := http.NewRequest("GET", BASE+"/api/v2/data/preTradeAnalysis?exchange=string", nil) for k, v := range signedHeadersQuery(req.URL.Query()) { req.Header.Set(k, v) } resp, err := http.DefaultClient.Do(req) if err != nil { log.Fatal(err) } defer resp.Body.Close() io.Copy(os.Stdout, resp.Body) ``` ``` HttpResponse resp = client.send( signedGet("/api/v2/data/preTradeAnalysis?exchange=string"), HttpResponse.BodyHandlers.ofString()); ``` ``` const res = await fetch(`${BASE}/api/v2/data/preTradeAnalysis?exchange=string`, { method: "GET", headers: signedHeadersQuery(params), }); const data: PreTradeAnalysis = await res.json(); ``` ``` val request = signedGet("/api/v2/data/preTradeAnalysis?exchange=string") val response = client.send(request, HttpResponse.BodyHandlers.ofString()) println(response.body()) ``` ``` cpr::Response r = cpr::Get( cpr::Url{BASE + "/api/v2/data/preTradeAnalysis?exchange=string"}, signedHeadersQuery(params)); std::cout << r.text << std::endl; ``` ``` const res = await fetch(`${BASE}/api/v2/data/preTradeAnalysis?exchange=string`, { method: "GET", headers: signedHeadersQuery(params), }); console.log(await res.json()); ``` **Response** 200 ``` { "supported": true, "missing": [ "string" ], "snapshot_timestamp": 0, "market": "string", "impact": { "tier": "LOW", "duration_seconds": 0, "volume_participation_pct": 0.0, "order_book_participation_pct": 0.0, "book_safe": true, "model": { "reference_duration_seconds": 0, "volume_participation_pct": 0.0, "order_book_participation_pct": 0.0, "low_order_book_participation_pct": 0.0, "thresholds_low_order_book": { "medium_pct": 0.0, "high_pct": 0.0 }, "thresholds_high_order_book": { "medium_pct": 0.0, "high_pct": 0.0 } } }, "execution": "string", "advice": { "safe_duration_seconds": 0, "moderate_duration_seconds": 0 }, "pov": { "pov_ratio_pct": 0.0, "pace_vs_market_pct": 0.0, "share_of_total_pct": 0.0, "estimated_fill_seconds": 0, "estimated_fill_seconds_24h": 0, "thresholds": { "medium_pct": 0.0, "high_pct": 0.0 }, "safe_pov_pct": 0.0, "moderate_pov_pct": 0.0, "high_pov_pct": 0.0 }, "cost_estimate": { "slippage_bps": 0.0, "price_move_bps": 0.0, "permanent_bps": 0.0, "market_risk_bps": 0.0, "horizon_seconds": 0, "pace_pct": 0.0, "model": "string", "calibrated": true } } ``` # Resume POST `https://api.pro.anboto.xyz/api/v2/strategies/campaigns/resume` paused -> running. A campaign in error also retries from here: its open legs are watched again. **ApiKeyAuth** required. ### Body params `campaign_id` string required The campaign's id (UUID) ### Headers | Header | | | | --------------- | ----------------- | -------- | | `X-API-KEY` | string | required | | `X-TIMESTAMP` | int64 ms | required | | `X-SIGN` | string | required | | `X-RECV-WINDOW` | int, default 5000 | | ### Responses | | | | --- | ------------------------------------------------------------------------------------------------------------------------------- | | 200 | The campaign, running | | 400 | campaign_id is missing or not a valid id, `{"code", "error", "errors"?}` | | 401 | Unauthorized: missing or unknown API key | | 403 | Forbidden: the API key is read-only, or the paper_farm_bot feature is not enabled for this team, `{"code", "error", "errors"?}` | | 404 | No such campaign on this account, `{"code", "error", "errors"?}` | | 409 | Not a valid transition from the campaign's current status, `{"code", "error", "errors"?}` | | 429 | Rate limit exceeded, retry later, `{"code", "error", "errors"?}` | | 503 | The strategies service is unavailable, `{"code", "error", "errors"?}` | ### Response fields — [StrategyCampaign](https://api-docs.anboto.xyz/reference/schemas/#strategycampaign) `id` string Campaign id (UUID) `type` string Campaign type; today always paper_farm `status` enum running | paused | stopped | done | error — `running`, `paused`, `stopped`, `done`, `error` `stopping` boolean A graceful stop or a hard kill is under way. Independent of status: can be true while status stays error (the open legs are being closed before the campaign reaches stopped) `phase` string Cycle phase the runner is in: idle, opening, open, closing or settling `stop_reason` string Why a stopped/done campaign ended: cycles_done, budget_spent, session_key_expiring, queued_share, user_stop or user_kill. Empty while still running `cycles_done` integer Cycles completed so far `cycles_planned` integer max_cycles from create, or null for unlimited `paper_minted` number Total PAPER minted by this campaign's losing legs `usdc_converted` number Total USDC spent converting minted PAPER (haircut + fee) `queued_usdc` number Profit queued to fund a future cycle's margin instead of being paid out `haircut_paid` number Total haircut paid converting PAPER to USDC `fees_paid` number Total trading fees paid by this campaign `current_legs` array\[[StrategyCampaignLeg](https://api-docs.anboto.xyz/reference/schemas/#strategycampaignleg)\] Open legs of the current cycle (0 while idle, up to 2 while open) `current_legs[].position_id` string The venue's position id, or null while the open is still unconfirmed `current_legs[].side` string long or short `current_legs[].entry` number Entry (mark) price the leg opened at `current_legs[].move_pct` number Signed move since entry, in percent, from this leg's point of view `current_legs[].bust` number This leg's liquidation (bust) price `current_legs[].size` number Position size `current_legs[].margin` number Margin posted for this leg, in USDC `current_legs[].leverage` integer Leverage of this leg `current_legs[].mark_price` number Latest mark price used to watch this leg `current_legs[].parent_order_id` string The order id that opened this leg `current_legs[].opened_at` date-time UTC time the leg opened, ISO 8601 `last_cycle` [StrategyCampaignCycle](https://api-docs.anboto.xyz/reference/schemas/#strategycampaigncycle) The campaign's most recently closed cycle `last_cycle.pnl_usdc` number Net result of the cycle, in USDC (can be negative) `last_cycle.paper` number PAPER minted by the losing leg of this cycle `last_cycle.closed_at` date-time UTC time both legs were closed, ISO 8601 `last_cycle.multileg_order_id` string The multileg (or paired single) order id the close went through, when known `last_error` string Why the campaign is in error; empty otherwise `symbol` string Anboto symbol being farmed, e.g. BTC/USDC:USDC `leverage` integer Leverage of each leg `margin_per_leg` number Margin posted per leg at the start of a cycle, in USDC `target_move_bps` integer Winning-leg move, in basis points, that closes the cycle `budget_usdc` number budget_usdc from create, or null for no spend cap `stop` [StrategyStopRules](https://api-docs.anboto.xyz/reference/schemas/#strategystoprules) Stop conditions the campaign watches on its own, besides an explicit stop/kill `stop.queued_share_pct` number Stop once this percent (0-100) of a new cycle's margin would come from queued profit rather than fresh budget. Null or omitted: off `stop.stop_before_key_expiry` boolean Stop gracefully once the Papertrade session key has under an hour left, rather than risk a cycle stuck open past expiry Default: `true` `stop.hard_kill_on_stop` boolean If a stop rule fires mid-cycle, close both legs at market now instead of waiting for the target Default: `false` `created_at` date-time UTC time the campaign was created, ISO 8601 `started_at` date-time UTC time the campaign started, ISO 8601 `stopped_at` date-time UTC time the campaign stopped, ISO 8601, or null while still running ``` body='{ "campaign_id": "string" }' curl -X POST "$BASE/api/v2/strategies/campaigns/resume" \ -H "X-API-KEY: $API_KEY" -H "X-TIMESTAMP: $ts" \ -H "X-SIGN: $sign" \ -H "Content-Type: application/json" -d "$body" ``` ``` payload = { "campaign_id": "string" } r = requests.post(f"{BASE}/api/v2/strategies/campaigns/resume", data=json.dumps(payload) headers=signed_headers(payload)) print(r.json()) ``` ``` let payload = serde_json::json!({ "campaign_id": "string" }); let resp = client .post(format!("{BASE}/api/v2/strategies/campaigns/resume")) .headers(signed_headers(&payload)) .json(&payload) .send()?; println!("{}", resp.text()?); ``` ``` payload := map[string]any{ "campaign_id": "string", } body, _ := json.Marshal(payload) req, _ := http.NewRequest("POST", BASE+"/api/v2/strategies/campaigns/resume", bytes.NewReader(body)) for k, v := range signedHeaders(string(body)) { req.Header.Set(k, v) } req.Header.Set("Content-Type", "application/json") resp, err := http.DefaultClient.Do(req) if err != nil { log.Fatal(err) } defer resp.Body.Close() io.Copy(os.Stdout, resp.Body) ``` ``` String jsonBody = mapper.writeValueAsString(payload); HttpResponse resp = client.send( signedPost("/api/v2/strategies/campaigns/resume", jsonBody), HttpResponse.BodyHandlers.ofString()); ``` ``` const payload: StrategyCampaignActionRequest = { "campaign_id": "string" }; const res = await fetch(`${BASE}/api/v2/strategies/campaigns/resume`, { method: "POST", headers: signedHeaders(payload), body: JSON.stringify(payload), }); const data: StrategyCampaign = await res.json(); ``` ``` val jsonBody = mapper.writeValueAsString(payload) val request = signedPost("/api/v2/strategies/campaigns/resume", jsonBody) val response = client.send(request, HttpResponse.BodyHandlers.ofString()) println(response.body()) ``` ``` std::string body = R"({ "campaign_id": "string" })"; cpr::Response r = cpr::Post( cpr::Url{BASE + "/api/v2/strategies/campaigns/resume"}, signedHeaders(body), cpr::Header{{"Content-Type", "application/json"}}, cpr::Body{body}); std::cout << r.text << std::endl; ``` ``` const payload = { "campaign_id": "string" }; const res = await fetch(`${BASE}/api/v2/strategies/campaigns/resume`, { method: "POST", headers: signedHeaders(payload), body: JSON.stringify(payload), }); console.log(await res.json()); ``` **Response** 200 ``` { "id": "string", "type": "string", "status": "running", "stopping": true, "phase": "string", "stop_reason": "string", "cycles_done": 0, "cycles_planned": 0, "paper_minted": 0.0, "usdc_converted": 0.0, "queued_usdc": 0.0, "haircut_paid": 0.0, "fees_paid": 0.0, "current_legs": [ { "position_id": "string", "side": "string", "entry": 0.0, "move_pct": 0.0, "bust": 0.0, "size": 0.0, "margin": 0.0, "leverage": 0, "mark_price": 0.0, "parent_order_id": "string", "opened_at": "string" } ], "last_cycle": { "pnl_usdc": 0.0, "paper": 0.0, "closed_at": "string", "multileg_order_id": "string" }, "last_error": "string", "symbol": "string", "leverage": 0, "margin_per_leg": 0.0, "target_move_bps": 0, "budget_usdc": 0.0, "stop": { "queued_share_pct": 0.0, "stop_before_key_expiry": true, "hard_kill_on_stop": true }, "created_at": "string", "started_at": "string", "stopped_at": "string" } ``` # Schemas Request and response objects of the Anboto Trading API. Endpoint pages link here from their type columns. ## AccountMarginResponse Margin and equity summary of a futures account on one exchange. Account value is `equity`: it already includes unrealised PnL, so a portfolio total adds spot holdings to `equity` and must not add `unrealized_pnl` again. `position_value` is exposure, not money. Fields the exchange does not report are absent rather than zero. `remaining_cushion`, `liq_distance` and `vol_cover` measure margin the same way on every exchange; they are absent for Binance portfolio-margin and Kraken accounts, and when price history is missing. `raw_margin_ratio` is the exchange's own account ratio; its convention differs between exchanges. | Field | Type | | Description | Example | | ---------------------- | ------- | --- | ------------------------------------------------------------------------------------------------------------------- | -------- | | `equity` | number | | Account equity: wallet balance plus unrealised PnL | | | `balance` | number | | Wallet balance, excluding unrealised PnL | | | `unrealized_pnl` | number | | Unrealised PnL across open positions | | | `position_value` | number | | Total notional of open positions (exposure, not account value) | | | `total_initial_margin` | number | | Initial margin locked by open positions | | | `total_maint_margin` | number | | Maintenance margin requirement | | | `total_order_margin` | number | | Margin locked by open orders, where the exchange reports it separately | | | `margin_ratio` | number | | Maintenance margin over equity, normalised to 0..1 (liquidation approached at 1) | | | `raw_margin_ratio` | number | | Venue-native account margin ratio as sent (conventions differ). Omitted when the venue has no native account ratio. | | | `raw_margin_field` | string | | Venue JSON key for raw_margin_ratio, e.g. uniMMR, mgnRatio, accountMMRate. | | | `remaining_cushion` | number | | 1 minus margin_ratio. Negative once equity is already below maintenance margin. | | | `liq_distance` | number | | (equity − maintenance margin) / notional. Absent for Binance portfolio-margin and Kraken accounts. | | | `vol_cover` | number | | Pessimistic volatility cover: (equity − maintenance margin) / Σ( | notional | | `vol_sigma_window` | string | | Label for the σ window used in vol_cover, e.g. 24h | | | `margin_estimated` | boolean | | True when maintenance margin was estimated (Lighter) rather than reported by the venue | | | `effective_leverage` | number | | Position value over equity | | | `available_balance` | number | | Balance available to open new positions | | | `account_mode` | string | | Exchange account mode, where reported (for example cross or isolated) | | ## AccountPositionResponse One open position of an account on an exchange | Field | Type | | Description | Example | | ------------------ | ------- | --- | ----------------------------------------------------- | ------- | | `collateral` | number | | The collateral amount for the position | | | `contracts` | number | | The number of contracts | | | `entryPrice` | number | | The average entry price | | | `leverage` | number | | The position leverage | | | `liquidationPrice` | number | | The liquidation price | | | `marginMode` | enum | | The margin mode of the position — `CROSS`, `ISOLATED` | | | `markPrice` | number | | The current mark price | | | `notional` | number | | The notional value of the position | | | `side` | enum | | The position side — `LONG`, `SHORT`, `BOTH` | | | `symbol` | string | | The trading symbol | | | `timestamp` | integer | | Unix timestamp in milliseconds | | | `unrealizedPnl` | number | | The unrealized profit and loss | | ## ApiErrorCode The error code used to describe why an order was rejected. Values: `OTHER`, `QUANTITY_EXCEED`, `AUTHENTICATION_ERROR`, `INSUFFICIENT_FUNDS`, `RATE_LIMIT_EXCEEDED`, `DDOS_PROTECTION`, `EXCHANGE_NOT_AVAILABLE`, `NETWORK_ERROR`, `INVALID_ORDER`, `EXCHANGE_ERROR`, `EMS_INSTANCES_DOWN`, `SLIPPAGE_EXCEEDED`, `EXPIRY_REACHED`, `MAX_FEE_PER_GAS_IS_TOO_LOW`, `PARENT_ORDER_WAS_TERMINATED`, `MAX_PRIORITY_FEE_PER_GAS_IS_TOO_LOW`, `INVALID_QUANTITY`, `INVALID_END_TIME`, `INVALID_TRADE_TIME`, `INVALID_FEE`, `INVALID_SYMBOL`, `INVALID_TRADE_STRATEGY`, `INVALID_LIMIT_PRICE`, `INVALID_WOULD_PRICE`, `INVALID_TRIGGER_PRICE`, `INVALID_PARAM`, `INVALID_EXCHANGE`, `INVALID_SIGNATURE`, `INVALID_API_KEY`, `INVALID_TIMESTAMP`, `BATCH_OVERSIZE`, `SYSTEM_ERROR`, `INVALID_REQUEST`, `SYSTEM_BUSY` ## AssetBalanceResponse Balance of one asset in an account on an exchange | Field | Type | | Description | Example | | --------- | ------ | --- | --------------------------------- | ------- | | `balance` | number | | The total balance of the asset | | | `free` | number | | The balance available for trading | | | `symbol` | string | | The asset symbol | `BTC` | ## AssetCategory The Asset category of the order. Values: `SPOT`, `FUTURE` ## AssetClass Values: `UNDEFINED`, `SPOT`, `FUTURE`, `OPTION`, `CFD` ## CancelManyUpstreamOrdersRequest Used for cancelling many parent orders at the same time | Field | Type | | Description | Example | | -------------------------- | ---------------------------------------------------------------------------------------------------------------- | -------- | ---------------------------------------- | -------------- | | `orders` | array\[[CancelUpstreamOrderRequest](https://api-docs.anboto.xyz/reference/schemas/#cancelupstreamorderrequest)\] | required | The list of parent cancellation requests | | | `orders[].order_id` | integer | | The Anboto generated order id | `123456` | | `orders[].client_order_id` | string | | The client provided order id | `xxx-yyy-zzzz` | ## CancelUpstreamOrderRequest Used for cancelling a parent order | Field | Type | | Description | Example | | ----------------- | ------- | --- | ----------------------------- | -------------- | | `order_id` | integer | | The Anboto generated order id | `123456` | | `client_order_id` | string | | The client provided order id | `xxx-yyy-zzzz` | ## ClipSizeType The clip size for the child orders. The default is AUTOMATIC Values: `ABSOLUTE`, `PERCENTAGE`, `AUTOMATIC`, `ORDER_COUNT` ## CreateManyMultiLegsParentOrdersRequest A request to create many multilegs orders in a single request. | Field | Type | | Description | Example | | -------------------------- | ------------------------------------------------------------------------------------------------------------------------------ | -------- | --------------------------------------------------------------- | ---------------------- | | `orders` | array\[[CreateMultiLegsParentOrderRequest](https://api-docs.anboto.xyz/reference/schemas/#createmultilegsparentorderrequest)\] | required | | | | `orders[].client_order_id` | string | | A custom string to identify the order | `ABC-12345^12-10-23` | | `orders[].subaccount` | string | | The sub-account under which to trade the order | | | `orders[].algo` | [enum](https://api-docs.anboto.xyz/reference/schemas/#multilegsalgo) | required | The execution strategy for the order. — `PAIR` | | | `orders[].legs` | array\[[CreateOrderLegRequest](https://api-docs.anboto.xyz/reference/schemas/#createorderlegrequest)\] | required | The order legs | | | `orders[].start_time` | string | | The start time in UTC | `2024-01-22T22:05:00Z` | | `orders[].end_time` | string | | The end time in UTC | `2024-04-22T22:05:00Z` | | `orders[].params` | [MultiLegsOrderParams](https://api-docs.anboto.xyz/reference/schemas/#multilegsorderparams) | | The advanced order parameters to modify the execution behavior. | | ## CreateManyParentOrdersRequest A request to create many parent orders in a single request. | Field | Type | | Description | Example | | --------------------------- | ------------------------------------------------------------------------------------------------------------ | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------- | | `orders` | array\[[CreateParentOrderRequest](https://api-docs.anboto.xyz/reference/schemas/#createparentorderrequest)\] | required | | | | `orders[].client_order_id` | string | | A custom string to identify the order | `ABC-12345^12-10-23` | | `orders[].exchange` | [enum](https://api-docs.anboto.xyz/reference/schemas/#tradingexchange) | required | The exchanges available for order placement via the API — `BINANCE`, `HUOBI`, `GATEIO`, `KRAKEN`, `KUCOIN`, `OKX`, `BYBIT`, `BITGET`, … (17 values) | | | `orders[].subaccount` | string | | The sub-account under which to trade the order | | | `orders[].symbol` | string | required | The symbol using Anboto symbology, e.g. BTC/USDT | | | `orders[].asset_category` | [enum](https://api-docs.anboto.xyz/reference/schemas/#assetcategory) | required | The Asset category of the order. — `SPOT`, `FUTURE` | `SPOT` | | `orders[].side` | [enum](https://api-docs.anboto.xyz/reference/schemas/#side) | required | The side of the book to trade. — `BUY`, `SELL` | | | `orders[].quantity` | string | required | The quantity to trade as a exchange trade-able decimal value, e.g. 0.015 | | | `orders[].strategy` | [enum](https://api-docs.anboto.xyz/reference/schemas/#executionstrategy) | required | The execution strategy for the order. — `TWAP`, `VWAP`, `ICEBERG`, `POV`, `MARKET`, `LIMIT`, `IS`, `SCALE` | | | `orders[].limit_price` | string | | The exchange valid limit price for the order | `2205.10` | | `orders[].limit_is_arrival` | boolean | | Use the arrival price (the midpoint when Anboto accepts the order) as the limit price; params.limit_bps shifts it. Mutually exclusive with limit_price. | | | `orders[].start_time` | string | | The start time in UTC | `2024-01-22T22:05:00Z` | | `orders[].end_time` | string | | The end time in UTC | `2024-04-22T22:05:00Z` | | `orders[].clip_size_type` | [enum](https://api-docs.anboto.xyz/reference/schemas/#clipsizetype) | | The clip size for the child orders. The default is AUTOMATIC — `ABSOLUTE`, `PERCENTAGE`, `AUTOMATIC`, `ORDER_COUNT` | `AUTOMATIC` | | `orders[].clip_size_val` | string | | The clip size value, required if the type is ABSOLUTE or PERCENTAGE | `0.01` | | `orders[].params` | [OrderParams](https://api-docs.anboto.xyz/reference/schemas/#orderparams) | | The advanced order parameters to modify the execution behavior. | | ## CreateMultiLegsParentOrderRequest Used for creating a parent order. | Field | Type | | Description | Example | | ----------------------- | ------------------------------------------------------------------------------------------------------ | -------- | --------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------- | | `client_order_id` | string | | A custom string to identify the order | `ABC-12345^12-10-23` | | `subaccount` | string | | The sub-account under which to trade the order | | | `algo` | [enum](https://api-docs.anboto.xyz/reference/schemas/#multilegsalgo) | required | The execution strategy for the order. — `PAIR` | | | `legs` | array\[[CreateOrderLegRequest](https://api-docs.anboto.xyz/reference/schemas/#createorderlegrequest)\] | required | The order legs | | | `legs[].exchange` | [enum](https://api-docs.anboto.xyz/reference/schemas/#tradingexchange) | required | The exchanges available for order placement via the API — `BINANCE`, `HUOBI`, `GATEIO`, `KRAKEN`, `KUCOIN`, `OKX`, `BYBIT`, `BITGET`, … (17 values) | | | `legs[].symbol` | string | required | The symbol using Anboto symbology, e.g. BTC/USDT | | | `legs[].asset_category` | [enum](https://api-docs.anboto.xyz/reference/schemas/#assetcategory) | required | The Asset category of the order. — `SPOT`, `FUTURE` | `SPOT` | | `legs[].side` | [enum](https://api-docs.anboto.xyz/reference/schemas/#side) | required | The side of the book to trade. — `BUY`, `SELL` | | | `legs[].target_value` | string | required | The target value to be filled | `12.0` | | `legs[].ccy` | string | required | The currency of target value | `USD` | | `legs[].limit_price` | string | | The exchange valid limit price for the order leg | `2205.10` | | `legs[].strategy` | [enum](https://api-docs.anboto.xyz/reference/schemas/#executionstrategy) | required | The execution strategy for the order. — `TWAP`, `VWAP`, `ICEBERG`, `POV`, `MARKET`, `LIMIT`, `IS`, `SCALE` | | | `legs[].clip_size_type` | [enum](https://api-docs.anboto.xyz/reference/schemas/#clipsizetype) | | The clip size for the child orders. The default is AUTOMATIC — `ABSOLUTE`, `PERCENTAGE`, `AUTOMATIC`, `ORDER_COUNT` | `AUTOMATIC` | | `legs[].clip_size_val` | string | | The clip size value, required if the type is ABSOLUTE or PERCENTAGE | `0.01` | | `legs[].params` | [OrderLegParams](https://api-docs.anboto.xyz/reference/schemas/#orderlegparams) | | The advanced order parameters to modify the execution behavior. | | | `start_time` | string | | The start time in UTC | `2024-01-22T22:05:00Z` | | `end_time` | string | | The end time in UTC | `2024-04-22T22:05:00Z` | | `params` | [MultiLegsOrderParams](https://api-docs.anboto.xyz/reference/schemas/#multilegsorderparams) | | The advanced order parameters to modify the execution behavior. | | ## CreateOrderLegRequest Used for creating a parent order. | Field | Type | | Description | Example | | -------------------------------- | ------------------------------------------------------------------------------- | -------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------- | | `exchange` | [enum](https://api-docs.anboto.xyz/reference/schemas/#tradingexchange) | required | The exchanges available for order placement via the API — `BINANCE`, `HUOBI`, `GATEIO`, `KRAKEN`, `KUCOIN`, `OKX`, `BYBIT`, `BITGET`, … (17 values) | | | `symbol` | string | required | The symbol using Anboto symbology, e.g. BTC/USDT | | | `asset_category` | [enum](https://api-docs.anboto.xyz/reference/schemas/#assetcategory) | required | The Asset category of the order. — `SPOT`, `FUTURE` | `SPOT` | | `side` | [enum](https://api-docs.anboto.xyz/reference/schemas/#side) | required | The side of the book to trade. — `BUY`, `SELL` | | | `target_value` | string | required | The target value to be filled | `12.0` | | `ccy` | string | required | The currency of target value | `USD` | | `limit_price` | string | | The exchange valid limit price for the order leg | `2205.10` | | `strategy` | [enum](https://api-docs.anboto.xyz/reference/schemas/#executionstrategy) | required | The execution strategy for the order. — `TWAP`, `VWAP`, `ICEBERG`, `POV`, `MARKET`, `LIMIT`, `IS`, `SCALE` | | | `clip_size_type` | [enum](https://api-docs.anboto.xyz/reference/schemas/#clipsizetype) | | The clip size for the child orders. The default is AUTOMATIC — `ABSOLUTE`, `PERCENTAGE`, `AUTOMATIC`, `ORDER_COUNT` | `AUTOMATIC` | | `clip_size_val` | string | | The clip size value, required if the type is ABSOLUTE or PERCENTAGE | `0.01` | | `params` | [OrderLegParams](https://api-docs.anboto.xyz/reference/schemas/#orderlegparams) | | The advanced order parameters to modify the execution behavior. | | | `params.duration_seconds` | string | | The duration of the order in seconds, this is a required field for TWAP and VWAP. | `120` | | `params.trading_style` | [enum](https://api-docs.anboto.xyz/reference/schemas/#tradingstyle) | | The trading style of the order, the default is HYBRID — `PASSIVE`, `AGGRESSIVE`, `HYBRID` | | | `params.urgency` | [enum](https://api-docs.anboto.xyz/reference/schemas/#urgency) | | The Urgency or Risk Aversion of the IS strategy, the default is MEDIUM. The parameter is not case-sensitive. Each risk aversion levels correspond to a lambda value, "that is, how much we penalize variance relative to expected cost" Low : 0.2e-6 Medium: 1e-6 High: 5e-6 Based on the paper from Almgren Chriss https://www.smallake.kr/wp-content/uploads/2016/03/optliq.pdf — `LOW`, `MEDIUM`, `HIGH` | | | `params.randomize_amount` | boolean | | Whether to randomize the slice amount | | | `params.would` | [WouldInfo](https://api-docs.anboto.xyz/reference/schemas/#wouldinfo) | | Information to instruct how to execute a Would price trigger. | | | `params.trigger` | [TriggerInfo](https://api-docs.anboto.xyz/reference/schemas/#triggerinfo) | | Information related to how the order should be triggered. | | | `params.placement_infos` | [PlacementInfo](https://api-docs.anboto.xyz/reference/schemas/#placementinfo) | | How to place an order into the book | | | `params.is_leading` | boolean | | true if this is a leading leg | | | `params.timer_iceberg_delay` | number | | Seconds between Iceberg and Scale clips, between 0.25 and 3600. Omitted: the engine uses 0.25 | `0.5` | | `params.timer_iceberg_delay_min` | number | | Lower bound, in seconds, of the Iceberg/Scale clip delay. May be 0. Set together with timer_iceberg_delay_max | `0` | | `params.timer_iceberg_delay_max` | number | | Upper bound, in seconds, of the Iceberg/Scale clip delay, up to 3600. Set together with timer_iceberg_delay_min | `10` | | `params.randomize_iceberg_timer` | boolean | | Randomize the Iceberg/Scale clip delay between 80% and 120% of timer_iceberg_delay. A min/max band replaces that draw when both bounds are set. Omitted: the engine uses true. Explicit false cannot be combined with the band | | | `params.extend_duration` | boolean | | TWAP, VWAP, and IS: extend the scheduled end past duration_seconds by a buffer, still capped by end_time. Omitted: the engine uses true | | ## CreateParentOrderRequest Used for creating a parent order. | Field | Type | | Description | Example | | -------------------------------- | ----------------------------------------------------------------------------- | -------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------- | | `client_order_id` | string | | A custom string to identify the order | `ABC-12345^12-10-23` | | `exchange` | [enum](https://api-docs.anboto.xyz/reference/schemas/#tradingexchange) | required | The exchanges available for order placement via the API — `BINANCE`, `HUOBI`, `GATEIO`, `KRAKEN`, `KUCOIN`, `OKX`, `BYBIT`, `BITGET`, … (17 values) | | | `subaccount` | string | | The sub-account under which to trade the order | | | `symbol` | string | required | The symbol using Anboto symbology, e.g. BTC/USDT | | | `asset_category` | [enum](https://api-docs.anboto.xyz/reference/schemas/#assetcategory) | required | The Asset category of the order. — `SPOT`, `FUTURE` | `SPOT` | | `side` | [enum](https://api-docs.anboto.xyz/reference/schemas/#side) | required | The side of the book to trade. — `BUY`, `SELL` | | | `quantity` | string | required | The quantity to trade as a exchange trade-able decimal value, e.g. 0.015 | | | `strategy` | [enum](https://api-docs.anboto.xyz/reference/schemas/#executionstrategy) | required | The execution strategy for the order. — `TWAP`, `VWAP`, `ICEBERG`, `POV`, `MARKET`, `LIMIT`, `IS`, `SCALE` | | | `limit_price` | string | | The exchange valid limit price for the order | `2205.10` | | `limit_is_arrival` | boolean | | Use the arrival price (the midpoint when Anboto accepts the order) as the limit price; params.limit_bps shifts it. Mutually exclusive with limit_price. | | | `start_time` | string | | The start time in UTC | `2024-01-22T22:05:00Z` | | `end_time` | string | | The end time in UTC | `2024-04-22T22:05:00Z` | | `clip_size_type` | [enum](https://api-docs.anboto.xyz/reference/schemas/#clipsizetype) | | The clip size for the child orders. The default is AUTOMATIC — `ABSOLUTE`, `PERCENTAGE`, `AUTOMATIC`, `ORDER_COUNT` | `AUTOMATIC` | | `clip_size_val` | string | | The clip size value, required if the type is ABSOLUTE or PERCENTAGE | `0.01` | | `params` | [OrderParams](https://api-docs.anboto.xyz/reference/schemas/#orderparams) | | The advanced order parameters to modify the execution behavior. | | | `params.duration_seconds` | string | | The duration of the order in seconds, this is a required field for TWAP and VWAP. | `120` | | `params.trading_style` | [enum](https://api-docs.anboto.xyz/reference/schemas/#tradingstyle) | | The trading style of the order, the default is HYBRID — `PASSIVE`, `AGGRESSIVE`, `HYBRID` | | | `params.urgency` | [enum](https://api-docs.anboto.xyz/reference/schemas/#urgency) | | The Urgency or Risk Aversion of the IS strategy, the default is MEDIUM. The parameter is not case-sensitive. Each risk aversion levels correspond to a lambda value, "that is, how much we penalize variance relative to expected cost" Low : 0.2e-6 Medium: 1e-6 High: 5e-6 Based on the paper from Almgren Chriss https://www.smallake.kr/wp-content/uploads/2016/03/optliq.pdf — `LOW`, `MEDIUM`, `HIGH` | | | `params.pov_ratio` | number | | Target participation in market volume, in percent (e.g. 5 = 5 %). Required for POV, between 0.01 and 33 | `5` | | `params.pov_risk` | [enum](https://api-docs.anboto.xyz/reference/schemas/#povrisk) | | How far the POV strategy may fall behind its target before it sends the next child order: LOW 2 %, DEFAULT 7.5 %, HIGH 15 % of the executed quantity. The parameter is not case-sensitive. — `LOW`, `DEFAULT`, `HIGH` | | | `params.randomize_amount` | boolean | | Whether to randomize the slice amount | | | `params.would` | [WouldInfo](https://api-docs.anboto.xyz/reference/schemas/#wouldinfo) | | Information to instruct how to execute a Would price trigger. | | | `params.trigger` | [TriggerInfo](https://api-docs.anboto.xyz/reference/schemas/#triggerinfo) | | Information related to how the order should be triggered. | | | `params.placement_infos` | [PlacementInfo](https://api-docs.anboto.xyz/reference/schemas/#placementinfo) | | How to place an order into the book | | | `params.reduce_only` | boolean | | Reduce Only for future positions | | | `params.start_ladder_price` | string | | Start price for Scale (ICEBERG) ladder | | | `params.end_ladder_price` | string | | End price for Scale (ICEBERG) ladder | | | `params.ladder_direction` | string | | Scale ladder direction: upwards or downwards | | | `params.ladder_profile` | string | | Scale ladder profile. Default: linear | | | `params.size_skew` | number | | Scale size skew (1 = linear). Default: 1 | | | `params.ob_imbalance_cancel` | boolean | | Cancel resting child orders and pause re-posting while the orderbook L1 imbalance leans against the order | | | `params.ob_imbalance_threshold` | string | | Opposing-side share of L1 quantity that triggers the imbalance cancel, between 0.5 and 0.99. Default: 0.75. Only used with ob_imbalance_cancel | `0.75` | | `params.price_lock_bps` | string | | Opportunistic completion: take the full remainder aggressively when the market is this many bps better than the arrival price, between 1 and 100 | `5` | | `params.limit_is_arrival` | boolean | | Use the arrival price (the midpoint when Anboto accepts the order) as the limit price; limit_bps shifts it. Mutually exclusive with top-level limit_price. | | | `params.limit_bps` | string | | Signed bps vs the parent cap (arrival or numeric limit_price). Positive = must be better; negative = may be worse. Range -100 to 100. Omitted or 0 leaves the cap unchanged. | `-10` | | `params.timer_iceberg_delay` | number | | Seconds between Iceberg and Scale clips, between 0.25 and 3600. Omitted: the engine uses 0.25 | `0.5` | | `params.timer_iceberg_delay_min` | number | | Lower bound, in seconds, of the Iceberg/Scale clip delay. May be 0. Set together with timer_iceberg_delay_max. When both are set, the engine draws once from this band instead of 80–120% of timer_iceberg_delay | `0` | | `params.timer_iceberg_delay_max` | number | | Upper bound, in seconds, of the Iceberg/Scale clip delay, up to 3600. Set together with timer_iceberg_delay_min | `10` | | `params.randomize_iceberg_timer` | boolean | | Randomize the Iceberg/Scale clip delay between 80% and 120% of timer_iceberg_delay. A min/max band replaces that draw when both bounds are set. Omitted: the engine uses true. Explicit false cannot be combined with the band | | | `params.extend_duration` | boolean | | TWAP, VWAP, and IS: extend the scheduled end past duration_seconds by a buffer, still capped by end_time. Omitted: the engine uses true | | ## CreateStrategyCampaignRequest Start a PAPER-farm campaign | Field | Type | | Description | Example | | ----------------------------- | ------------------------------------------------------------------------------------- | -------- | ----------------------------------------------------------------------------------------------------------------------------------- | --------------- | | `type` | string | required | Campaign type; today only paper_farm | | | `exchange_id` | string | required | The venue to farm on; today only papertrade | | | `symbol` | string | required | Anboto symbol, BTC/USDC:USDC or ETH/USDC:USDC | `BTC/USDC:USDC` | | `leverage` | integer | required | Leverage of each leg, 1-1000 (the leverage guard caps it well below 1000 in practice) | | | `margin_per_leg` | number | required | Margin to post per leg at the start of a cycle, in USDC (>= 10) | | | `target_move_bps` | integer | required | Winning-leg move, in basis points, that closes a cycle (50-100) | | | `max_cycles` | integer | | Stop after this many cycles; omit or null for unlimited | | | `budget_usdc` | number | | Stop once this much USDC has been spent; omit or null for no cap | | | `stop` | [StrategyStopRules](https://api-docs.anboto.xyz/reference/schemas/#strategystoprules) | | Stop conditions the campaign watches on its own, besides an explicit stop/kill | | | `stop.queued_share_pct` | number | | Stop once this percent (0-100) of a new cycle's margin would come from queued profit rather than fresh budget. Null or omitted: off | | | `stop.stop_before_key_expiry` | boolean | | Stop gracefully once the Papertrade session key has under an hour left, rather than risk a cycle stuck open past expiry | | | `stop.hard_kill_on_stop` | boolean | | If a stop rule fires mid-cycle, close both legs at market now instead of waiting for the target | | ## DepthMode How placement and cancel are measured. LEVEL walks the book. BPS_SPREAD is basis points from the midpoint. Omitted means LEVEL. Values: `LEVEL`, `BPS_SPREAD` ## ExchangeCode Platform exchange identifier (all venues, including ones not tradable via the API) Values: `BINANCE`, `HUOBI`, `COINBASE_ADV`, `GATEIO`, `KRAKEN`, `KUCOIN`, `OKX`, `BYBIT`, `WOO`, `MEXC`, `BITGET`, `BULLISH`, `B2C2`, `HYPERLIQUID`, `COINBASE_PRIME`, `COINBASE_INTL`, `EXTENDED`, `LIGHTER`, `PAPERTRADE` ## ExecutionStrategy The execution strategy for the order. Values: `TWAP`, `VWAP`, `ICEBERG`, `POV`, `MARKET`, `LIMIT`, `IS`, `SCALE` ## FlowRecord One deposit, withdrawal or internal transfer leg | Field | Type | | Description | Example | | ---------------- | ------- | -------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------- | | `id` | string | required | Stable identifier of the flow | | | `time` | integer | required | Event time, ms since epoch | | | `exchange` | string | required | | | | `subaccount` | string | required | "" is the main account | | | `type` | enum | required | `deposit`, `withdrawal`, `internal_transfer` | | | `direction` | enum | required | Direction for this account — `in`, `out`, `internal`, `unknown` | | | `external` | boolean | required | True for flows that cross the team's boundary (deposits and withdrawals) | | | `asset` | string | required | | | | `qty` | number | required | Absolute amount of the asset, with every stored decimal digit | | | `usd_value` | number | required | USD value at the event time; null when the asset could not be priced | | | `net_flow_usd` | number | required | Signed contribution to the total-scope net_flows of the daily PnL (positive in, negative out). 0 for transfers within one account (whatever the price) and for unknown directions. null when the asset could not be priced: the flow is then not in the USD totals and is counted in totals.unpriced_count. counted_in_pnl is false whenever net_flow_usd is 0 for those reasons or null | | | `counted_in_pnl` | boolean | required | Whether the flow moves net_flows of the daily PnL: true when net_flow_usd is not null and direction is in or out | | | `source` | string | required | Exchange history the flow was read from, e.g. binance_deposit, binance_sub_transfer | | ## FlowTotals Sums of net_flow_usd over the whole window and selection | Field | Type | | Description | Example | | ------------------ | ------- | -------- | ------------------------------------------------------------------------------------------ | ------- | | `deposits_usd` | number | required | Sum of deposits (≥ 0) | | | `withdrawals_usd` | number | required | Sum of withdrawals, signed (≤ 0) | | | `net_external_usd` | number | required | deposits_usd + withdrawals_usd | | | `net_internal_usd` | number | required | Net of internal transfers counted in PnL (non-zero when the selection is part of the team) | | | `unpriced_count` | integer | required | Flows whose net_flow_usd is null (unpriced); they are not in the USD sums | | ## FundingRate | Field | Type | | Description | Example | | ----------- | --------- | -------- | ----------- | ------- | | `exchange` | string | required | | | | `symbol` | string | required | | | | `time` | date-time | required | | | | `nextTime` | date-time | required | | | | `rate` | number | required | | | | `nextRate` | number | | | | | `markPrice` | number | | | | ## Instrument | Field | Type | | Description | Example | | --------------------------- | ------------------------------------------------------------------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------- | | `exchange` | [enum](https://api-docs.anboto.xyz/reference/schemas/#exchangecode) | required | Platform exchange identifier (all venues, including ones not tradable via the API) — `BINANCE`, `HUOBI`, `COINBASE_ADV`, `GATEIO`, `KRAKEN`, `KUCOIN`, `OKX`, `BYBIT`, … (19 values) | | | `symbol` | string | required | | | | `baseAsset` | string | required | | | | `quoteAsset` | string | required | | | | `exchangeSymbol` | string | required | | | | `exchangeAssetClass` | string | required | | | | `assetClass` | [enum](https://api-docs.anboto.xyz/reference/schemas/#assetclass) | required | `UNDEFINED`, `SPOT`, `FUTURE`, `OPTION`, `CFD` | | | `quantityPrecision` | integer | | | | | `pricePrecision` | integer | | | | | `maxQuantityLimit` | number | | | | | `minQuantityLimit` | number | | | | | `minCostLimit` | number | | | | | `maxCostLimit` | number | | | | | `contractSize` | number | | | | | `minMarketLimit` | number | | | | | `maxMarketLimit` | number | | | | | `minPriceLimit` | number | | | | | `maxPriceLimit` | number | | | | | `enabled` | boolean | required | | | | `timestamp` | date-time | required | | | | `priceSignificantFigure` | integer | | | | | `quantitySignificantFigure` | integer | | | | | `assetId` | string | | | | ## LedgerCoverage Income ingestion status of one account and market | Field | Type | | Description | Example | | ------------------ | --------- | -------- | ----------------------------------------------------------------------------------- | ------- | | `exchange` | string | required | | | | `subaccount` | string | required | "" is the main account; null means every account on the exchange | | | `market` | enum | required | `spot`, `future` | | | `status` | enum | required | `complete`, `partial`, `unsupported` | | | `ingested_through` | date-time | required | UTC time up to which income is ingested | | | `reason` | string | required | Why the account is partial or unsupported, e.g. exchange_not_supported, key_invalid | | ## LedgerRow Income of one day and/or symbol of one account, in USD | Field | Type | | Description | Example | | -------------- | ------ | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------ | ------- | | `date` | date | required | UTC day (YYYY-MM-DD); null when group_by is symbol | | | `exchange` | string | required | | | | `subaccount` | string | required | "" is the main account | | | `symbol` | string | required | Anboto symbol, e.g. BTC/USDT:USDT (futures) or BTC/USDT (spot); null when group_by is day or for income without a symbol | | | `market` | enum | required | `spot`, `future` | | | `realized_pnl` | number | required | Realized trading PnL; null for market spot (trading fees only), never 0 | | | `funding` | number | required | Funding; null for market spot (trading fees only), never 0 | | | `commission` | number | required | Trading fees (≤ 0), spot and futures | | | `fee_rebate` | number | required | Fee rebates (≥ 0), spot and futures | | | `interest` | number | required | Margin interest: not ingested, 0 | | | `other` | number | required | Other PnL-relevant income; null for market spot (trading fees only), never 0 | | | `net` | number | required | Net realized (futures): sum of the row's components. Null for market spot: spot trading fees are in commission and fee_rebate only, never in net | | ## LedgerTotals Income components in USD. net is the net realized PnL of the futures scopes only: spot trading fees are in commission and fee_rebate but not in net. Every value is null when no day of the window is covered | Field | Type | | Description | Example | | -------------- | ------ | -------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------- | | `realized_pnl` | number | required | Realized trading PnL; null when the selection has no futures scope | | | `funding` | number | required | Funding: positive when received; null when the selection has no futures scope | | | `commission` | number | required | Trading fees (≤ 0) | | | `fee_rebate` | number | required | Fee rebates (≥ 0) | | | `interest` | number | required | Margin interest: not ingested, 0 | | | `other` | number | required | Other PnL-relevant income; null when the selection has no futures scope | | | `net` | number | required | Net realized (futures): the sum of the futures components. Spot trading fees are in commission and fee_rebate but not in net, so with a spot scope in the selection net is not the sum of the values above. Null when the selection has no futures scope | | ## MultiLegsAlgo The execution strategy for the order. Values: `PAIR` ## MultiLegsOrderParams The advanced order parameters to modify the execution behavior. Type: `object` ## OrderDetails | Field | Type | | Description | Example | | -------------------------------- | ------------------------------------------------------------------------------------ | -------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------- | | `order_id` | integer | | The Anboto generated order id | `123456` | | `client_order_id` | string | | The client provided order id | `xxx-yyy-zzz` | | `symbol` | string | | The order symbol in Anboto's symbology | | | `status` | [enum](https://api-docs.anboto.xyz/reference/schemas/#orderstatus) | | The order status — `PENDING_NEW`, `ACCEPTED`, `REJECTED`, `PARTIALLY_FILLED`, `FILLED`, `PENDING_CANCEL`, `CANCELLED`, `PENDING_PAUSE`, … (12 values) | | | `asset_class` | [enum](https://api-docs.anboto.xyz/reference/schemas/#assetcategory) | | The Asset category of the order. — `SPOT`, `FUTURE` | `SPOT` | | `exchange` | [enum](https://api-docs.anboto.xyz/reference/schemas/#tradingexchange) | | The exchanges available for order placement via the API — `BINANCE`, `HUOBI`, `GATEIO`, `KRAKEN`, `KUCOIN`, `OKX`, `BYBIT`, `BITGET`, … (17 values) | | | `strategy` | [enum](https://api-docs.anboto.xyz/reference/schemas/#executionstrategy) | | The execution strategy for the order. — `TWAP`, `VWAP`, `ICEBERG`, `POV`, `MARKET`, `LIMIT`, `IS`, `SCALE` | `VWAP` | | `start_time` | number | | The time when the order start trading from epoch time in ms | | | `end_time` | number | | The scheduled end of the execution from epoch time in ms while the order is working (e.g. start_time + duration for a TWAP); the time the order reached its terminal state once finished | | | `quantity` | number | | The total quantity of the parent order in base asset, as placed. Absent for value-target (notional) orders, see target_value | `6` | | `filled_quantity` | number | required | The absolute amount of the order quantity filled | `0` | | `leaves_quantity` | number | required | The absolute amount of the parent order quantity remaining to be filled (quantity - filled_quantity, 0 once the order is terminal). This is the parent order's remainder, never the leaves of the child order currently working it | `0` | | `progress` | number | | Execution progress of the parent order between 0 and 1: filled_quantity / quantity, or filled notional / target_value for value-target orders. Same computation as the WebSocket order topic orderProgress; 1 once FILLED. Absent when the parent order is not known | `0.1783` | | `side` | [enum](https://api-docs.anboto.xyz/reference/schemas/#side) | | The side of the book to trade. — `BUY`, `SELL` | | | `last_quantity` | number | required | The last qty received in a fill from the exchange | `0` | | `last_price` | number | required | The last price executed on the exchange | `0` | | `average_price` | number | required | The average execution price of the order | `0` | | `limit_price` | number | | The limit price of the parent order, if one was set | | | `clip_size_type` | [enum](https://api-docs.anboto.xyz/reference/schemas/#clipsizetype) | | The clip size for the child orders. The default is AUTOMATIC — `ABSOLUTE`, `PERCENTAGE`, `AUTOMATIC`, `ORDER_COUNT` | | | `clip_size_val` | number | | The clip size value of the parent order, as placed | | | `target_value` | number | | The target notional of a value-target order (e.g. a multi-leg order leg); quantity is absent for such orders | | | `params` | [OrderParams](https://api-docs.anboto.xyz/reference/schemas/#orderparams) | | The advanced order parameters to modify the execution behavior. | | | `params.duration_seconds` | string | | The duration of the order in seconds, this is a required field for TWAP and VWAP. | `120` | | `params.trading_style` | [enum](https://api-docs.anboto.xyz/reference/schemas/#tradingstyle) | | The trading style of the order, the default is HYBRID — `PASSIVE`, `AGGRESSIVE`, `HYBRID` | | | `params.urgency` | [enum](https://api-docs.anboto.xyz/reference/schemas/#urgency) | | The Urgency or Risk Aversion of the IS strategy, the default is MEDIUM. The parameter is not case-sensitive. Each risk aversion levels correspond to a lambda value, "that is, how much we penalize variance relative to expected cost" Low : 0.2e-6 Medium: 1e-6 High: 5e-6 Based on the paper from Almgren Chriss https://www.smallake.kr/wp-content/uploads/2016/03/optliq.pdf — `LOW`, `MEDIUM`, `HIGH` | | | `params.pov_ratio` | number | | Target participation in market volume, in percent (e.g. 5 = 5 %). Required for POV, between 0.01 and 33 | `5` | | `params.pov_risk` | [enum](https://api-docs.anboto.xyz/reference/schemas/#povrisk) | | How far the POV strategy may fall behind its target before it sends the next child order: LOW 2 %, DEFAULT 7.5 %, HIGH 15 % of the executed quantity. The parameter is not case-sensitive. — `LOW`, `DEFAULT`, `HIGH` | | | `params.randomize_amount` | boolean | | Whether to randomize the slice amount | | | `params.would` | [WouldInfo](https://api-docs.anboto.xyz/reference/schemas/#wouldinfo) | | Information to instruct how to execute a Would price trigger. | | | `params.trigger` | [TriggerInfo](https://api-docs.anboto.xyz/reference/schemas/#triggerinfo) | | Information related to how the order should be triggered. | | | `params.placement_infos` | [PlacementInfo](https://api-docs.anboto.xyz/reference/schemas/#placementinfo) | | How to place an order into the book | | | `params.reduce_only` | boolean | | Reduce Only for future positions | | | `params.start_ladder_price` | string | | Start price for Scale (ICEBERG) ladder | | | `params.end_ladder_price` | string | | End price for Scale (ICEBERG) ladder | | | `params.ladder_direction` | string | | Scale ladder direction: upwards or downwards | | | `params.ladder_profile` | string | | Scale ladder profile. Default: linear | | | `params.size_skew` | number | | Scale size skew (1 = linear). Default: 1 | | | `params.ob_imbalance_cancel` | boolean | | Cancel resting child orders and pause re-posting while the orderbook L1 imbalance leans against the order | | | `params.ob_imbalance_threshold` | string | | Opposing-side share of L1 quantity that triggers the imbalance cancel, between 0.5 and 0.99. Default: 0.75. Only used with ob_imbalance_cancel | `0.75` | | `params.price_lock_bps` | string | | Opportunistic completion: take the full remainder aggressively when the market is this many bps better than the arrival price, between 1 and 100 | `5` | | `params.limit_is_arrival` | boolean | | Use the arrival price (the midpoint when Anboto accepts the order) as the limit price; limit_bps shifts it. Mutually exclusive with top-level limit_price. | | | `params.limit_bps` | string | | Signed bps vs the parent cap (arrival or numeric limit_price). Positive = must be better; negative = may be worse. Range -100 to 100. Omitted or 0 leaves the cap unchanged. | `-10` | | `params.timer_iceberg_delay` | number | | Seconds between Iceberg and Scale clips, between 0.25 and 3600. Omitted: the engine uses 0.25 | `0.5` | | `params.timer_iceberg_delay_min` | number | | Lower bound, in seconds, of the Iceberg/Scale clip delay. May be 0. Set together with timer_iceberg_delay_max. When both are set, the engine draws once from this band instead of 80–120% of timer_iceberg_delay | `0` | | `params.timer_iceberg_delay_max` | number | | Upper bound, in seconds, of the Iceberg/Scale clip delay, up to 3600. Set together with timer_iceberg_delay_min | `10` | | `params.randomize_iceberg_timer` | boolean | | Randomize the Iceberg/Scale clip delay between 80% and 120% of timer_iceberg_delay. A min/max band replaces that draw when both bounds are set. Omitted: the engine uses true. Explicit false cannot be combined with the band | | | `params.extend_duration` | boolean | | TWAP, VWAP, and IS: extend the scheduled end past duration_seconds by a buffer, still capped by end_time. Omitted: the engine uses true | | | `trades` | array\[[TradeDetails](https://api-docs.anboto.xyz/reference/schemas/#tradedetails)\] | | The list of trades associated with this order when include_trades=true | | | `trades[].trade_id` | string | | The trade id assigned by the exchange, or the Anboto platform trade id when no exchange trade id was captured | `1204004183` | | `trades[].symbol` | string | required | The symbol of the fill in Anboto's symbology | `BTC/USDT:USDT` | | `trades[].exchange_order_id` | string | | The exchange order id of the child order the fill belongs to | `151990408` | | `trades[].client_order_id` | string | | The client order id of the child order the fill belongs to | | | `trades[].quantity` | number | required | The absolute amount filled by this trade, in base asset | `0.5` | | `trades[].price` | number | required | The traded price | `92.91` | | `trades[].direction` | enum | | The direction of the trade — `BUY`, `SELL` | `BUY` | | `trades[].maker_or_taker` | enum | | Whether the fill was made as maker or taker — `MAKER`, `TAKER` | `MAKER` | | `trades[].exec_time` | integer | | The execution time of the trade as ms since epoch | `1758276000000` | | `trades[].fee` | number | | The fee charged on the trade, in fee_currency | `0.0021` | | `trades[].fee_currency` | string | | The asset the fee was charged in | `USDT` | | `trades[].parent_order_id` | integer | | The Anboto id of the parent order the fill belongs to (the order_id of the enclosing order) | `596990285759373312` | | `trades[].child_order_id` | integer | | The Anboto id of the child (slice) order that executed on the exchange; the WebSocket trade topic carries it as order_id | `596990290020118528` | | `fees_infos` | object | | Aggregated fees per currency when include_fees=true | | ## OrderDetailsList | Field | Type | | Description | Example | | -------------------------- | ------------------------------------------------------------------------------------ | -------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------- | | `orders` | array\[[OrderDetails](https://api-docs.anboto.xyz/reference/schemas/#orderdetails)\] | required | The list of order details for separate orders. | | | `orders[].order_id` | integer | | The Anboto generated order id | `123456` | | `orders[].client_order_id` | string | | The client provided order id | `xxx-yyy-zzz` | | `orders[].symbol` | string | | The order symbol in Anboto's symbology | | | `orders[].status` | [enum](https://api-docs.anboto.xyz/reference/schemas/#orderstatus) | | The order status — `PENDING_NEW`, `ACCEPTED`, `REJECTED`, `PARTIALLY_FILLED`, `FILLED`, `PENDING_CANCEL`, `CANCELLED`, `PENDING_PAUSE`, … (12 values) | | | `orders[].asset_class` | [enum](https://api-docs.anboto.xyz/reference/schemas/#assetcategory) | | The Asset category of the order. — `SPOT`, `FUTURE` | `SPOT` | | `orders[].exchange` | [enum](https://api-docs.anboto.xyz/reference/schemas/#tradingexchange) | | The exchanges available for order placement via the API — `BINANCE`, `HUOBI`, `GATEIO`, `KRAKEN`, `KUCOIN`, `OKX`, `BYBIT`, `BITGET`, … (17 values) | | | `orders[].strategy` | [enum](https://api-docs.anboto.xyz/reference/schemas/#executionstrategy) | | The execution strategy for the order. — `TWAP`, `VWAP`, `ICEBERG`, `POV`, `MARKET`, `LIMIT`, `IS`, `SCALE` | `VWAP` | | `orders[].start_time` | number | | The time when the order start trading from epoch time in ms | | | `orders[].end_time` | number | | The scheduled end of the execution from epoch time in ms while the order is working (e.g. start_time + duration for a TWAP); the time the order reached its terminal state once finished | | | `orders[].quantity` | number | | The total quantity of the parent order in base asset, as placed. Absent for value-target (notional) orders, see target_value | `6` | | `orders[].filled_quantity` | number | required | The absolute amount of the order quantity filled | `0` | | `orders[].leaves_quantity` | number | required | The absolute amount of the parent order quantity remaining to be filled (quantity - filled_quantity, 0 once the order is terminal). This is the parent order's remainder, never the leaves of the child order currently working it | `0` | | `orders[].progress` | number | | Execution progress of the parent order between 0 and 1: filled_quantity / quantity, or filled notional / target_value for value-target orders. Same computation as the WebSocket order topic orderProgress; 1 once FILLED. Absent when the parent order is not known | `0.1783` | | `orders[].side` | [enum](https://api-docs.anboto.xyz/reference/schemas/#side) | | The side of the book to trade. — `BUY`, `SELL` | | | `orders[].last_quantity` | number | required | The last qty received in a fill from the exchange | `0` | | `orders[].last_price` | number | required | The last price executed on the exchange | `0` | | `orders[].average_price` | number | required | The average execution price of the order | `0` | | `orders[].limit_price` | number | | The limit price of the parent order, if one was set | | | `orders[].clip_size_type` | [enum](https://api-docs.anboto.xyz/reference/schemas/#clipsizetype) | | The clip size for the child orders. The default is AUTOMATIC — `ABSOLUTE`, `PERCENTAGE`, `AUTOMATIC`, `ORDER_COUNT` | | | `orders[].clip_size_val` | number | | The clip size value of the parent order, as placed | | | `orders[].target_value` | number | | The target notional of a value-target order (e.g. a multi-leg order leg); quantity is absent for such orders | | | `orders[].params` | [OrderParams](https://api-docs.anboto.xyz/reference/schemas/#orderparams) | | The advanced order parameters to modify the execution behavior. | | | `orders[].trades` | array\[[TradeDetails](https://api-docs.anboto.xyz/reference/schemas/#tradedetails)\] | | The list of trades associated with this order when include_trades=true | | | `orders[].fees_infos` | object | | Aggregated fees per currency when include_fees=true | | ## OrderLegParams The advanced order parameters to modify the execution behavior. | Field | Type | | Description | Example | | -------------------------------- | ----------------------------------------------------------------------------- | -------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------- | | `duration_seconds` | string | | The duration of the order in seconds, this is a required field for TWAP and VWAP. | `120` | | `trading_style` | [enum](https://api-docs.anboto.xyz/reference/schemas/#tradingstyle) | | The trading style of the order, the default is HYBRID — `PASSIVE`, `AGGRESSIVE`, `HYBRID` | | | `urgency` | [enum](https://api-docs.anboto.xyz/reference/schemas/#urgency) | | The Urgency or Risk Aversion of the IS strategy, the default is MEDIUM. The parameter is not case-sensitive. Each risk aversion levels correspond to a lambda value, "that is, how much we penalize variance relative to expected cost" Low : 0.2e-6 Medium: 1e-6 High: 5e-6 Based on the paper from Almgren Chriss https://www.smallake.kr/wp-content/uploads/2016/03/optliq.pdf — `LOW`, `MEDIUM`, `HIGH` | | | `randomize_amount` | boolean | | Whether to randomize the slice amount | | | `would` | [WouldInfo](https://api-docs.anboto.xyz/reference/schemas/#wouldinfo) | | Information to instruct how to execute a Would price trigger. | | | `would.would_price` | string | | The price to trigger Would mode | | | `would.would_pct` | string | required | The percent of the order to trade when the Would price triggers | | | `would.would_style` | [enum](https://api-docs.anboto.xyz/reference/schemas/#tradingstyle) | required | The trading style of the order, the default is HYBRID — `PASSIVE`, `AGGRESSIVE`, `HYBRID` | | | `would.would_is_arrival` | boolean | | Would price as arrival price | | | `would.would_bps` | string | | Bps better than the would reference (arrival or would_price) before would children trigger. Default: 1 with would_is_arrival, 0 with would_price | `5` | | `trigger` | [TriggerInfo](https://api-docs.anboto.xyz/reference/schemas/#triggerinfo) | | Information related to how the order should be triggered. | | | `trigger.trigger_price` | string | required | The price to monitor for the trigger | | | `trigger.trigger_condition` | [enum](https://api-docs.anboto.xyz/reference/schemas/#triggercondition) | required | The trigger condition to start the order — `ABOVE`, `BELOW` | | | `placement_infos` | [PlacementInfo](https://api-docs.anboto.xyz/reference/schemas/#placementinfo) | | How to place an order into the book | | | `placement_infos.placement_mode` | [enum](https://api-docs.anboto.xyz/reference/schemas/#placementmode) | required | The style used to place an order in the book. DEFAULT is the default and will be at the discretion of the trading strategy — `DEFAULT`, `TIGHT`, `CUSTOM` | | | `placement_infos.placement` | string | | Where to place new orders in the book. With depth_mode level (default) it is a book level, e.g. 2 places at the second best price. With depth_mode bps_spread it is basis points from the midpoint, a whole number from 1 to 500. | | | `placement_infos.cancel` | string | | When to cancel a resting order. With depth_mode level (default) it is a book level, e.g. 6 cancels the order once it is at level 6 of the book. With depth_mode bps_spread it is basis points from the midpoint, a whole number greater than placement and at most 1000. | | | `placement_infos.depth_mode` | [enum](https://api-docs.anboto.xyz/reference/schemas/#depthmode) | | How placement and cancel are measured. LEVEL walks the book. BPS_SPREAD is basis points from the midpoint. Omitted means LEVEL. — `LEVEL`, `BPS_SPREAD` | | | `is_leading` | boolean | | true if this is a leading leg | | | `timer_iceberg_delay` | number | | Seconds between Iceberg and Scale clips, between 0.25 and 3600. Omitted: the engine uses 0.25 | `0.5` | | `timer_iceberg_delay_min` | number | | Lower bound, in seconds, of the Iceberg/Scale clip delay. May be 0. Set together with timer_iceberg_delay_max | `0` | | `timer_iceberg_delay_max` | number | | Upper bound, in seconds, of the Iceberg/Scale clip delay, up to 3600. Set together with timer_iceberg_delay_min | `10` | | `randomize_iceberg_timer` | boolean | | Randomize the Iceberg/Scale clip delay between 80% and 120% of timer_iceberg_delay. A min/max band replaces that draw when both bounds are set. Omitted: the engine uses true. Explicit false cannot be combined with the band | | | `extend_duration` | boolean | | TWAP, VWAP, and IS: extend the scheduled end past duration_seconds by a buffer, still capped by end_time. Omitted: the engine uses true | | ## OrderParams The advanced order parameters to modify the execution behavior. | Field | Type | | Description | Example | | -------------------------------- | ----------------------------------------------------------------------------- | -------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------- | | `duration_seconds` | string | | The duration of the order in seconds, this is a required field for TWAP and VWAP. | `120` | | `trading_style` | [enum](https://api-docs.anboto.xyz/reference/schemas/#tradingstyle) | | The trading style of the order, the default is HYBRID — `PASSIVE`, `AGGRESSIVE`, `HYBRID` | | | `urgency` | [enum](https://api-docs.anboto.xyz/reference/schemas/#urgency) | | The Urgency or Risk Aversion of the IS strategy, the default is MEDIUM. The parameter is not case-sensitive. Each risk aversion levels correspond to a lambda value, "that is, how much we penalize variance relative to expected cost" Low : 0.2e-6 Medium: 1e-6 High: 5e-6 Based on the paper from Almgren Chriss https://www.smallake.kr/wp-content/uploads/2016/03/optliq.pdf — `LOW`, `MEDIUM`, `HIGH` | | | `pov_ratio` | number | | Target participation in market volume, in percent (e.g. 5 = 5 %). Required for POV, between 0.01 and 33 | `5` | | `pov_risk` | [enum](https://api-docs.anboto.xyz/reference/schemas/#povrisk) | | How far the POV strategy may fall behind its target before it sends the next child order: LOW 2 %, DEFAULT 7.5 %, HIGH 15 % of the executed quantity. The parameter is not case-sensitive. — `LOW`, `DEFAULT`, `HIGH` | | | `randomize_amount` | boolean | | Whether to randomize the slice amount | | | `would` | [WouldInfo](https://api-docs.anboto.xyz/reference/schemas/#wouldinfo) | | Information to instruct how to execute a Would price trigger. | | | `would.would_price` | string | | The price to trigger Would mode | | | `would.would_pct` | string | required | The percent of the order to trade when the Would price triggers | | | `would.would_style` | [enum](https://api-docs.anboto.xyz/reference/schemas/#tradingstyle) | required | The trading style of the order, the default is HYBRID — `PASSIVE`, `AGGRESSIVE`, `HYBRID` | | | `would.would_is_arrival` | boolean | | Would price as arrival price | | | `would.would_bps` | string | | Bps better than the would reference (arrival or would_price) before would children trigger. Default: 1 with would_is_arrival, 0 with would_price | `5` | | `trigger` | [TriggerInfo](https://api-docs.anboto.xyz/reference/schemas/#triggerinfo) | | Information related to how the order should be triggered. | | | `trigger.trigger_price` | string | required | The price to monitor for the trigger | | | `trigger.trigger_condition` | [enum](https://api-docs.anboto.xyz/reference/schemas/#triggercondition) | required | The trigger condition to start the order — `ABOVE`, `BELOW` | | | `placement_infos` | [PlacementInfo](https://api-docs.anboto.xyz/reference/schemas/#placementinfo) | | How to place an order into the book | | | `placement_infos.placement_mode` | [enum](https://api-docs.anboto.xyz/reference/schemas/#placementmode) | required | The style used to place an order in the book. DEFAULT is the default and will be at the discretion of the trading strategy — `DEFAULT`, `TIGHT`, `CUSTOM` | | | `placement_infos.placement` | string | | Where to place new orders in the book. With depth_mode level (default) it is a book level, e.g. 2 places at the second best price. With depth_mode bps_spread it is basis points from the midpoint, a whole number from 1 to 500. | | | `placement_infos.cancel` | string | | When to cancel a resting order. With depth_mode level (default) it is a book level, e.g. 6 cancels the order once it is at level 6 of the book. With depth_mode bps_spread it is basis points from the midpoint, a whole number greater than placement and at most 1000. | | | `placement_infos.depth_mode` | [enum](https://api-docs.anboto.xyz/reference/schemas/#depthmode) | | How placement and cancel are measured. LEVEL walks the book. BPS_SPREAD is basis points from the midpoint. Omitted means LEVEL. — `LEVEL`, `BPS_SPREAD` | | | `reduce_only` | boolean | | Reduce Only for future positions | | | `start_ladder_price` | string | | Start price for Scale (ICEBERG) ladder | | | `end_ladder_price` | string | | End price for Scale (ICEBERG) ladder | | | `ladder_direction` | string | | Scale ladder direction: upwards or downwards | | | `ladder_profile` | string | | Scale ladder profile. Default: linear | | | `size_skew` | number | | Scale size skew (1 = linear). Default: 1 | | | `ob_imbalance_cancel` | boolean | | Cancel resting child orders and pause re-posting while the orderbook L1 imbalance leans against the order | | | `ob_imbalance_threshold` | string | | Opposing-side share of L1 quantity that triggers the imbalance cancel, between 0.5 and 0.99. Default: 0.75. Only used with ob_imbalance_cancel | `0.75` | | `price_lock_bps` | string | | Opportunistic completion: take the full remainder aggressively when the market is this many bps better than the arrival price, between 1 and 100 | `5` | | `limit_is_arrival` | boolean | | Use the arrival price (the midpoint when Anboto accepts the order) as the limit price; limit_bps shifts it. Mutually exclusive with top-level limit_price. | | | `limit_bps` | string | | Signed bps vs the parent cap (arrival or numeric limit_price). Positive = must be better; negative = may be worse. Range -100 to 100. Omitted or 0 leaves the cap unchanged. | `-10` | | `timer_iceberg_delay` | number | | Seconds between Iceberg and Scale clips, between 0.25 and 3600. Omitted: the engine uses 0.25 | `0.5` | | `timer_iceberg_delay_min` | number | | Lower bound, in seconds, of the Iceberg/Scale clip delay. May be 0. Set together with timer_iceberg_delay_max. When both are set, the engine draws once from this band instead of 80–120% of timer_iceberg_delay | `0` | | `timer_iceberg_delay_max` | number | | Upper bound, in seconds, of the Iceberg/Scale clip delay, up to 3600. Set together with timer_iceberg_delay_min | `10` | | `randomize_iceberg_timer` | boolean | | Randomize the Iceberg/Scale clip delay between 80% and 120% of timer_iceberg_delay. A min/max band replaces that draw when both bounds are set. Omitted: the engine uses true. Explicit false cannot be combined with the band | | | `extend_duration` | boolean | | TWAP, VWAP, and IS: extend the scheduled end past duration_seconds by a buffer, still capped by end_time. Omitted: the engine uses true | | ## OrderStatus The order status Values: `PENDING_NEW`, `ACCEPTED`, `REJECTED`, `PARTIALLY_FILLED`, `FILLED`, `PENDING_CANCEL`, `CANCELLED`, `PENDING_PAUSE`, `PAUSED`, `PENDING_UNPAUSE`, `EXPIRED`, `CANCEL_REJECTED` ## OrderSummary Summarizes the state of the parent order | Field | Type | | Description | Example | | ----------------- | ------------------------------------------------------------------- | -------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------- | | `order_id` | integer | | The Anboto assigned order identifier | | | `client_order_id` | string | | A custom string to identify the order | `ABC-12345^12-10-23` | | `status` | [enum](https://api-docs.anboto.xyz/reference/schemas/#orderstatus) | | The order status — `PENDING_NEW`, `ACCEPTED`, `REJECTED`, `PARTIALLY_FILLED`, `FILLED`, `PENDING_CANCEL`, `CANCELLED`, `PENDING_PAUSE`, … (12 values) | | | `created_at` | date-time | required | The time in UTC when the order was created | `2024-01-22T22:05:00Z` | | `message` | string | | Any additional information, usually if the order was rejected | | | `error_code` | [enum](https://api-docs.anboto.xyz/reference/schemas/#apierrorcode) | | The error code used to describe why an order was rejected. — `OTHER`, `QUANTITY_EXCEED`, `AUTHENTICATION_ERROR`, `INSUFFICIENT_FUNDS`, `RATE_LIMIT_EXCEEDED`, `DDOS_PROTECTION`, `EXCHANGE_NOT_AVAILABLE`, `NETWORK_ERROR`, … (34 values) | `INVALID_ORDER` | ## OrderSummaryList | Field | Type | | Description | Example | | -------------------------- | ------------------------------------------------------------------------------------ | -------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------- | | `orders` | array\[[OrderSummary](https://api-docs.anboto.xyz/reference/schemas/#ordersummary)\] | required | The list of order summaries for separate orders. | | | `orders[].order_id` | integer | | The Anboto assigned order identifier | | | `orders[].client_order_id` | string | | A custom string to identify the order | `ABC-12345^12-10-23` | | `orders[].status` | [enum](https://api-docs.anboto.xyz/reference/schemas/#orderstatus) | | The order status — `PENDING_NEW`, `ACCEPTED`, `REJECTED`, `PARTIALLY_FILLED`, `FILLED`, `PENDING_CANCEL`, `CANCELLED`, `PENDING_PAUSE`, … (12 values) | | | `orders[].created_at` | date-time | required | The time in UTC when the order was created | `2024-01-22T22:05:00Z` | | `orders[].message` | string | | Any additional information, usually if the order was rejected | | | `orders[].error_code` | [enum](https://api-docs.anboto.xyz/reference/schemas/#apierrorcode) | | The error code used to describe why an order was rejected. — `OTHER`, `QUANTITY_EXCEED`, `AUTHENTICATION_ERROR`, `INSUFFICIENT_FUNDS`, `RATE_LIMIT_EXCEEDED`, `DDOS_PROTECTION`, `EXCHANGE_NOT_AVAILABLE`, `NETWORK_ERROR`, … (34 values) | `INVALID_ORDER` | ## PlacementInfo How to place an order into the book | Field | Type | | Description | Example | | ---------------- | -------------------------------------------------------------------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------- | | `placement_mode` | [enum](https://api-docs.anboto.xyz/reference/schemas/#placementmode) | required | The style used to place an order in the book. DEFAULT is the default and will be at the discretion of the trading strategy — `DEFAULT`, `TIGHT`, `CUSTOM` | | | `placement` | string | | Where to place new orders in the book. With depth_mode level (default) it is a book level, e.g. 2 places at the second best price. With depth_mode bps_spread it is basis points from the midpoint, a whole number from 1 to 500. | | | `cancel` | string | | When to cancel a resting order. With depth_mode level (default) it is a book level, e.g. 6 cancels the order once it is at level 6 of the book. With depth_mode bps_spread it is basis points from the midpoint, a whole number greater than placement and at most 1000. | | | `depth_mode` | [enum](https://api-docs.anboto.xyz/reference/schemas/#depthmode) | | How placement and cancel are measured. LEVEL walks the book. BPS_SPREAD is basis points from the midpoint. Omitted means LEVEL. — `LEVEL`, `BPS_SPREAD` | | ## PlacementMode The style used to place an order in the book. DEFAULT is the default and will be at the discretion of the trading strategy Values: `DEFAULT`, `TIGHT`, `CUSTOM` ## PnlDateRange First and last UTC day of a run of PnL points | Field | Type | | Description | Example | | ------------ | ---- | -------- | --------------------------- | ------- | | `first_date` | date | required | First day (YYYY-MM-DD, UTC) | | | `last_date` | date | required | Last day (YYYY-MM-DD, UTC) | | ## PnlGroup PnL of one group of accounts. Ratio fields are null when not computed per group | Field | Type | | Description | Example | | -------------------------------- | ---------------------------------------------------------------------------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------- | | `key` | [PnlGroupKey](https://api-docs.anboto.xyz/reference/schemas/#pnlgroupkey) | required | Identity of a PnL group | | | `key.exchange` | string | required | | | | `key.subaccount` | string | required | "" is the main account; null when grouping by exchange | | | `key.market` | string | required | Reserved for a later market grouping; null today | | | `as_of` | date-time | required | UTC time of the newest live snapshot used for this group's today_pnl | | | `today_pnl` | number | required | Group PnL since 00:00 UTC; null when not available for this group | | | `cumulative_pnl` | number | required | Sum of the group's daily_pnl over the window | | | `period_return_pct` | number | required | Simple return of the group over the window, in percent | | | `since_inception_pnl` | number | required | | | | `since_inception_return_pct` | number | required | | | | `since_inception_date` | date | required | | | | `sharpe` | number | required | | | | `max_drawdown_pct` | number | required | In percent (≤ 0) | | | `estimated` | boolean | | True when at least one of the group's days is estimated | | | `reconstructed_range` | [PnlDateRange](https://api-docs.anboto.xyz/reference/schemas/#pnldaterange) | required | First and last UTC day of a run of PnL points | | | `reconstructed_range.first_date` | date | required | First day (YYYY-MM-DD, UTC) | | | `reconstructed_range.last_date` | date | required | Last day (YYYY-MM-DD, UTC) | | | `point_count` | integer | required | Number of points in series | | | `series` | array\[[PnlPoint](https://api-docs.anboto.xyz/reference/schemas/#pnlpoint)\] | required | Only the days of total.series on which the group had data; a missing day contributed 0 | | | `series[].date` | date | required | UTC day (YYYY-MM-DD) | | | `series[].daily_pnl` | number | required | PnL of the day, net of deposits and withdrawals | | | `series[].net_flows` | number | required | Net external flows of the day: positive for deposits, negative for withdrawals | | | `series[].equity_close` | number | required | Equity at the day's close (00:00 UTC of the next day) | | | `series[].equity_prev` | number | | Equity at the previous close; the denominator of a time-weighted return | | | `series[].daily_return_pct` | number | required | daily_pnl over the flow-adjusted previous equity, in percent | | | `series[].drawdown_pct` | number | required | Drawdown from the running peak, in percent (≤ 0) | | | `series[].daily_unrealized_pnl` | number | required | Change of unrealised PnL over the day, where the exchange reports it | | | `series[].unrealized_pnl_close` | number | required | Unrealised PnL at the close, where the exchange reports it | | | `series[].quality` | enum | required | ok, or estimated when the close was not taken from a snapshot — `ok`, `estimated` | | | `series[].reconstructed` | boolean | required | True when the day's close or the previous close was rebuilt from the account's fills, income history and daily mark prices, for days before its first stored daily close. quality is estimated on those days | | ## PnlGroupKey Identity of a PnL group | Field | Type | | Description | Example | | ------------ | ------ | -------- | ------------------------------------------------------ | ------- | | `exchange` | string | required | | | | `subaccount` | string | required | "" is the main account; null when grouping by exchange | | | `market` | string | required | Reserved for a later market grouping; null today | | ## PnlPoint One UTC day. daily_pnl = equity_close - equity_prev - net_flows | Field | Type | | Description | Example | | ---------------------- | ------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------- | | `date` | date | required | UTC day (YYYY-MM-DD) | | | `daily_pnl` | number | required | PnL of the day, net of deposits and withdrawals | | | `net_flows` | number | required | Net external flows of the day: positive for deposits, negative for withdrawals | | | `equity_close` | number | required | Equity at the day's close (00:00 UTC of the next day) | | | `equity_prev` | number | | Equity at the previous close; the denominator of a time-weighted return | | | `daily_return_pct` | number | required | daily_pnl over the flow-adjusted previous equity, in percent | | | `drawdown_pct` | number | required | Drawdown from the running peak, in percent (≤ 0) | | | `daily_unrealized_pnl` | number | required | Change of unrealised PnL over the day, where the exchange reports it | | | `unrealized_pnl_close` | number | required | Unrealised PnL at the close, where the exchange reports it | | | `quality` | enum | required | ok, or estimated when the close was not taken from a snapshot — `ok`, `estimated` | | | `reconstructed` | boolean | required | True when the day's close or the previous close was rebuilt from the account's fills, income history and daily mark prices, for days before its first stored daily close. quality is estimated on those days | | ## PnlSummary PnL figures and daily series of a selection | Field | Type | | Description | Example | | -------------------------------- | ---------------------------------------------------------------------------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------- | | `today_pnl` | number | required | PnL since 00:00 UTC from live equity; null when no live snapshot exists or a flow today could not be priced | | | `cumulative_pnl` | number | required | Sum of daily_pnl over the window | | | `period_return_pct` | number | required | Simple return over the window in percent: cumulative_pnl over the first flow-adjusted equity (not time-weighted) | | | `since_inception_pnl` | number | required | PnL since the selection's first closed day | | | `since_inception_return_pct` | number | required | Simple return since inception, in percent | | | `since_inception_date` | date | required | First closed day of the selection (YYYY-MM-DD) | | | `sharpe` | number | required | Sharpe ratio of the daily returns, annualised with √365; null with fewer than 2 points | | | `max_drawdown_pct` | number | required | Largest peak-to-trough drawdown in the window, in percent (≤ 0) | | | `estimated` | boolean | | True when at least one day in the window is estimated rather than closed from snapshots | | | `reconstructed_range` | [PnlDateRange](https://api-docs.anboto.xyz/reference/schemas/#pnldaterange) | required | First and last UTC day of a run of PnL points | | | `reconstructed_range.first_date` | date | required | First day (YYYY-MM-DD, UTC) | | | `reconstructed_range.last_date` | date | required | Last day (YYYY-MM-DD, UTC) | | | `point_count` | integer | required | Number of points in series | | | `series` | array\[[PnlPoint](https://api-docs.anboto.xyz/reference/schemas/#pnlpoint)\] | required | One point per UTC day, oldest first. Days without comparable data are skipped | | | `series[].date` | date | required | UTC day (YYYY-MM-DD) | | | `series[].daily_pnl` | number | required | PnL of the day, net of deposits and withdrawals | | | `series[].net_flows` | number | required | Net external flows of the day: positive for deposits, negative for withdrawals | | | `series[].equity_close` | number | required | Equity at the day's close (00:00 UTC of the next day) | | | `series[].equity_prev` | number | | Equity at the previous close; the denominator of a time-weighted return | | | `series[].daily_return_pct` | number | required | daily_pnl over the flow-adjusted previous equity, in percent | | | `series[].drawdown_pct` | number | required | Drawdown from the running peak, in percent (≤ 0) | | | `series[].daily_unrealized_pnl` | number | required | Change of unrealised PnL over the day, where the exchange reports it | | | `series[].unrealized_pnl_close` | number | required | Unrealised PnL at the close, where the exchange reports it | | | `series[].quality` | enum | required | ok, or estimated when the close was not taken from a snapshot — `ok`, `estimated` | | | `series[].reconstructed` | boolean | required | True when the day's close or the previous close was rebuilt from the account's fills, income history and daily mark prices, for days before its first stored daily close. quality is estimated on those days | | ## PortfolioAccountRef An exchange account: main account, one subaccount, or every account on the exchange | Field | Type | | Description | Example | | ------------ | ------ | -------- | ------------------------------------------------------------------------------------ | ------- | | `exchange` | string | required | Exchange code, e.g. binance | | | `subaccount` | string | required | Subaccount name; "" is the main account and null means every account on the exchange | | ## PortfolioFlowsResponse Deposits, withdrawals and internal transfers of the team | Field | Type | | Description | Example | | ------------------------- | -------------------------------------------------------------------------------- | -------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------- | | `from_ms` | integer | required | Start of the window, ms since epoch (inclusive) | | | `to_ms` | integer | required | End of the window, ms since epoch (exclusive): a flow at exactly to_ms is not in this window. Pass it as startMs to read the next window | | | `flows` | array\[[FlowRecord](https://api-docs.anboto.xyz/reference/schemas/#flowrecord)\] | required | Flows of this page, oldest first | | | `flows[].id` | string | required | Stable identifier of the flow | | | `flows[].time` | integer | required | Event time, ms since epoch | | | `flows[].exchange` | string | required | | | | `flows[].subaccount` | string | required | "" is the main account | | | `flows[].type` | enum | required | `deposit`, `withdrawal`, `internal_transfer` | | | `flows[].direction` | enum | required | Direction for this account — `in`, `out`, `internal`, `unknown` | | | `flows[].external` | boolean | required | True for flows that cross the team's boundary (deposits and withdrawals) | | | `flows[].asset` | string | required | | | | `flows[].qty` | number | required | Absolute amount of the asset, with every stored decimal digit | | | `flows[].usd_value` | number | required | USD value at the event time; null when the asset could not be priced | | | `flows[].net_flow_usd` | number | required | Signed contribution to the total-scope net_flows of the daily PnL (positive in, negative out). 0 for transfers within one account (whatever the price) and for unknown directions. null when the asset could not be priced: the flow is then not in the USD totals and is counted in totals.unpriced_count. counted_in_pnl is false whenever net_flow_usd is 0 for those reasons or null | | | `flows[].counted_in_pnl` | boolean | required | Whether the flow moves net_flows of the daily PnL: true when net_flow_usd is not null and direction is in or out | | | `flows[].source` | string | required | Exchange history the flow was read from, e.g. binance_deposit, binance_sub_transfer | | | `totals` | [FlowTotals](https://api-docs.anboto.xyz/reference/schemas/#flowtotals) | required | Sums of net_flow_usd over the whole window and selection | | | `totals.deposits_usd` | number | required | Sum of deposits (≥ 0) | | | `totals.withdrawals_usd` | number | required | Sum of withdrawals, signed (≤ 0) | | | `totals.net_external_usd` | number | required | deposits_usd + withdrawals_usd | | | `totals.net_internal_usd` | number | required | Net of internal transfers counted in PnL (non-zero when the selection is part of the team) | | | `totals.unpriced_count` | integer | required | Flows whose net_flow_usd is null (unpriced); they are not in the USD sums | | | `next_cursor` | string | required | Pass as `cursor` to read the next page; null on the last page | | ## PortfolioLedgerResponse Realized PnL, funding and fees from the exchange income history | Field | Type | | Description | Example | | ----------------------------- | ---------------------------------------------------------------------------------------- | -------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------- | | `as_of` | date-time | required | UTC time of the newest ingested income data | | | `from_date` | date | required | First day of the window (YYYY-MM-DD, UTC) | | | `to_date` | date | required | Last day of the window (YYYY-MM-DD, UTC); today's figures are provisional | | | `group_by` | enum | required | Grouping of `rows` — `day`, `symbol`, `day_symbol` | | | `currency` | string | required | Currency of every money value | `USD` | | `coverage` | array\[[LedgerCoverage](https://api-docs.anboto.xyz/reference/schemas/#ledgercoverage)\] | required | Ingestion status per account and market. Unsupported venues are listed here, not reported as zero | | | `coverage[].exchange` | string | required | | | | `coverage[].subaccount` | string | required | "" is the main account; null means every account on the exchange | | | `coverage[].market` | enum | required | `spot`, `future` | | | `coverage[].status` | enum | required | `complete`, `partial`, `unsupported` | | | `coverage[].ingested_through` | date-time | required | UTC time up to which income is ingested | | | `coverage[].reason` | string | required | Why the account is partial or unsupported, e.g. exchange_not_supported, key_invalid | | | `totals` | [LedgerTotals](https://api-docs.anboto.xyz/reference/schemas/#ledgertotals) | required | Income components in USD. net is the net realized PnL of the futures scopes only: spot trading fees are in commission and fee_rebate but not in net. Every value is null when no day of the window is covered | | | `totals.realized_pnl` | number | required | Realized trading PnL; null when the selection has no futures scope | | | `totals.funding` | number | required | Funding: positive when received; null when the selection has no futures scope | | | `totals.commission` | number | required | Trading fees (≤ 0) | | | `totals.fee_rebate` | number | required | Fee rebates (≥ 0) | | | `totals.interest` | number | required | Margin interest: not ingested, 0 | | | `totals.other` | number | required | Other PnL-relevant income; null when the selection has no futures scope | | | `totals.net` | number | required | Net realized (futures): the sum of the futures components. Spot trading fees are in commission and fee_rebate but not in net, so with a spot scope in the selection net is not the sum of the values above. Null when the selection has no futures scope | | | `unpriced_assets` | array[string] | | Assets with income rows that could not be valued in USD; those amounts are missing from the USD figures | | | `rows` | array\[[LedgerRow](https://api-docs.anboto.xyz/reference/schemas/#ledgerrow)\] | required | One row per day, symbol or day and symbol, depending on group_by | | | `rows[].date` | date | required | UTC day (YYYY-MM-DD); null when group_by is symbol | | | `rows[].exchange` | string | required | | | | `rows[].subaccount` | string | required | "" is the main account | | | `rows[].symbol` | string | required | Anboto symbol, e.g. BTC/USDT:USDT (futures) or BTC/USDT (spot); null when group_by is day or for income without a symbol | | | `rows[].market` | enum | required | `spot`, `future` | | | `rows[].realized_pnl` | number | required | Realized trading PnL; null for market spot (trading fees only), never 0 | | | `rows[].funding` | number | required | Funding; null for market spot (trading fees only), never 0 | | | `rows[].commission` | number | required | Trading fees (≤ 0), spot and futures | | | `rows[].fee_rebate` | number | required | Fee rebates (≥ 0), spot and futures | | | `rows[].interest` | number | required | Margin interest: not ingested, 0 | | | `rows[].other` | number | required | Other PnL-relevant income; null for market spot (trading fees only), never 0 | | | `rows[].net` | number | required | Net realized (futures): sum of the row's components. Null for market spot: spot trading fees are in commission and fee_rebate only, never in net | | | `next_cursor` | string | required | Pass as `cursor` to read the next page; null on the last page | | ## PortfolioPnlResponse NAV daily PnL of the team, overall and per group | Field | Type | | Description | Example | | ------------------------------------- | -------------------------------------------------------------------------------------------------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------- | | `as_of` | date-time | required | UTC time of the newest live equity snapshot used for today_pnl; null when none was available | | | `nav_usd` | number | required | Net asset value of the selection now: the sum of each account's newest live equity snapshot (at most 3 days old; for scope spot or future, that wallet's equity), in USD. Null when no snapshot was available | | | `from_date` | date | required | First day of the window (YYYY-MM-DD, UTC), as applied | | | `to_date` | date | required | Last day of the window (YYYY-MM-DD, UTC), as applied. Days are closed at 00:00 UTC, so this is at most yesterday | | | `scope` | enum | required | Wallet scope — `total`, `spot`, `future` | | | `group_by` | enum | required | Grouping of `groups` — `none`, `exchange`, `account` | | | `currency` | string | required | Currency of every money value | `USD` | | `accounts` | array\[[PortfolioAccountRef](https://api-docs.anboto.xyz/reference/schemas/#portfolioaccountref)\] | required | The resolved account selection; null when the request covered every account of the team | | | `accounts[].exchange` | string | required | Exchange code, e.g. binance | | | `accounts[].subaccount` | string | required | Subaccount name; "" is the main account and null means every account on the exchange | | | `uncovered_exchanges` | array[string] | | Requested or connected exchanges without daily PnL coverage. They are left out of every figure, never counted as zero | | | `total` | [PnlSummary](https://api-docs.anboto.xyz/reference/schemas/#pnlsummary) | required | PnL figures and daily series of a selection | | | `total.today_pnl` | number | required | PnL since 00:00 UTC from live equity; null when no live snapshot exists or a flow today could not be priced | | | `total.cumulative_pnl` | number | required | Sum of daily_pnl over the window | | | `total.period_return_pct` | number | required | Simple return over the window in percent: cumulative_pnl over the first flow-adjusted equity (not time-weighted) | | | `total.since_inception_pnl` | number | required | PnL since the selection's first closed day | | | `total.since_inception_return_pct` | number | required | Simple return since inception, in percent | | | `total.since_inception_date` | date | required | First closed day of the selection (YYYY-MM-DD) | | | `total.sharpe` | number | required | Sharpe ratio of the daily returns, annualised with √365; null with fewer than 2 points | | | `total.max_drawdown_pct` | number | required | Largest peak-to-trough drawdown in the window, in percent (≤ 0) | | | `total.estimated` | boolean | | True when at least one day in the window is estimated rather than closed from snapshots | | | `total.reconstructed_range` | [PnlDateRange](https://api-docs.anboto.xyz/reference/schemas/#pnldaterange) | required | First and last UTC day of a run of PnL points | | | `total.point_count` | integer | required | Number of points in series | | | `total.series` | array\[[PnlPoint](https://api-docs.anboto.xyz/reference/schemas/#pnlpoint)\] | required | One point per UTC day, oldest first. Days without comparable data are skipped | | | `groups` | array\[[PnlGroup](https://api-docs.anboto.xyz/reference/schemas/#pnlgroup)\] | | One entry per exchange or account; present only when group_by is not none. Money values add up to `total`; ratios (returns, sharpe, drawdown) do not | | | `groups[].key` | [PnlGroupKey](https://api-docs.anboto.xyz/reference/schemas/#pnlgroupkey) | required | Identity of a PnL group | | | `groups[].as_of` | date-time | required | UTC time of the newest live snapshot used for this group's today_pnl | | | `groups[].today_pnl` | number | required | Group PnL since 00:00 UTC; null when not available for this group | | | `groups[].cumulative_pnl` | number | required | Sum of the group's daily_pnl over the window | | | `groups[].period_return_pct` | number | required | Simple return of the group over the window, in percent | | | `groups[].since_inception_pnl` | number | required | | | | `groups[].since_inception_return_pct` | number | required | | | | `groups[].since_inception_date` | date | required | | | | `groups[].sharpe` | number | required | | | | `groups[].max_drawdown_pct` | number | required | In percent (≤ 0) | | | `groups[].estimated` | boolean | | True when at least one of the group's days is estimated | | | `groups[].reconstructed_range` | [PnlDateRange](https://api-docs.anboto.xyz/reference/schemas/#pnldaterange) | required | First and last UTC day of a run of PnL points | | | `groups[].point_count` | integer | required | Number of points in series | | | `groups[].series` | array\[[PnlPoint](https://api-docs.anboto.xyz/reference/schemas/#pnlpoint)\] | required | Only the days of total.series on which the group had data; a missing day contributed 0 | | ## PovRisk How far the POV strategy may fall behind its target before it sends the next child order: LOW 2 %, DEFAULT 7.5 %, HIGH 15 % of the executed quantity. The parameter is not case-sensitive. Values: `LOW`, `DEFAULT`, `HIGH` ## PreTradeAdvice Advised durations, on Anboto's duration ladder | Field | Type | | Description | Example | | --------------------------- | ------- | --- | ---------------------------------------- | ------- | | `safe_duration_seconds` | integer | | Shortest duration rated LOW | | | `moderate_duration_seconds` | integer | | Shortest duration rated MEDIUM or better | | ## PreTradeAnalysis Pre-trade analysis of an order, from Anboto's live market snapshot | Field | Type | | Description | Example | | ------------------------------------- | ------------------------------------------------------------------------------------------- | -------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------- | | `supported` | boolean | required | False when the venue or symbol cannot be analysed; see missing | | | `missing` | array[string] | required | Inputs that could not be sourced (e.g. deep_book, ohlcv_1m) or why the analysis is unavailable (disabled, exchange_not_supported, timeout, rejected, error, stale) | | | `snapshot_timestamp` | integer | | Epoch ms of the market snapshot used; null when no snapshot could be read (disabled, exchange_not_supported, timeout, rejected, error) | | | `market` | object | | | | | `impact` | [PreTradeImpact](https://api-docs.anboto.xyz/reference/schemas/#pretradeimpact) | | Participation and impact tier at the requested duration | | | `impact.tier` | enum | | Null when no duration was given — `LOW`, `MEDIUM`, `HIGH` | | | `impact.duration_seconds` | integer | | | | | `impact.volume_participation_pct` | number | | Percent of the median 5-minute volume | | | `impact.order_book_participation_pct` | number | | Percent of the book depth within 20 bps, per minute | | | `impact.book_safe` | boolean | | The book depth can absorb the flow | | | `impact.model` | [PreTradeImpactModel](https://api-docs.anboto.xyz/reference/schemas/#pretradeimpactmodel) | required | Participation at a reference duration; pct(D) = pct × reference_duration_seconds / D. Volume participation above medium_pct is MEDIUM and above high_pct is HIGH, with the low order book thresholds while the order book participation is below low_order_book_participation_pct | | | `execution` | object | | | | | `advice` | [PreTradeAdvice](https://api-docs.anboto.xyz/reference/schemas/#pretradeadvice) | | Advised durations, on Anboto's duration ladder | | | `advice.safe_duration_seconds` | integer | | Shortest duration rated LOW | | | `advice.moderate_duration_seconds` | integer | | Shortest duration rated MEDIUM or better | | | `pov` | [PreTradePov](https://api-docs.anboto.xyz/reference/schemas/#pretradepov) | | POV model. At a participation p the order trades k = p / (1 - 2p) of everyone else's volume, because the engine counts its own fills. The impact tier depends on p alone: pace_vs_market_pct above medium_pct is MEDIUM, above high_pct is HIGH, whatever the book depth. The quantity only sets the time to fill. | | | `pov.pov_ratio_pct` | number | required | Requested participation, percent of market volume | | | `pov.pace_vs_market_pct` | number | required | Order flow as a share of the rest of the market (k) | | | `pov.share_of_total_pct` | number | required | Order flow as a share of all market volume, own fills included | | | `pov.estimated_fill_seconds` | integer | | Time to fill the quantity if market volume stays at its recent median 5-minute volume. An estimate only: POV speeds up when volume rises and slows down when it falls; passive and hybrid styles, or a limit price, can be slower | | | `pov.estimated_fill_seconds_24h` | integer | | Same at the 24h average volume | | | `pov.thresholds` | [PreTradeThresholds](https://api-docs.anboto.xyz/reference/schemas/#pretradethresholds) | required | | | | `pov.safe_pov_pct` | number | | Largest ladder participation rated LOW | | | `pov.moderate_pov_pct` | number | | Largest ladder participation rated MEDIUM or better | | | `pov.high_pov_pct` | number | | Smallest ladder participation rated HIGH | | | `cost_estimate` | [PreTradeCostEstimate](https://api-docs.anboto.xyz/reference/schemas/#pretradecostestimate) | | Expected execution cost from a market-impact model (Almgren, Thum, Hauptmann and Li, 2005) with its published coefficients, in basis points of the arrival price. Assumes normal liquidity: market makers refill the book and nobody trades heavily against the order. calibrated is false until the coefficients are fitted on Anboto fills. | | | `cost_estimate.slippage_bps` | number | required | Expected average execution price against arrival | | | `cost_estimate.price_move_bps` | number | required | Expected price move by the end of the execution | | | `cost_estimate.permanent_bps` | number | required | Part of the move expected to remain after the order | | | `cost_estimate.market_risk_bps` | number | required | One standard deviation of the market's own move over the execution time | | | `cost_estimate.horizon_seconds` | integer | required | Execution time assumed: the duration, or the POV time to fill | | | `cost_estimate.pace_pct` | number | required | Order flow as a share of the rest of the market | | | `cost_estimate.model` | string | required | | | | `cost_estimate.calibrated` | boolean | required | | | ## PreTradeCostEstimate Expected execution cost from a market-impact model (Almgren, Thum, Hauptmann and Li, 2005) with its published coefficients, in basis points of the arrival price. Assumes normal liquidity: market makers refill the book and nobody trades heavily against the order. calibrated is false until the coefficients are fitted on Anboto fills. | Field | Type | | Description | Example | | ----------------- | ------- | -------- | ----------------------------------------------------------------------- | ------- | | `slippage_bps` | number | required | Expected average execution price against arrival | | | `price_move_bps` | number | required | Expected price move by the end of the execution | | | `permanent_bps` | number | required | Part of the move expected to remain after the order | | | `market_risk_bps` | number | required | One standard deviation of the market's own move over the execution time | | | `horizon_seconds` | integer | required | Execution time assumed: the duration, or the POV time to fill | | | `pace_pct` | number | required | Order flow as a share of the rest of the market | | | `model` | string | required | | | | `calibrated` | boolean | required | | | ## PreTradeExecution Immediate execution figures | Field | Type | | Description | Example | | ----------------------- | ------ | --- | --------------------------------------------------------------------- | ------- | | `sweep_price` | number | | Price reached sweeping the book, half of each level assumed available | | | `slippage_pct` | number | | | | | `percent_of_24h_volume` | number | | | | ## PreTradeImpact Participation and impact tier at the requested duration | Field | Type | | Description | Example | | ---------------------------------------- | ----------------------------------------------------------------------------------------- | -------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------- | | `tier` | enum | | Null when no duration was given — `LOW`, `MEDIUM`, `HIGH` | | | `duration_seconds` | integer | | | | | `volume_participation_pct` | number | | Percent of the median 5-minute volume | | | `order_book_participation_pct` | number | | Percent of the book depth within 20 bps, per minute | | | `book_safe` | boolean | | The book depth can absorb the flow | | | `model` | [PreTradeImpactModel](https://api-docs.anboto.xyz/reference/schemas/#pretradeimpactmodel) | required | Participation at a reference duration; pct(D) = pct × reference_duration_seconds / D. Volume participation above medium_pct is MEDIUM and above high_pct is HIGH, with the low order book thresholds while the order book participation is below low_order_book_participation_pct | | | `model.reference_duration_seconds` | integer | required | | | | `model.volume_participation_pct` | number | | | | | `model.order_book_participation_pct` | number | | | | | `model.low_order_book_participation_pct` | number | required | | | | `model.thresholds_low_order_book` | [PreTradeThresholds](https://api-docs.anboto.xyz/reference/schemas/#pretradethresholds) | required | | | | `model.thresholds_high_order_book` | [PreTradeThresholds](https://api-docs.anboto.xyz/reference/schemas/#pretradethresholds) | required | | | ## PreTradeImpactModel Participation at a reference duration; pct(D) = pct × reference_duration_seconds / D. Volume participation above medium_pct is MEDIUM and above high_pct is HIGH, with the low order book thresholds while the order book participation is below low_order_book_participation_pct | Field | Type | | Description | Example | | --------------------------------------- | --------------------------------------------------------------------------------------- | -------- | ----------- | ------- | | `reference_duration_seconds` | integer | required | | | | `volume_participation_pct` | number | | | | | `order_book_participation_pct` | number | | | | | `low_order_book_participation_pct` | number | required | | | | `thresholds_low_order_book` | [PreTradeThresholds](https://api-docs.anboto.xyz/reference/schemas/#pretradethresholds) | required | | | | `thresholds_low_order_book.medium_pct` | number | required | | | | `thresholds_low_order_book.high_pct` | number | required | | | | `thresholds_high_order_book` | [PreTradeThresholds](https://api-docs.anboto.xyz/reference/schemas/#pretradethresholds) | required | | | | `thresholds_high_order_book.medium_pct` | number | required | | | | `thresholds_high_order_book.high_pct` | number | required | | | ## PreTradeMarket Market figures of the symbol | Field | Type | | Description | Example | | ---------------------- | ------- | --- | ------------------------------------------------------------------------------------------------------------- | ------- | | `last` | number | | | | | `best_bid` | number | | | | | `best_ask` | number | | | | | `mark_price` | number | | | | | `funding_rate` | number | | Current funding rate (fraction), perpetuals only | | | `open_interest` | number | | | | | `high_24h` | number | | | | | `low_24h` | number | | | | | `base_volume_24h` | number | | | | | `quote_volume_24h` | number | | | | | `volatility_short` | number | | Per-minute std of log returns, 1m candles over 5 h | | | `volatility_long` | number | | Per-minute std of log returns, 1h candles over 3 d | | | `volatility_daily` | number | | 1h log-return stdev scaled to 1 day (×√24) | | | `median_volume_5m` | number | | Median volume of the last 100 5-minute candles | | | `volume_timeframe_min` | number | | | | | `contract_size` | number | | Base units per contract when volumes and depths are in contracts (e.g. OKX); null when they are in base units | | | `min_quantity` | number | | | | | `quantity_precision` | integer | | | | | `book_levels` | integer | | Order book levels used | | | `book_source` | string | | Order book the analysis used: memory (full exchange depth) or redis (top 10 levels only) | | ## PreTradePov POV model. At a participation p the order trades k = p / (1 - 2p) of everyone else's volume, because the engine counts its own fills. The impact tier depends on p alone: pace_vs_market_pct above medium_pct is MEDIUM, above high_pct is HIGH, whatever the book depth. The quantity only sets the time to fill. | Field | Type | | Description | Example | | ---------------------------- | --------------------------------------------------------------------------------------- | -------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------- | | `pov_ratio_pct` | number | required | Requested participation, percent of market volume | | | `pace_vs_market_pct` | number | required | Order flow as a share of the rest of the market (k) | | | `share_of_total_pct` | number | required | Order flow as a share of all market volume, own fills included | | | `estimated_fill_seconds` | integer | | Time to fill the quantity if market volume stays at its recent median 5-minute volume. An estimate only: POV speeds up when volume rises and slows down when it falls; passive and hybrid styles, or a limit price, can be slower | | | `estimated_fill_seconds_24h` | integer | | Same at the 24h average volume | | | `thresholds` | [PreTradeThresholds](https://api-docs.anboto.xyz/reference/schemas/#pretradethresholds) | required | | | | `thresholds.medium_pct` | number | required | | | | `thresholds.high_pct` | number | required | | | | `safe_pov_pct` | number | | Largest ladder participation rated LOW | | | `moderate_pov_pct` | number | | Largest ladder participation rated MEDIUM or better | | | `high_pov_pct` | number | | Smallest ladder participation rated HIGH | | ## PreTradeThresholds | Field | Type | | Description | Example | | ------------ | ------ | -------- | ----------- | ------- | | `medium_pct` | number | required | | | | `high_pct` | number | required | | | ## Side The side of the book to trade. Values: `BUY`, `SELL` ## StrategyCampaign A PAPER-farm bot campaign | Field | Type | | Description | Example | | -------------------------------- | -------------------------------------------------------------------------------------------------- | --- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------- | | `id` | string | | Campaign id (UUID) | | | `type` | string | | Campaign type; today always paper_farm | | | `status` | enum | | running | paused | | `stopping` | boolean | | A graceful stop or a hard kill is under way. Independent of status: can be true while status stays error (the open legs are being closed before the campaign reaches stopped) | | | `phase` | string | | Cycle phase the runner is in: idle, opening, open, closing or settling | | | `stop_reason` | string | | Why a stopped/done campaign ended: cycles_done, budget_spent, session_key_expiring, queued_share, user_stop or user_kill. Empty while still running | | | `cycles_done` | integer | | Cycles completed so far | | | `cycles_planned` | integer | | max_cycles from create, or null for unlimited | | | `paper_minted` | number | | Total PAPER minted by this campaign's losing legs | | | `usdc_converted` | number | | Total USDC spent converting minted PAPER (haircut + fee) | | | `queued_usdc` | number | | Profit queued to fund a future cycle's margin instead of being paid out | | | `haircut_paid` | number | | Total haircut paid converting PAPER to USDC | | | `fees_paid` | number | | Total trading fees paid by this campaign | | | `current_legs` | array\[[StrategyCampaignLeg](https://api-docs.anboto.xyz/reference/schemas/#strategycampaignleg)\] | | Open legs of the current cycle (0 while idle, up to 2 while open) | | | `current_legs[].position_id` | string | | The venue's position id, or null while the open is still unconfirmed | | | `current_legs[].side` | string | | long or short | | | `current_legs[].entry` | number | | Entry (mark) price the leg opened at | | | `current_legs[].move_pct` | number | | Signed move since entry, in percent, from this leg's point of view | | | `current_legs[].bust` | number | | This leg's liquidation (bust) price | | | `current_legs[].size` | number | | Position size | | | `current_legs[].margin` | number | | Margin posted for this leg, in USDC | | | `current_legs[].leverage` | integer | | Leverage of this leg | | | `current_legs[].mark_price` | number | | Latest mark price used to watch this leg | | | `current_legs[].parent_order_id` | string | | The order id that opened this leg | | | `current_legs[].opened_at` | date-time | | UTC time the leg opened, ISO 8601 | | | `last_cycle` | [StrategyCampaignCycle](https://api-docs.anboto.xyz/reference/schemas/#strategycampaigncycle) | | The campaign's most recently closed cycle | | | `last_cycle.pnl_usdc` | number | | Net result of the cycle, in USDC (can be negative) | | | `last_cycle.paper` | number | | PAPER minted by the losing leg of this cycle | | | `last_cycle.closed_at` | date-time | | UTC time both legs were closed, ISO 8601 | | | `last_cycle.multileg_order_id` | string | | The multileg (or paired single) order id the close went through, when known | | | `last_error` | string | | Why the campaign is in error; empty otherwise | | | `symbol` | string | | Anboto symbol being farmed, e.g. BTC/USDC:USDC | | | `leverage` | integer | | Leverage of each leg | | | `margin_per_leg` | number | | Margin posted per leg at the start of a cycle, in USDC | | | `target_move_bps` | integer | | Winning-leg move, in basis points, that closes the cycle | | | `budget_usdc` | number | | budget_usdc from create, or null for no spend cap | | | `stop` | [StrategyStopRules](https://api-docs.anboto.xyz/reference/schemas/#strategystoprules) | | Stop conditions the campaign watches on its own, besides an explicit stop/kill | | | `stop.queued_share_pct` | number | | Stop once this percent (0-100) of a new cycle's margin would come from queued profit rather than fresh budget. Null or omitted: off | | | `stop.stop_before_key_expiry` | boolean | | Stop gracefully once the Papertrade session key has under an hour left, rather than risk a cycle stuck open past expiry | | | `stop.hard_kill_on_stop` | boolean | | If a stop rule fires mid-cycle, close both legs at market now instead of waiting for the target | | | `created_at` | date-time | | UTC time the campaign was created, ISO 8601 | | | `started_at` | date-time | | UTC time the campaign started, ISO 8601 | | | `stopped_at` | date-time | | UTC time the campaign stopped, ISO 8601, or null while still running | | ## StrategyCampaignActionRequest Names the campaign a pause/resume/stop/kill call acts on | Field | Type | | Description | Example | | ------------- | ------ | -------- | ------------------------ | ------- | | `campaign_id` | string | required | The campaign's id (UUID) | | ## StrategyCampaignCycle The campaign's most recently closed cycle | Field | Type | | Description | Example | | ------------------- | --------- | --- | --------------------------------------------------------------------------- | ------- | | `pnl_usdc` | number | | Net result of the cycle, in USDC (can be negative) | | | `paper` | number | | PAPER minted by the losing leg of this cycle | | | `closed_at` | date-time | | UTC time both legs were closed, ISO 8601 | | | `multileg_order_id` | string | | The multileg (or paired single) order id the close went through, when known | | ## StrategyCampaignLeg One leg (long or short) of the campaign's open or just-closed cycle | Field | Type | | Description | Example | | ----------------- | --------- | --- | -------------------------------------------------------------------- | ------- | | `position_id` | string | | The venue's position id, or null while the open is still unconfirmed | | | `side` | string | | long or short | | | `entry` | number | | Entry (mark) price the leg opened at | | | `move_pct` | number | | Signed move since entry, in percent, from this leg's point of view | | | `bust` | number | | This leg's liquidation (bust) price | | | `size` | number | | Position size | | | `margin` | number | | Margin posted for this leg, in USDC | | | `leverage` | integer | | Leverage of this leg | | | `mark_price` | number | | Latest mark price used to watch this leg | | | `parent_order_id` | string | | The order id that opened this leg | | | `opened_at` | date-time | | UTC time the leg opened, ISO 8601 | | ## StrategyCampaignList A page of the team's campaigns | Field | Type | | Description | Example | | ----------------------------- | -------------------------------------------------------------------------------------------------- | -------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------- | | `count` | integer | | Total campaigns matching the filter, across every page | | | `campaigns` | array\[[StrategyCampaign](https://api-docs.anboto.xyz/reference/schemas/#strategycampaign)\] | required | This page's campaigns, newest first | | | `campaigns[].id` | string | | Campaign id (UUID) | | | `campaigns[].type` | string | | Campaign type; today always paper_farm | | | `campaigns[].status` | enum | | running | paused | | `campaigns[].stopping` | boolean | | A graceful stop or a hard kill is under way. Independent of status: can be true while status stays error (the open legs are being closed before the campaign reaches stopped) | | | `campaigns[].phase` | string | | Cycle phase the runner is in: idle, opening, open, closing or settling | | | `campaigns[].stop_reason` | string | | Why a stopped/done campaign ended: cycles_done, budget_spent, session_key_expiring, queued_share, user_stop or user_kill. Empty while still running | | | `campaigns[].cycles_done` | integer | | Cycles completed so far | | | `campaigns[].cycles_planned` | integer | | max_cycles from create, or null for unlimited | | | `campaigns[].paper_minted` | number | | Total PAPER minted by this campaign's losing legs | | | `campaigns[].usdc_converted` | number | | Total USDC spent converting minted PAPER (haircut + fee) | | | `campaigns[].queued_usdc` | number | | Profit queued to fund a future cycle's margin instead of being paid out | | | `campaigns[].haircut_paid` | number | | Total haircut paid converting PAPER to USDC | | | `campaigns[].fees_paid` | number | | Total trading fees paid by this campaign | | | `campaigns[].current_legs` | array\[[StrategyCampaignLeg](https://api-docs.anboto.xyz/reference/schemas/#strategycampaignleg)\] | | Open legs of the current cycle (0 while idle, up to 2 while open) | | | `campaigns[].last_cycle` | [StrategyCampaignCycle](https://api-docs.anboto.xyz/reference/schemas/#strategycampaigncycle) | | The campaign's most recently closed cycle | | | `campaigns[].last_error` | string | | Why the campaign is in error; empty otherwise | | | `campaigns[].symbol` | string | | Anboto symbol being farmed, e.g. BTC/USDC:USDC | | | `campaigns[].leverage` | integer | | Leverage of each leg | | | `campaigns[].margin_per_leg` | number | | Margin posted per leg at the start of a cycle, in USDC | | | `campaigns[].target_move_bps` | integer | | Winning-leg move, in basis points, that closes the cycle | | | `campaigns[].budget_usdc` | number | | budget_usdc from create, or null for no spend cap | | | `campaigns[].stop` | [StrategyStopRules](https://api-docs.anboto.xyz/reference/schemas/#strategystoprules) | | Stop conditions the campaign watches on its own, besides an explicit stop/kill | | | `campaigns[].created_at` | date-time | | UTC time the campaign was created, ISO 8601 | | | `campaigns[].started_at` | date-time | | UTC time the campaign started, ISO 8601 | | | `campaigns[].stopped_at` | date-time | | UTC time the campaign stopped, ISO 8601, or null while still running | | ## StrategyStopRules Stop conditions the campaign watches on its own, besides an explicit stop/kill | Field | Type | | Description | Example | | ------------------------ | ------- | --- | ----------------------------------------------------------------------------------------------------------------------------------- | ------- | | `queued_share_pct` | number | | Stop once this percent (0-100) of a new cycle's margin would come from queued profit rather than fresh budget. Null or omitted: off | | | `stop_before_key_expiry` | boolean | | Stop gracefully once the Papertrade session key has under an hour left, rather than risk a cycle stuck open past expiry | | | `hard_kill_on_stop` | boolean | | If a stop rule fires mid-cycle, close both legs at market now instead of waiting for the target | | ## TradeDetails A fill of a child order, attached to its parent order | Field | Type | | Description | Example | | ------------------- | ------- | -------- | ------------------------------------------------------------------------------------------------------------------------ | -------------------- | | `trade_id` | string | | The trade id assigned by the exchange, or the Anboto platform trade id when no exchange trade id was captured | `1204004183` | | `symbol` | string | required | The symbol of the fill in Anboto's symbology | `BTC/USDT:USDT` | | `exchange_order_id` | string | | The exchange order id of the child order the fill belongs to | `151990408` | | `client_order_id` | string | | The client order id of the child order the fill belongs to | | | `quantity` | number | required | The absolute amount filled by this trade, in base asset | `0.5` | | `price` | number | required | The traded price | `92.91` | | `direction` | enum | | The direction of the trade — `BUY`, `SELL` | `BUY` | | `maker_or_taker` | enum | | Whether the fill was made as maker or taker — `MAKER`, `TAKER` | `MAKER` | | `exec_time` | integer | | The execution time of the trade as ms since epoch | `1758276000000` | | `fee` | number | | The fee charged on the trade, in fee_currency | `0.0021` | | `fee_currency` | string | | The asset the fee was charged in | `USDT` | | `parent_order_id` | integer | | The Anboto id of the parent order the fill belongs to (the order_id of the enclosing order) | `596990285759373312` | | `child_order_id` | integer | | The Anboto id of the child (slice) order that executed on the exchange; the WebSocket trade topic carries it as order_id | `596990290020118528` | ## TradeDetailsList | Field | Type | | Description | Example | | ---------------------------- | ------------------------------------------------------------------------------------ | -------- | ------------------------------------------------------------------------------------------------------------------------ | -------------------- | | `trades` | array\[[TradeDetails](https://api-docs.anboto.xyz/reference/schemas/#tradedetails)\] | required | The list of trade details | | | `trades[].trade_id` | string | | The trade id assigned by the exchange, or the Anboto platform trade id when no exchange trade id was captured | `1204004183` | | `trades[].symbol` | string | required | The symbol of the fill in Anboto's symbology | `BTC/USDT:USDT` | | `trades[].exchange_order_id` | string | | The exchange order id of the child order the fill belongs to | `151990408` | | `trades[].client_order_id` | string | | The client order id of the child order the fill belongs to | | | `trades[].quantity` | number | required | The absolute amount filled by this trade, in base asset | `0.5` | | `trades[].price` | number | required | The traded price | `92.91` | | `trades[].direction` | enum | | The direction of the trade — `BUY`, `SELL` | `BUY` | | `trades[].maker_or_taker` | enum | | Whether the fill was made as maker or taker — `MAKER`, `TAKER` | `MAKER` | | `trades[].exec_time` | integer | | The execution time of the trade as ms since epoch | `1758276000000` | | `trades[].fee` | number | | The fee charged on the trade, in fee_currency | `0.0021` | | `trades[].fee_currency` | string | | The asset the fee was charged in | `USDT` | | `trades[].parent_order_id` | integer | | The Anboto id of the parent order the fill belongs to (the order_id of the enclosing order) | `596990285759373312` | | `trades[].child_order_id` | integer | | The Anboto id of the child (slice) order that executed on the exchange; the WebSocket trade topic carries it as order_id | `596990290020118528` | ## TradingExchange The exchanges available for order placement via the API Values: `BINANCE`, `HUOBI`, `GATEIO`, `KRAKEN`, `KUCOIN`, `OKX`, `BYBIT`, `BITGET`, `WOO`, `MEXC`, `BULLISH`, `B2C2`, `COINBASE_PRIME`, `COINBASE_INTL`, `HYPERLIQUID`, `LIGHTER`, `PAPERTRADE` ## TradingStyle The trading style of the order, the default is HYBRID Values: `PASSIVE`, `AGGRESSIVE`, `HYBRID` ## TriggerCondition The trigger condition to start the order Values: `ABOVE`, `BELOW` ## TriggerInfo Information related to how the order should be triggered. | Field | Type | | Description | Example | | ------------------- | ----------------------------------------------------------------------- | -------- | ----------------------------------------------------------- | ------- | | `trigger_price` | string | required | The price to monitor for the trigger | | | `trigger_condition` | [enum](https://api-docs.anboto.xyz/reference/schemas/#triggercondition) | required | The trigger condition to start the order — `ABOVE`, `BELOW` | | ## Urgency The Urgency or Risk Aversion of the IS strategy, the default is MEDIUM. The parameter is not case-sensitive. Each risk aversion levels correspond to a lambda value, "that is, how much we penalize variance relative to expected cost" Low : 0.2e-6 Medium: 1e-6 High: 5e-6 Based on the paper from Almgren Chriss https://www.smallake.kr/wp-content/uploads/2016/03/optliq.pdf Values: `LOW`, `MEDIUM`, `HIGH` ## WouldInfo Information to instruct how to execute a Would price trigger. | Field | Type | | Description | Example | | ------------------ | ------------------------------------------------------------------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------ | ------- | | `would_price` | string | | The price to trigger Would mode | | | `would_pct` | string | required | The percent of the order to trade when the Would price triggers | | | `would_style` | [enum](https://api-docs.anboto.xyz/reference/schemas/#tradingstyle) | required | The trading style of the order, the default is HYBRID — `PASSIVE`, `AGGRESSIVE`, `HYBRID` | | | `would_is_arrival` | boolean | | Would price as arrival price | | | `would_bps` | string | | Bps better than the would reference (arrival or would_price) before would children trigger. Default: 1 with would_is_arrival, 0 with would_price | `5` | # Status GET `https://api.pro.anboto.xyz/status/ping` Returns service status and the current server timestamp in milliseconds. No authentication required. ### Responses | | | | --- | ------------- | | 200 | Service is up | ``` curl -X GET "$BASE/status/ping" ``` ``` r = requests.get(f"{BASE}/status/ping") print(r.json()) ``` ``` let resp = client .get(format!("{BASE}/status/ping")) .send()?; println!("{}", resp.text()?); ``` ``` req, _ := http.NewRequest("GET", BASE+"/status/ping", nil) resp, err := http.DefaultClient.Do(req) if err != nil { log.Fatal(err) } defer resp.Body.Close() io.Copy(os.Stdout, resp.Body) ``` ``` HttpResponse resp = client.send( signedGet("/status/ping"), HttpResponse.BodyHandlers.ofString()); ``` ``` const res = await fetch(`${BASE}/status/ping`, { method: "GET", }); const data = await res.json(); ``` ``` val request = signedGet("/status/ping") val response = client.send(request, HttpResponse.BodyHandlers.ofString()) println(response.body()) ``` ``` cpr::Response r = cpr::Get( cpr::Url{BASE + "/status/ping"}); std::cout << r.text << std::endl; ``` ``` const res = await fetch(`${BASE}/status/ping`, { method: "GET", }); console.log(await res.json()); ``` **Response** 200 ``` "{status=ok, timestamp=1783329083000}" ``` # Stop POST `https://api.pro.anboto.xyz/api/v2/strategies/campaigns/stop` The open cycle closes at its target first, then the campaign reaches stopped. Not valid from error (which still holds legs): resume or kill it instead. **ApiKeyAuth** required. ### Body params `campaign_id` string required The campaign's id (UUID) ### Headers | Header | | | | --------------- | ----------------- | -------- | | `X-API-KEY` | string | required | | `X-TIMESTAMP` | int64 ms | required | | `X-SIGN` | string | required | | `X-RECV-WINDOW` | int, default 5000 | | ### Responses | | | | --- | ----------------------------------------------------------------------------------------- | | 200 | The campaign, stopping or stopped | | 400 | campaign_id is missing or not a valid id, `{"code", "error", "errors"?}` | | 401 | Unauthorized: missing or unknown API key | | 403 | Forbidden: the API key is read-only, `{"code", "error", "errors"?}` | | 404 | No such campaign on this account, `{"code", "error", "errors"?}` | | 409 | Not a valid transition from the campaign's current status, `{"code", "error", "errors"?}` | | 429 | Rate limit exceeded, retry later, `{"code", "error", "errors"?}` | | 503 | The strategies service is unavailable, `{"code", "error", "errors"?}` | ### Response fields — [StrategyCampaign](https://api-docs.anboto.xyz/reference/schemas/#strategycampaign) `id` string Campaign id (UUID) `type` string Campaign type; today always paper_farm `status` enum running | paused | stopped | done | error — `running`, `paused`, `stopped`, `done`, `error` `stopping` boolean A graceful stop or a hard kill is under way. Independent of status: can be true while status stays error (the open legs are being closed before the campaign reaches stopped) `phase` string Cycle phase the runner is in: idle, opening, open, closing or settling `stop_reason` string Why a stopped/done campaign ended: cycles_done, budget_spent, session_key_expiring, queued_share, user_stop or user_kill. Empty while still running `cycles_done` integer Cycles completed so far `cycles_planned` integer max_cycles from create, or null for unlimited `paper_minted` number Total PAPER minted by this campaign's losing legs `usdc_converted` number Total USDC spent converting minted PAPER (haircut + fee) `queued_usdc` number Profit queued to fund a future cycle's margin instead of being paid out `haircut_paid` number Total haircut paid converting PAPER to USDC `fees_paid` number Total trading fees paid by this campaign `current_legs` array\[[StrategyCampaignLeg](https://api-docs.anboto.xyz/reference/schemas/#strategycampaignleg)\] Open legs of the current cycle (0 while idle, up to 2 while open) `current_legs[].position_id` string The venue's position id, or null while the open is still unconfirmed `current_legs[].side` string long or short `current_legs[].entry` number Entry (mark) price the leg opened at `current_legs[].move_pct` number Signed move since entry, in percent, from this leg's point of view `current_legs[].bust` number This leg's liquidation (bust) price `current_legs[].size` number Position size `current_legs[].margin` number Margin posted for this leg, in USDC `current_legs[].leverage` integer Leverage of this leg `current_legs[].mark_price` number Latest mark price used to watch this leg `current_legs[].parent_order_id` string The order id that opened this leg `current_legs[].opened_at` date-time UTC time the leg opened, ISO 8601 `last_cycle` [StrategyCampaignCycle](https://api-docs.anboto.xyz/reference/schemas/#strategycampaigncycle) The campaign's most recently closed cycle `last_cycle.pnl_usdc` number Net result of the cycle, in USDC (can be negative) `last_cycle.paper` number PAPER minted by the losing leg of this cycle `last_cycle.closed_at` date-time UTC time both legs were closed, ISO 8601 `last_cycle.multileg_order_id` string The multileg (or paired single) order id the close went through, when known `last_error` string Why the campaign is in error; empty otherwise `symbol` string Anboto symbol being farmed, e.g. BTC/USDC:USDC `leverage` integer Leverage of each leg `margin_per_leg` number Margin posted per leg at the start of a cycle, in USDC `target_move_bps` integer Winning-leg move, in basis points, that closes the cycle `budget_usdc` number budget_usdc from create, or null for no spend cap `stop` [StrategyStopRules](https://api-docs.anboto.xyz/reference/schemas/#strategystoprules) Stop conditions the campaign watches on its own, besides an explicit stop/kill `stop.queued_share_pct` number Stop once this percent (0-100) of a new cycle's margin would come from queued profit rather than fresh budget. Null or omitted: off `stop.stop_before_key_expiry` boolean Stop gracefully once the Papertrade session key has under an hour left, rather than risk a cycle stuck open past expiry Default: `true` `stop.hard_kill_on_stop` boolean If a stop rule fires mid-cycle, close both legs at market now instead of waiting for the target Default: `false` `created_at` date-time UTC time the campaign was created, ISO 8601 `started_at` date-time UTC time the campaign started, ISO 8601 `stopped_at` date-time UTC time the campaign stopped, ISO 8601, or null while still running ``` body='{ "campaign_id": "string" }' curl -X POST "$BASE/api/v2/strategies/campaigns/stop" \ -H "X-API-KEY: $API_KEY" -H "X-TIMESTAMP: $ts" \ -H "X-SIGN: $sign" \ -H "Content-Type: application/json" -d "$body" ``` ``` payload = { "campaign_id": "string" } r = requests.post(f"{BASE}/api/v2/strategies/campaigns/stop", data=json.dumps(payload) headers=signed_headers(payload)) print(r.json()) ``` ``` let payload = serde_json::json!({ "campaign_id": "string" }); let resp = client .post(format!("{BASE}/api/v2/strategies/campaigns/stop")) .headers(signed_headers(&payload)) .json(&payload) .send()?; println!("{}", resp.text()?); ``` ``` payload := map[string]any{ "campaign_id": "string", } body, _ := json.Marshal(payload) req, _ := http.NewRequest("POST", BASE+"/api/v2/strategies/campaigns/stop", bytes.NewReader(body)) for k, v := range signedHeaders(string(body)) { req.Header.Set(k, v) } req.Header.Set("Content-Type", "application/json") resp, err := http.DefaultClient.Do(req) if err != nil { log.Fatal(err) } defer resp.Body.Close() io.Copy(os.Stdout, resp.Body) ``` ``` String jsonBody = mapper.writeValueAsString(payload); HttpResponse resp = client.send( signedPost("/api/v2/strategies/campaigns/stop", jsonBody), HttpResponse.BodyHandlers.ofString()); ``` ``` const payload: StrategyCampaignActionRequest = { "campaign_id": "string" }; const res = await fetch(`${BASE}/api/v2/strategies/campaigns/stop`, { method: "POST", headers: signedHeaders(payload), body: JSON.stringify(payload), }); const data: StrategyCampaign = await res.json(); ``` ``` val jsonBody = mapper.writeValueAsString(payload) val request = signedPost("/api/v2/strategies/campaigns/stop", jsonBody) val response = client.send(request, HttpResponse.BodyHandlers.ofString()) println(response.body()) ``` ``` std::string body = R"({ "campaign_id": "string" })"; cpr::Response r = cpr::Post( cpr::Url{BASE + "/api/v2/strategies/campaigns/stop"}, signedHeaders(body), cpr::Header{{"Content-Type", "application/json"}}, cpr::Body{body}); std::cout << r.text << std::endl; ``` ``` const payload = { "campaign_id": "string" }; const res = await fetch(`${BASE}/api/v2/strategies/campaigns/stop`, { method: "POST", headers: signedHeaders(payload), body: JSON.stringify(payload), }); console.log(await res.json()); ``` **Response** 200 ``` { "id": "string", "type": "string", "status": "running", "stopping": true, "phase": "string", "stop_reason": "string", "cycles_done": 0, "cycles_planned": 0, "paper_minted": 0.0, "usdc_converted": 0.0, "queued_usdc": 0.0, "haircut_paid": 0.0, "fees_paid": 0.0, "current_legs": [ { "position_id": "string", "side": "string", "entry": 0.0, "move_pct": 0.0, "bust": 0.0, "size": 0.0, "margin": 0.0, "leverage": 0, "mark_price": 0.0, "parent_order_id": "string", "opened_at": "string" } ], "last_cycle": { "pnl_usdc": 0.0, "paper": 0.0, "closed_at": "string", "multileg_order_id": "string" }, "last_error": "string", "symbol": "string", "leverage": 0, "margin_per_leg": 0.0, "target_move_bps": 0, "budget_usdc": 0.0, "stop": { "queued_share_pct": 0.0, "stop_before_key_expiry": true, "hard_kill_on_stop": true }, "created_at": "string", "started_at": "string", "stopped_at": "string" } ``` # balance WS `wss://api.pro.anboto.xyz/api/v2/ws` Channel for subscribing to asset balance updates for a specific exchange Authenticate the connection with a listenKey — see [WebSocket](https://api-docs.anboto.xyz/resources/websocket/index.md). ### Subscribe message `topic` string required `balance` `exchange` string required Trading exchange, case-insensitive Example: `BINANCE` `method` enum required `subscribe` / `unsubscribe` ### Update message fields `balance` decimal Total balance `free` decimal Available balance `symbol` string required Asset symbol `timestamp` integer required Unix timestamp in milliseconds ### Responses | | | | -------- | ------------------------------------------------------------------------------------------------------------ | | code 0 | Acknowledgment of successful subscription | | code ≠ 0 | Error response for failed subscription — see [Errors](https://api-docs.anboto.xyz/resources/errors/index.md) | ``` { "topic": "balance", "exchange": "OKX", "method": "subscribe" } ``` ``` { "topic": "balance", "exchange": "OKX", "method": "unsubscribe" } ``` **Update** balance ``` { "balance": "100000.00", "free": "95000.00", "symbol": "USDT", "timestamp": 1708840800000 } ``` **Ack** code 0 ``` { "code": 0, "message": "string" } ``` # child_order WS `wss://api.pro.anboto.xyz/api/v2/ws` Channel for subscribing to child-order (slice) updates; subscribe with {"topic":"child_order","exchange":...,"method":"subscribe"} Authenticate the connection with a listenKey — see [WebSocket](https://api-docs.anboto.xyz/resources/websocket/index.md). ### Subscribe message `topic` string required `child_order` `exchange` string required Trading exchange, case-insensitive Example: `BINANCE` `method` enum required `subscribe` / `unsubscribe` ### Update message fields `orderStatus` OrderStatusObj Order Status `orderStatus.source` string Component sending the status `orderStatus.orderId` int64 Anboto's order Id `orderStatus.clientOrderId` string Client referenced order Id `orderStatus.extId` string Order Id from exchange `orderStatus.exchangeId` integer Exchange Id `orderStatus.status` enum Order Status — `PENDING_NEW`, `ACCEPTED`, `REJECTED`, `PARTIALLY_FILLED`, `FILLED`, `PENDING_CANCEL`, `CANCELLED`, `PENDING_PAUSE`, … (12 values) `orderStatus.createdAt` integer Unix timestamp of this status change in milliseconds `orderStatus.filledQuantity` integer filled quantity of the order `orderStatus.leavesQuantity` integer leave quantity of the order `orderStatus.side` enum order side — `BUY`, `SELL` `orderStatus.averagePrice` decimal average price of the fills `orderStatus.message` string Status message `orderStatus.errorCode` string Error code `order` object Child order context: orderId, clientOrderId, parentOrderId, exchangeId, exchangeName, symbol, assetClass, side, quantity, limitPrice, tif, expiryTime, createdAt, orderType. `orderProgress` number Execution progress of the parent order, 0..1 ### Responses | | | | -------- | ------------------------------------------------------------------------------------------------------------ | | code 0 | Acknowledgment of successful subscription | | code ≠ 0 | Error response for failed subscription — see [Errors](https://api-docs.anboto.xyz/resources/errors/index.md) | ``` { "topic": "child_order", "exchange": "BINANCE", "method": "subscribe" } ``` ``` { "topic": "child_order", "exchange": "BINANCE", "method": "unsubscribe" } ``` **Update** child_order ``` { "orderStatus": { "source": "string", "orderId": "string", "clientOrderId": "string", "extId": "string", "exchangeId": 0, "status": "PENDING_NEW", "createdAt": 0, "filledQuantity": 0, "leavesQuantity": 0, "side": "BUY", "averagePrice": "string", "message": "string", "errorCode": "string" }, "order": {}, "orderProgress": 0.0 } ``` **Ack** code 0 ``` { "code": 0, "message": "string" } ``` # WebSocket API v2.0.0 Real-time streams for orders, child orders, trades, positions, position risk, balances and market data. **Read-only** — orders are placed and cancelled through the REST API. [Download AsyncAPI spec](https://api-docs.anboto.xyz/spec/asynapi.yml) · [OpenAPI (REST) spec](https://api-docs.anboto.xyz/spec/anboto-trading-api-2.0.yml) ## Endpoints | Environment | URL | | ----------- | ---------------------------------------- | | Production | `wss://api.pro.anboto.xyz/api/v2/ws` | | Testnet | `wss://api.testnet.anboto.xyz/api/v2/ws` | ## Authentication 1. Call `GET /api/v2/trading/listenKey` ([guide](https://api-docs.anboto.xyz/resources/websocket/#authentication-listenkey)) — signed like any REST request. The response body is a listenKey (JWT, valid **1 hour**). 1. Connect to `wss:///api/v2/ws?listenKey=`, or send `Authorization: Bearer ` as a handshake header (keeps the token out of proxy logs). Invalid or expired listenKey → handshake rejected with HTTP 401. Checked at handshake only; open connections are not dropped on expiry, but every reconnect needs a fresh key. A read-only API key is sufficient. Details: [WebSocket guide](https://api-docs.anboto.xyz/resources/websocket/index.md). ## Keep-alive Server sends `{"topic":"ping"}` every 60 s — reply `{"topic":"pong"}`. No client message for 5 min → close 1001. Subscriptions are per connection: re-subscribe after every reconnect. See [Keep-alive](https://api-docs.anboto.xyz/reference/ws-keep-alive/index.md). ## Subscribing All messages are JSON text frames. One subscription per `(topic, exchange)` pair per connection. ``` {"topic": "order", "exchange": "binance", "method": "subscribe"} ``` | Field | | Description | | ---------- | -------- | -------------------------------------- | | `topic` | required | one of the topics below | | `exchange` | required | any trading exchange, case-insensitive | | `method` | required | `subscribe` / `unsubscribe` | Every request gets `{code, message}` back — `0` = ack; non-zero codes in [Errors](https://api-docs.anboto.xyz/resources/errors/#websocket). ## Topics | | Topic | Description | | --- | -------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | WS | [position](https://api-docs.anboto.xyz/reference/ws-position/index.md) | Channel for subscribing to account position updates for a specific exchange | | WS | [balance](https://api-docs.anboto.xyz/reference/ws-balance/index.md) | Channel for subscribing to asset balance updates for a specific exchange | | WS | [order](https://api-docs.anboto.xyz/reference/ws-order/index.md) | Channel for subscribing to order updates for a specific exchange | | WS | [trade](https://api-docs.anboto.xyz/reference/ws-trade/index.md) | Channel for subscribing to trade (fill) updates for a specific exchange | | WS | [child_order](https://api-docs.anboto.xyz/reference/ws-child-order/index.md) | Channel for subscribing to child-order (slice) updates; subscribe with | | WS | [position_risk](https://api-docs.anboto.xyz/reference/ws-position-risk/index.md) | Channel for subscribing to position risk telemetry; subscribe with | | WS | [ticker](https://api-docs.anboto.xyz/reference/ws-ticker/index.md) | Best bid/offer stream per symbol; subscribe with {"topic":"ticker","exchange":...,"symbol":"BTC/USDT","method":"subscribe"}. Market data subscriptions are capped per connection and may be disabled per environment. | | WS | [ohlcv](https://api-docs.anboto.xyz/reference/ws-ohlcv/index.md) | Candlestick stream per symbol; subscribe with | | WS | [open_interest](https://api-docs.anboto.xyz/reference/ws-open-interest/index.md) | Open interest stream per symbol; subscribe with {"topic":"open_interest","exchange":...,"symbol":"BTC/USDT:USDT","method":"subscribe"}. Derivatives only — use the perpetual symbol form. Market data subscriptions are capped per connection and may be disabled per environment. | | WS | [Keep-alive (ping/pong)](https://api-docs.anboto.xyz/reference/ws-keep-alive/index.md) | Keep-alive channel for maintaining WebSocket connection | Limits: [Rate limits](https://api-docs.anboto.xyz/resources/rate-limits/#websocket). # Keep-alive (ping/pong) WS `wss://api.pro.anboto.xyz/api/v2/ws` Keep-alive channel for maintaining WebSocket connection Authenticate the connection with a listenKey — see [WebSocket](https://api-docs.anboto.xyz/resources/websocket/index.md). ### Responses | | | | ---- | --------------------------------------------------- | | pong | Reply to every server ping; idle 5 min → close 1001 | ``` { "topic": "ping" } ``` ``` { "topic": "pong" } ``` # ohlcv WS `wss://api.pro.anboto.xyz/api/v2/ws` Candlestick stream per symbol; subscribe with {"topic":"ohlcv","exchange":...,"symbol":"BTC/USDT","method":"subscribe"} Authenticate the connection with a listenKey — see [WebSocket](https://api-docs.anboto.xyz/resources/websocket/index.md). ### Subscribe message `topic` string required `ohlcv` `exchange` string required Trading exchange, case-insensitive Example: `BINANCE` `method` enum required `subscribe` / `unsubscribe` ### Update message fields `symbol` string `exchange` string `assetClass` string `open` number `high` number `low` number `close` number `volume` number `last` number `openTime` integer `closeTime` integer `interval` enum `ONE_MINUTE`, `FIVE_MINUTE`, `FIFTEEN_MINUTE`, `THIRTY_MINUTE`, `ONE_HOUR`, `SIX_HOUR`, `ONE_DAY` ### Responses | | | | -------- | ------------------------------------------------------------------------------------------------------------ | | code 0 | Acknowledgment of successful subscription | | code ≠ 0 | Error response for failed subscription — see [Errors](https://api-docs.anboto.xyz/resources/errors/index.md) | ``` { "topic": "ohlcv", "exchange": "BINANCE", "symbol": "BTC/USDT:USDT", "method": "subscribe" } ``` ``` { "topic": "ohlcv", "exchange": "BINANCE", "symbol": "BTC/USDT:USDT", "method": "unsubscribe" } ``` **Update** ohlcv ``` { "symbol": "string", "exchange": "string", "assetClass": "string", "open": 0.0, "high": 0.0, "low": 0.0, "close": 0.0, "volume": 0.0, "last": 0.0, "openTime": 0, "closeTime": 0, "interval": "ONE_MINUTE" } ``` **Ack** code 0 ``` { "code": 0, "message": "string" } ``` # open_interest WS `wss://api.pro.anboto.xyz/api/v2/ws` Open interest stream per symbol; subscribe with {"topic":"open_interest","exchange":...,"symbol":"BTC/USDT:USDT","method":"subscribe"}. Derivatives only — use the perpetual symbol form. Market data subscriptions are capped per connection and may be disabled per environment. Authenticate the connection with a listenKey — see [WebSocket](https://api-docs.anboto.xyz/resources/websocket/index.md). ### Subscribe message `topic` string required `open_interest` `exchange` string required Trading exchange, case-insensitive Example: `BINANCE` `method` enum required `subscribe` / `unsubscribe` ### Update message fields `symbol` string `exchange` string `assetClass` string `openInterest` number contracts/base units as reported by the exchange `openInterestValue` number quote currency value when available `timestamp` integer ### Responses | | | | -------- | ------------------------------------------------------------------------------------------------------------ | | code 0 | Acknowledgment of successful subscription | | code ≠ 0 | Error response for failed subscription — see [Errors](https://api-docs.anboto.xyz/resources/errors/index.md) | ``` { "topic": "open_interest", "exchange": "OKX", "symbol": "BTC/USDT:USDT", "method": "subscribe" } ``` ``` { "topic": "open_interest", "exchange": "OKX", "symbol": "BTC/USDT:USDT", "method": "unsubscribe" } ``` **Update** open_interest ``` { "symbol": "string", "exchange": "string", "assetClass": "string", "openInterest": 0.0, "openInterestValue": 0.0, "timestamp": 0 } ``` **Ack** code 0 ``` { "code": 0, "message": "string" } ``` # order WS `wss://api.pro.anboto.xyz/api/v2/ws` Channel for subscribing to order updates for a specific exchange Authenticate the connection with a listenKey — see [WebSocket](https://api-docs.anboto.xyz/resources/websocket/index.md). ### Subscribe message `topic` string required `order` `exchange` string required Trading exchange, case-insensitive Example: `BINANCE` `method` enum required `subscribe` / `unsubscribe` ### Update message fields `orderStatus` OrderStatusObj Order Status `orderStatus.source` string Component sending the status `orderStatus.orderId` int64 Anboto's order Id `orderStatus.clientOrderId` string Client referenced order Id `orderStatus.extId` string Order Id from exchange `orderStatus.exchangeId` integer Exchange Id `orderStatus.status` enum Order Status — `PENDING_NEW`, `ACCEPTED`, `REJECTED`, `PARTIALLY_FILLED`, `FILLED`, `PENDING_CANCEL`, `CANCELLED`, `PENDING_PAUSE`, … (12 values) `orderStatus.createdAt` integer Unix timestamp of this status change in milliseconds `orderStatus.filledQuantity` integer filled quantity of the order `orderStatus.leavesQuantity` integer leave quantity of the order `orderStatus.side` enum order side — `BUY`, `SELL` `orderStatus.averagePrice` decimal average price of the fills `orderStatus.message` string Status message `orderStatus.errorCode` string Error code `order` object The order context: orderId, clientOrderId, exchangeId, exchangeName, subaccount, symbol, assetClass, side, quantity, limitPrice, strategy, orderType, tif, createdAt, startTime, endTime, clipSizeType, clipSizeVal, targetValue, feeUrgency, params, source, linkId. Multi-leg orders carry algo and legs[] instead of the single-symbol fields. `orderProgress` number Execution progress of the parent order, 0..1 `mishedge` number Multi-leg only — current mishedge between the legs ### Responses | | | | -------- | ------------------------------------------------------------------------------------------------------------ | | code 0 | Acknowledgment of successful subscription | | code ≠ 0 | Error response for failed subscription — see [Errors](https://api-docs.anboto.xyz/resources/errors/index.md) | ``` { "topic": "order", "exchange": "BINANCE", "method": "subscribe" } ``` ``` { "topic": "order", "exchange": "BINANCE", "method": "unsubscribe" } ``` **Update** order ``` { "orderStatus": { "clientOrderId": "554500941080543232", "createdAt": 1773198526482, "filledQuantity": 0, "leavesQuantity": 0, "orderId": "554500941080543233", "side": "BUY", "source": "ods-764fc58e30", "status": "PENDING_NEW" }, "order": { "orderId": "554500941080543233", "clientOrderId": "554500941080543232", "exchangeId": 1, "exchangeName": "BINANCE", "symbol": "BTC/USDT", "assetClass": "SPOT", "side": "BUY", "quantity": 1.0, "strategy": "TWAP", "orderType": "LIMIT", "createdAt": 1773198526000, "startTime": 1773198526000, "endTime": 1773202126000 }, "orderProgress": 0 } ``` **Ack** code 0 ``` { "code": 0, "message": "string" } ``` # position_risk WS `wss://api.pro.anboto.xyz/api/v2/ws` Channel for subscribing to position risk telemetry; subscribe with {"topic":"position_risk","exchange":...,"method":"subscribe"} Authenticate the connection with a listenKey — see [WebSocket](https://api-docs.anboto.xyz/resources/websocket/index.md). ### Subscribe message `topic` string required `position_risk` `exchange` string required Trading exchange, case-insensitive Example: `BINANCE` `method` enum required `subscribe` / `unsubscribe` ### Update message fields `exchangeId` integer `subaccount` string `error` string `positionRisk` object `positionRisk.symbol` string `positionRisk.contracts` number `positionRisk.contractSize` number `positionRisk.unrealizedPnl` number `positionRisk.leverage` number `positionRisk.liquidationPrice` number `positionRisk.collateral` number `positionRisk.notional` number `positionRisk.markPrice` number `positionRisk.entryPrice` number `positionRisk.timestamp` integer `positionRisk.initialMargin` number `positionRisk.initialMarginPercentage` number `positionRisk.maintenanceMargin` number `positionRisk.maintenanceMarginPercentage` number `positionRisk.marginRatio` number `positionRisk.marginMode` string `positionRisk.side` string `positionRisk.hedged` boolean `positionRisk.percentage` number `positionRisk.stopLossPrice` number `positionRisk.takeProfitPrice` number ### Responses | | | | -------- | ------------------------------------------------------------------------------------------------------------ | | code 0 | Acknowledgment of successful subscription | | code ≠ 0 | Error response for failed subscription — see [Errors](https://api-docs.anboto.xyz/resources/errors/index.md) | ``` { "topic": "position_risk", "exchange": "BINANCE", "method": "subscribe" } ``` ``` { "topic": "position_risk", "exchange": "BINANCE", "method": "unsubscribe" } ``` **Update** position_risk ``` { "exchangeId": 0, "subaccount": "string", "error": "string", "positionRisk": { "symbol": "string", "contracts": 0.0, "contractSize": 0.0, "unrealizedPnl": 0.0, "leverage": 0.0, "liquidationPrice": 0.0, "collateral": 0.0, "notional": 0.0, "markPrice": 0.0, "entryPrice": 0.0, "timestamp": 0, "initialMargin": 0.0, "initialMarginPercentage": 0.0, "maintenanceMargin": 0.0, "maintenanceMarginPercentage": 0.0, "marginRatio": 0.0, "marginMode": "string", "side": "string", "hedged": true, "percentage": 0.0, "stopLossPrice": 0.0, "takeProfitPrice": 0.0 } } ``` **Ack** code 0 ``` { "code": 0, "message": "string" } ``` # position WS `wss://api.pro.anboto.xyz/api/v2/ws` Channel for subscribing to account position updates for a specific exchange Authenticate the connection with a listenKey — see [WebSocket](https://api-docs.anboto.xyz/resources/websocket/index.md). ### Subscribe message `topic` string required `position` `exchange` string required Trading exchange, case-insensitive Example: `BINANCE` `method` enum required `subscribe` / `unsubscribe` ### Update message fields `collateral` decimal Collateral amount for the position `contracts` decimal Number of contracts `entryPrice` decimal Average entry price `leverage` decimal Position leverage `liquidationPrice` decimal Liquidation price `marginMode` enum Margin mode for the position — `CROSS`, `ISOLATED` `markPrice` decimal Current mark price `notional` decimal Notional value of the position `side` enum Position side — `LONG`, `SHORT`, `BOTH` `symbol` string required Trading symbol `timestamp` integer required Unix timestamp in milliseconds `unrealizedPnl` decimal Unrealized profit and loss `instrument` Instrument Trading instrument details `instrument.assetClass` enum Asset class of the instrument — `UNDEFINED`, `SPOT`, `FUTURE`, `OPTION`, `CFD` `instrument.assetId` string Unique asset identifier `instrument.baseAsset` string Base asset symbol `instrument.contractSize` number Contract size `instrument.enabled` boolean required Whether the instrument is enabled for trading `instrument.exchangeAssetClass` string Exchange-specific asset class `instrument.exchangeSymbol` string Symbol as used on the exchange `instrument.maxCostLimit` number Maximum cost limit `instrument.maxMarketLimit` number Maximum market order limit `instrument.maxPriceLimit` number Maximum price limit `instrument.maxQuantityLimit` number Maximum quantity limit `instrument.minCostLimit` number Minimum cost limit `instrument.minMarketLimit` number Minimum market order limit `instrument.minPriceLimit` number Minimum price limit `instrument.minQuantityLimit` number Minimum quantity limit `instrument.pricePrecision` integer Price decimal precision `instrument.priceSignificantFigure` integer Price significant figures `instrument.quantityPrecision` integer Quantity decimal precision `instrument.quantitySignificantFigure` integer Quantity significant figures `instrument.quoteAsset` string Quote asset symbol `instrument.symbol` string Instrument symbol `instrument.timestamp` date-time Last update timestamp ### Responses | | | | -------- | ------------------------------------------------------------------------------------------------------------ | | code 0 | Acknowledgment of successful subscription | | code ≠ 0 | Error response for failed subscription — see [Errors](https://api-docs.anboto.xyz/resources/errors/index.md) | ``` { "topic": "position", "exchange": "BINANCE", "method": "subscribe" } ``` ``` { "topic": "position", "exchange": "BINANCE", "method": "unsubscribe" } ``` **Update** position ``` { "collateral": "50000.00", "contracts": "2.5", "entryPrice": "45000.00", "leverage": "10.0", "liquidationPrice": "40500.00", "marginMode": "CROSS", "markPrice": "46000.00", "notional": "115000.00", "side": "LONG", "symbol": "BTC-USDT", "timestamp": 1708840800000, "unrealizedPnl": "2500.00", "instrument": { "assetClass": "FUTURE", "symbol": "BTC-USDT", "baseAsset": "BTC", "quoteAsset": "USDT" } } ``` **Ack** code 0 ``` { "code": 0, "message": "string" } ``` # ticker WS `wss://api.pro.anboto.xyz/api/v2/ws` Best bid/offer stream per symbol; subscribe with {"topic":"ticker","exchange":...,"symbol":"BTC/USDT","method":"subscribe"}. Market data subscriptions are capped per connection and may be disabled per environment. Authenticate the connection with a listenKey — see [WebSocket](https://api-docs.anboto.xyz/resources/websocket/index.md). ### Subscribe message `topic` string required `ticker` `exchange` string required Trading exchange, case-insensitive Example: `BINANCE` `method` enum required `subscribe` / `unsubscribe` ### Update message fields `symbol` string `exchange` string `assetClass` string `bid` number `ask` number `bidQty` number `askQty` number `timestamp` integer ### Responses | | | | -------- | ------------------------------------------------------------------------------------------------------------ | | code 0 | Acknowledgment of successful subscription | | code ≠ 0 | Error response for failed subscription — see [Errors](https://api-docs.anboto.xyz/resources/errors/index.md) | ``` { "topic": "ticker", "exchange": "BINANCE", "symbol": "BTC/USDT:USDT", "method": "subscribe" } ``` ``` { "topic": "ticker", "exchange": "BINANCE", "symbol": "BTC/USDT:USDT", "method": "unsubscribe" } ``` **Update** ticker ``` { "symbol": "string", "exchange": "string", "assetClass": "string", "bid": 0.0, "ask": 0.0, "bidQty": 0.0, "askQty": 0.0, "timestamp": 0 } ``` **Ack** code 0 ``` { "code": 0, "message": "string" } ``` # trade WS `wss://api.pro.anboto.xyz/api/v2/ws` Channel for subscribing to trade (fill) updates for a specific exchange Authenticate the connection with a listenKey — see [WebSocket](https://api-docs.anboto.xyz/resources/websocket/index.md). ### Subscribe message `topic` string required `trade` `exchange` string required Trading exchange, case-insensitive Example: `BINANCE` `method` enum required `subscribe` / `unsubscribe` ### Update message fields `trade_id` string Anboto's trade Id `order_id` integer The Anboto id of the child (slice) order that executed on the exchange `parent_order_id` integer The Anboto id of the parent order the filled child order belongs to; the order_id reported by the REST order endpoints and the order topic `exchange_id` integer The platform exchange id of the filled child order (see GET /api/v2/data/exchanges). A trade subscription delivers fills of its subscribed exchange; fills with an unresolved exchange (child order not yet cached) are passed through `symbol` string the symbol of the trade `side` enum trade side — `BUY`, `SELL` `taker_or_maker` enum maker or taker of the trade — `MAKER`, `TAKER` `price` decimal the price of the trade `amount` decimal the quantity of the trade `cost` decimal the notional of the trade `fee_currency` string fee currency `fee_cost` decimal the fee of the trade `timestamp` integer Unix timestamp of this status change in milliseconds `ext_trade_id` string trade Id from exchange `ext_order_id` string order Id of the trade from exchnage ### Responses | | | | -------- | ------------------------------------------------------------------------------------------------------------ | | code 0 | Acknowledgment of successful subscription | | code ≠ 0 | Error response for failed subscription — see [Errors](https://api-docs.anboto.xyz/resources/errors/index.md) | ``` { "topic": "trade", "exchange": "BINANCE", "method": "subscribe" } ``` ``` { "topic": "order", "exchange": "BINANCE", "method": "unsubscribe" } ``` **Update** trade ``` { "trade_id": "151990408", "order_id": 558547168212975616, "symbol": "KITE/USDT:USDT", "side": "SELL", "taker_or_maker": "MAKER", "price": 0.21735, "amount": 153, "cost": 33.25455, "fee_currency": "BNB", "fee_cost": 7.55e-06, "timestamp": 1719224096000, "ext_trade_id": "1204004183", "ext_order_id": "151990408", "client_order_id": "554500941080543232", "parent_order_id": 558547165436166144, "exchange_id": 1 } ``` **Ack** code 0 ``` { "code": 0, "message": "string" } ```