# Cancel trade Source: https://docs.tradeit.app/api/cancel-trade `POST /api/tool/execute` Cancels a draft immediately or requests cancellation of an eligible submitted order from the brokerage. **OAuth scopes:** `trade:write`, `tool:execute` **Returns:** [Trade](/models/trade) ## Request body [#request-body] | Field | Type | Required | Description | | --- | --- | --- | --- | | `toolName` | `"cancel_trade"` | Yes | Selects the cancellation operation. | | `params.trade_id` | integer or string | Yes | ID of the draft or submitted trade to cancel. | ## Example request [#example-request] ```bash curl https://api.tradeit.app/api/tool/execute \ --request POST \ --header "Authorization: Bearer $TRADE_IT_ACCESS_TOKEN" \ --header "Content-Type: application/json" \ --data '{ "toolName": "cancel_trade", "params": { "trade_id": 842 } }' ``` ## Example response [#example-response] ### `200 OK` [#_200-ok] ```json { "id": 842, "created_at": "2026-03-17T14:14:31.112Z", "updated_at": "2026-03-17T14:24:08.502Z", "user_id": 1, "asset_id": 88, "account_id": 304, "source": null, "image_url": null, "external_id": "114", "type": 0, "action": "buy", "direction": null, "total_units": 4, "filled_units": 0, "canceled_units": 0, "notional_amount": { "amount": 1000, "currency": "USD" }, "execution_price": null, "status": "canceled", "order_type": "limit", "limit_price": { "amount": 250, "currency": "USD" }, "stop_price": null, "time_in_force": "day", "placed_at": "2026-03-17T14:21:54.937Z", "executed_at": null, "error_message": null, "fee": null, "legs": null, "event": null, "analysis": null } ``` Treat the returned trade as the latest known state and use `get_trades` with `refresh: true` when the final state matters. A non-cancelable trade returns `400` with an explanation of its current status. > **Note** > > Cancellation is not guaranteed if an order fills while the brokerage is processing the request. # Create options trade Source: https://docs.tradeit.app/api/create-options-trade `POST /api/tool/execute` Creates a single-leg or multi-leg options order for review. This is a separate operation from `create_trade`. **OAuth scopes:** `trade:write`, `tool:execute` **Plan:** Trade It Pro **Returns:** [Trade](/models/trade) ## Request body [#request-body] | Field | Type | Required | Description | | --- | --- | --- | --- | | `toolName` | `"create_options_trade"` | Yes | Selects the options draft operation. | | `params.symbol` | string | Yes | Underlying ticker symbol, such as `SPY`. | | `params.legs` | array | Yes | One or more option or equity legs. | | `params.direction` | `"debit"`, `"credit"`, or `"even"` | Conditional | Net direction for a multi-leg spread. | | `params.order_type` | `"market"`, `"limit"`, `"stop"`, or `"stop_limit"` | No | Defaults to `market`. | | `params.limit_price` | number | Conditional | Required for `limit` and `stop_limit`. May be `0` with direction `even`. | | `params.stop_price` | number | Conditional | Required for `stop` and `stop_limit`. | | `params.time_in_force` | `"day"`, `"gtc"`, `"ioc"`, or `"fok"` | No | How long the order remains active. Brokerage support varies. | | `params.account_id` | integer or string | No | Account from `get_accounts`. Uses the user's compatible default account when omitted. | ### Leg fields [#leg-fields] | Field | Type | Required | Description | | --- | --- | --- | --- | | `type` | `"option"` or `"equity"` | Yes | Instrument represented by the leg. | | `action` | `"buy"` or `"sell"` | Yes | Leg side. | | `position_effect` | `"open"`, `"close"`, or `null` | Conditional | Required for option legs; use `null` for equity legs. | | `occ` | string or `null` | Yes | OCC contract identifier for an option leg; `null` for an equity leg. | | `quantity` | number | Yes | Positive number of contracts or shares. | > **OCC symbols** > > OCC identifiers use `YYMMDD[C|P]STRIKE`, with the strike multiplied by 1,000 and zero-padded to eight digits. For example, `260620P00580000` is a $580 put expiring June 20, 2026. ## Example request [#example-request] ```bash curl https://api.tradeit.app/api/tool/execute \ --request POST \ --header "Authorization: Bearer $TRADE_IT_ACCESS_TOKEN" \ --header "Content-Type: application/json" \ --data '{ "toolName": "create_options_trade", "params": { "symbol": "SPY", "legs": [ { "type": "option", "action": "buy", "position_effect": "open", "occ": "260620P00580000", "quantity": 1 }, { "type": "option", "action": "sell", "position_effect": "open", "occ": "260620P00570000", "quantity": 1 } ], "direction": "debit", "order_type": "limit", "limit_price": 2.35, "time_in_force": "day", "account_id": 304 } }' ``` ## Example response [#example-response] ### `200 OK` [#_200-ok] ```json { "id": 843, "created_at": "2026-03-17T14:19:07.444Z", "updated_at": "2026-03-17T14:19:07.444Z", "user_id": 1, "asset_id": 23, "account_id": 304, "source": null, "image_url": null, "external_id": "draft-843", "type": 1, "action": "buy", "direction": "debit", "total_units": 1, "filled_units": 0, "canceled_units": 0, "notional_amount": null, "execution_price": null, "status": "draft", "order_type": "limit", "limit_price": { "amount": 2.35, "currency": "USD" }, "stop_price": null, "time_in_force": "day", "placed_at": null, "executed_at": null, "error_message": null, "fee": null, "legs": [ { "occ": "260620P00580000", "type": "option", "action": "buy", "quantity": 1, "execution_price": null, "position_effect": "open" }, { "occ": "260620P00570000", "type": "option", "action": "sell", "quantity": 1, "execution_price": null, "position_effect": "open" } ], "event": null, "analysis": null } ``` Show every returned leg and the net direction and price to the user before calling `execute_trade`. ## Reading prices on a multi-leg trade [#reading-prices-on-a-multi-leg-trade] > **Note** > > Every price on a trade is unsigned, including `execution_price`. A credit spread and a debit spread of the same size store the same number. `direction` tells them apart, and `total_cost` is the signed figure to display. | Field | Unit | Notes | | --- | --- | --- | | `legs[].execution_price` | Per share | Multiply by 100 for the per-contract cost. | | `legs[].quantity` | Contracts | The absolute count on that leg. | | `limit_price` | Per contract/spread unit | A `1.00` limit on a spread is a $100 package. | | `execution_price` | Net cash for the whole package | Unsigned. | | `total_units` | 1 | A multi-leg order counts as a single package. | | `filled_units` | Fraction of the package | Same as total_units when fully filled. | | `direction` | `debit`, `credit`, `even` | Which way the cash moved. | # Create trade Source: https://docs.tradeit.app/api/create-trade `POST /api/tool/execute` Creates a stock or crypto trade for review. This operation is distinct from `create_options_trade` and does not accept an options `legs` array. **OAuth scopes:** `trade:write`, `tool:execute` **Plan:** Trade It Pro **Returns:** [Trade](/models/trade) ## Request body [#request-body] | Field | Type | Required | Description | | --- | --- | --- | --- | | `toolName` | `"create_trade"` | Yes | Selects the equity or crypto draft operation. | | `params.symbol` | string | Yes | Ticker symbol, such as `TSLA` or `BTC`. | | `params.amount` | number | Yes | Positive amount interpreted using `unit`. | | `params.unit` | `"dollars"` or `"shares"` | Yes | Whether `amount` is notional value or units. | | `params.buy_or_sell` | `"buy"` or `"sell"` | Yes | Order side. | | `params.order_type` | `"market"`, `"limit"`, `"stop"`, or `"stop_limit"` | No | Defaults to `market`. | | `params.limit_price` | number | Conditional | Required for `limit` and `stop_limit`. | | `params.stop_price` | number | Conditional | Required for `stop` and `stop_limit`. | | `params.take_profit` | object | No | Attached exit as `{ "value": number, "unit": "$" or "%" }`. Buy entries only; support varies by brokerage. | | `params.stop_loss` | object | No | Attached exit as `{ "value": number, "unit": "$" or "%" }`. Buy entries only; support varies by brokerage. | | `params.time_in_force` | `"day"`, `"gtc"`, `"ioc"`, or `"fok"` | No | How long the order remains active. Brokerage support varies. | | `params.account_id` | integer or string | No | Account from `get_accounts`. Uses the user's compatible default account when omitted. | | `params.metadata.image_url` | string | No | Source image URL to associate with the trade. | ## Example request [#example-request] ```bash curl https://api.tradeit.app/api/tool/execute \ --request POST \ --header "Authorization: Bearer $TRADE_IT_ACCESS_TOKEN" \ --header "Content-Type: application/json" \ --data '{ "toolName": "create_trade", "params": { "symbol": "TSLA", "amount": 1000, "unit": "dollars", "buy_or_sell": "buy", "order_type": "limit", "limit_price": 250, "time_in_force": "day", "account_id": 304 } }' ``` ## Example response [#example-response] ### `200 OK` [#_200-ok] ```json { "id": 842, "created_at": "2026-03-17T14:14:31.112Z", "updated_at": "2026-03-17T14:14:31.112Z", "user_id": 1, "asset_id": 88, "account_id": 304, "source": null, "image_url": null, "external_id": "draft-842", "type": 0, "action": "buy", "direction": null, "total_units": 4, "filled_units": 0, "canceled_units": 0, "notional_amount": { "amount": 1000, "currency": "USD" }, "execution_price": { "amount": 250, "currency": "USD" }, "status": "draft", "order_type": "limit", "limit_price": { "amount": 250, "currency": "USD" }, "stop_price": null, "take_profit": null, "stop_loss": null, "time_in_force": "day", "placed_at": null, "executed_at": null, "error_message": null, "fee": null, "legs": null, "event": null, "analysis": null } ``` Show the returned order to the user and obtain explicit approval before passing `id` to `execute_trade`. > **Note** > > If automatic execution is enabled for the account, the returned status may already be `placed` instead of `draft`. # Execute trade Source: https://docs.tradeit.app/api/execute-trade `POST /api/tool/execute` Submits a previously created trade draft to the selected brokerage. **OAuth scopes:** `trade:write`, `tool:execute` **Plan:** Trade It Pro **Returns:** [Trade](/models/trade) > **User approval required** > > Only execute a trade after the user has reviewed and explicitly approved that specific draft. Do not chain this operation automatically after `create_trade` or `create_options_trade`. ## Request body [#request-body] | Field | Type | Required | Description | | --- | --- | --- | --- | | `toolName` | `"execute_trade"` | Yes | Selects the execution operation. | | `params.trade_id` | integer or string | Yes | `id` returned by `create_trade` or `create_options_trade`. | ## Example request [#example-request] ```bash curl https://api.tradeit.app/api/tool/execute \ --request POST \ --header "Authorization: Bearer $TRADE_IT_ACCESS_TOKEN" \ --header "Content-Type: application/json" \ --data '{ "toolName": "execute_trade", "params": { "trade_id": 842 } }' ``` ## Example response [#example-response] ### `200 OK` [#_200-ok] ```json { "id": 842, "created_at": "2026-03-17T14:14:31.112Z", "updated_at": "2026-03-17T14:21:54.937Z", "user_id": 1, "asset_id": 88, "account_id": 304, "source": null, "image_url": null, "external_id": "114", "type": 0, "action": "buy", "direction": null, "total_units": 4, "filled_units": 0, "canceled_units": 0, "notional_amount": { "amount": 1000, "currency": "USD" }, "execution_price": null, "status": "placed", "order_type": "limit", "limit_price": { "amount": 250, "currency": "USD" }, "stop_price": null, "time_in_force": "day", "placed_at": "2026-03-17T14:21:54.937Z", "executed_at": null, "error_message": null, "fee": null, "legs": null, "event": null, "analysis": null } ``` > **Note** > > A successful request means the order was accepted for processing; it does not necessarily mean it has filled. Inspect `status`, `filled_units`, `executed_at`, and `error_message`, then use `get_trades` with `refresh: true` when current brokerage state is required. # Get accounts Source: https://docs.tradeit.app/api/get-accounts `POST /api/tool/execute` Returns the authenticated user's connected brokerage accounts, balances, brokerage capabilities, and connection status. **OAuth scopes:** `brokerage:read`, `tool:execute` **Plan:** Trade It Pro **Returns:** [Account[]](/models/account), each wrapped with its `brokerage_metadata` and `connection` ## Request body [#request-body] | Field | Type | Required | Description | | --- | --- | --- | --- | | `toolName` | `"get_accounts"` | Yes | Selects the account-list operation. | | `params` | object | Yes | This operation takes an empty object. | | `params.refresh` | boolean | No | Requests the freshest eligible brokerage data. Defaults to `false`. Real-time refresh requires a Pro plan and has a one-minute per-account cooldown. | ## Example request [#example-request] ```bash curl https://api.tradeit.app/api/tool/execute \ --request POST \ --header "Authorization: Bearer $TRADE_IT_ACCESS_TOKEN" \ --header "Content-Type: application/json" \ --data '{ "toolName": "get_accounts", "params": {} }' ``` ## Example response [#example-response] ### `200 OK` [#_200-ok] ```json [ { "account": { "id": 304, "connection_id": 395, "external_id": "rh-304", "name": "Robinhood x1234", "balance": { "amount": 15420.5, "currency": "USD" }, "cash": { "amount": 3420.5, "currency": "USD" }, "buying_power": { "amount": 3420.5, "currency": "USD" }, "created_at": "2026-01-03T15:20:10.000Z", "updated_at": "2026-03-17T13:55:02.000Z", "synced_at": "2026-03-17T13:55:02.000Z" }, "brokerage_metadata": { "id": 1, "name": "Robinhood", "fractional_support": true, "minimum_order": 1, "options_support": true, "take_profit_support": false, "stop_loss_support": false }, "connection": { "id": 395, "status": 1 } } ] ``` Brokerage capability fields let your application validate features before showing them to a user. > **Note** > > Use `account.id`, not `connection.id` or `account.external_id`, as the `account_id` in holdings and trade requests. # Get holdings Source: https://docs.tradeit.app/api/get-holdings `POST /api/tool/execute` Returns normalized holdings for one of the authenticated user's connected brokerage accounts. **OAuth scopes:** `brokerage:read`, `tool:execute` **Plan:** Trade It Pro **Returns:** [Holding[]](/models/holding) ## Request body [#request-body] | Field | Type | Required | Description | | --- | --- | --- | --- | | `toolName` | `"get_holdings"` | Yes | Selects the holdings operation. | | `params.account_id` | integer or string | Yes | Trade It account ID returned by `get_accounts`. | | `params.refresh` | boolean | No | Requests the freshest eligible brokerage data. Defaults to `false`. Real-time refresh requires a Pro plan and has a one-minute per-account cooldown. | ## Example request [#example-request] ```bash curl https://api.tradeit.app/api/tool/execute \ --request POST \ --header "Authorization: Bearer $TRADE_IT_ACCESS_TOKEN" \ --header "Content-Type: application/json" \ --data '{ "toolName": "get_holdings", "params": { "account_id": 304, "refresh": true } }' ``` ## Example response [#example-response] ### `200 OK` [#_200-ok] ```json [ { "key": "equity:NET", "symbol": "NET", "display_symbol": "NET", "quantity": 0.024277, "average_price": { "amount": 2, "currency": "USD" }, "average_unit_cost": { "amount": 82.38, "currency": "USD" }, "description": "Cloudflare, Inc.", "type": 2, "instrument_kind": "equity", "market_price": { "amount": 191.42, "currency": "USD" }, "market_value": { "amount": 4.65, "currency": "USD" }, "unrealized_pnl": { "amount": 2.65, "currency": "USD" }, "unrealized_pnl_percent": 132.5, "price_kind": "brokerage", "price_as_of": "2026-03-17T14:20:00.000Z", "delayed": false }, { "key": "option:AMZN 260116C00295000", "symbol": "AMZN 260116C00295000", "display_symbol": "AMZN Jan 16 2026 $295 Call", "quantity": 1, "average_price": { "amount": 1, "currency": "USD" }, "average_unit_cost": { "amount": 1, "currency": "USD" }, "type": 2, "instrument_kind": "option", "option_symbol": "260116C00295000", "underlying_symbol": "AMZN", "multiplier": 100 } ] ``` > **Note** > > The response is an array, not the `{ "results": [...] }` shape used by the older account holdings route. Enrichment fields can be absent or `null` when a brokerage does not supply them. # Get trades Source: https://docs.tradeit.app/api/get-trades `POST /api/tool/execute` Returns the authenticated user's recent trades using cursor pagination. Use it to refresh an order after execution or cancellation. **OAuth scopes:** `trade:read`, `tool:execute` **Plan:** Trade It Pro **Returns:** a page of [Trade[]](/models/trade) in `trades` ## Request body [#request-body] | Field | Type | Required | Description | | --- | --- | --- | --- | | `toolName` | `"get_trades"` | Yes | Selects the trade-list operation. | | `params.limit` | integer | No | Number of trades to return. Defaults to `12`; maximum `100`. | | `params.cursor` | integer or string | No | `next_cursor` from the previous response. | | `params.refresh` | boolean | No | Syncs the freshest eligible trade state from brokerages before reading. Defaults to `false`. | ## Example request [#example-request] ```bash curl https://api.tradeit.app/api/tool/execute \ --request POST \ --header "Authorization: Bearer $TRADE_IT_ACCESS_TOKEN" \ --header "Content-Type: application/json" \ --data '{ "toolName": "get_trades", "params": { "limit": 20, "refresh": true } }' ``` ## Example response [#example-response] ### `200 OK` [#_200-ok] ```json { "trades": [ { "id": 842, "created_at": "2026-03-17T14:14:31.112Z", "updated_at": "2026-03-17T14:21:54.937Z", "user_id": 1, "asset_id": 88, "account_id": 304, "external_id": "114", "type": 0, "action": "buy", "direction": null, "total_units": 4, "filled_units": 0, "canceled_units": 0, "notional_amount": null, "execution_price": null, "status": "placed", "order_type": "limit", "limit_price": { "amount": 250, "currency": "USD" }, "stop_price": null, "time_in_force": "day", "placed_at": "2026-03-17T14:21:54.937Z", "executed_at": null, "error_message": null, "fee": null, "legs": null, "event": null, "analysis": null, "asset": { "id": 88, "name": "Tesla, Inc.", "ticker": "TSLA", "logo_url": "...", "type": 2, "exchange": "NASDAQ", "country": "US" } } ], "next_cursor": 842, "has_more": true } ``` To fetch the next page, pass the returned `next_cursor` as `params.cursor`. > **Note** > > Do not derive a cursor from array position. # Trade It API Source: https://docs.tradeit.app/api Base URL: https://api.tradeit.app Use the Trade It REST API to read connected brokerage accounts and holdings, create equity or options trade drafts, execute approved orders, and cancel eligible orders. These endpoints work without an embedded Trade It modal, so a partner can build the entire review and trading experience in its own application. ## Authentication [#authentication] Send either a Trade It API key or an OAuth access token as a bearer token with every request: ```http Authorization: Bearer Content-Type: application/json ``` Create an API key from the [API keys page](https://tradeit.app/account/api-keys). For a multi-user partner integration, use OAuth so every request is authorized for the correct Trade It user. OAuth discovery is available at: ```text https://tradeit.app/.well-known/oauth-authorization-server ``` > **Note** > > Keep the partner `client_secret`, API keys, access tokens, and refresh tokens on your server. Do not expose them in browser code. ## Tool execution [#tool-execution] The account and trading operations documented here use one canonical endpoint: ```http POST https://api.tradeit.app/api/tool/execute ``` Select the operation with `toolName` and pass its input in `params`: ```json { "toolName": "get_accounts", "params": {} } ``` > **Note** > > The response body is the operation result itself; it is not wrapped in a `result` property. ## API reference [#api-reference] | Operation | `toolName` | Purpose | | --- | --- | --- | | [Get accounts](/api/get-accounts) | `get_accounts` | List the user's connected brokerage accounts. | | [Get holdings](/api/get-holdings) | `get_holdings` | List positions for one brokerage account. | | [Get trades](/api/get-trades) | `get_trades` | Read recent trades and refresh order state. | | [Create trade](/api/create-trade) | `create_trade` | Create a stock or crypto trade draft. | | [Create options trade](/api/create-options-trade) | `create_options_trade` | Create a single-leg or multi-leg options draft. | | [Execute trade](/api/execute-trade) | `execute_trade` | Submit a reviewed draft to the brokerage. | | [Cancel trade](/api/cancel-trade) | `cancel_trade` | Cancel a draft or request brokerage cancellation. | Responses use these data models, each documented field by field: [Account](/models/account) [Holding](/models/holding) [Trade](/models/trade) ## Recommended trading flow [#recommended-trading-flow] 1. Call [Get accounts](/api/get-accounts) and let the user choose an account. 2. Call [Create trade](/api/create-trade) or [Create options trade](/api/create-options-trade). 3. Render the returned order, including its account, action, quantity, order type, prices, and legs. 4. Ask the user to approve that specific order. 5. Only after approval, pass its `id` to [Execute trade](/api/execute-trade). 6. Use [Get trades](/api/get-trades) to refresh the order state or [Cancel trade](/api/cancel-trade) when the user requests cancellation. > **Explicit approval** > > Creating a draft and executing it are separate operations. It's best practice not to call `execute_trade` immediately after a create operation so users can review and explicitly approve trades. Note that an account configured for automatic execution may return an already submitted trade from a create call. Check the `status` to confirm. ## OAuth scopes [#oauth-scopes] Request only the scopes the integration needs: | Scope | Used for | | --- | --- | | `brokerage:read` | Accounts and holdings | | `trade:read` | Trade history and current order state | | `trade:write` | Creating, executing, and canceling trades | | `tool:execute` | Calling the tool execution endpoint | ## Errors [#errors] Errors use a consistent JSON shape: ```json { "error": "invalid_request", "error_description": "The request body is invalid.", "resolution": null, "validation_errors": [] } ``` Common status codes include `400` for invalid input or an invalid trade state, `401` for missing or invalid authentication, and `403` for insufficient access or an unavailable plan feature. ## Partner setup [#partner-setup] If you need OAuth credentials for a multi-user integration: 1. Sign in at [tradeit.app](https://tradeit.app). 2. Choose `Organization` on first login. 3. Complete the partner setup flow in the partner portal. 4. Save the generated `client_id` and one-time `client_secret`. > **TIP** > > The [Trade It Postman collection](https://www.postman.com/trade-it/workspace/trade-it-apis/collection/5398302-70e1f409-c978-4701-a2fa-6f58b8b11932?action=share&source=copy-link&creator=5398302) remains available as a runnable companion to this reference. If you have questions or want to discuss your use case, [contact us](https://tradeit.app/contact). # Supported Brokerages Source: https://docs.tradeit.app/brokerages Trade It SDK and MCP integrations support the following brokerages. SDK partners can pass the code as `brokerageCode` to open a direct connection flow, or omit it to show the brokerage picker. | Name | Code | Type | Fractional | Options | Take-Profit | Stop-Loss | Minimum Order | Order History* | |------|------|------|------------|---------|-------------|-----------|---------------|----------------| | ![](https://images.tradeit.app/brokerages/charles_schwab-logo.svg) [Charles Schwab](https://schwab.com) | `charles_schwab` | Stock | | ✓ | ✓ | ✓ | 1 share | 90 days | | ![](https://images.tradeit.app/brokerages/coinbase-logo.svg) [Coinbase](https://coinbase.com) | `coinbase` | Crypto | ✓ | | | | $1 | 90 days | | ![](https://images.tradeit.app/brokerages/etrade-logo.svg) [ETrade](https://etrade.com) | `etrade` | Stock | | ✓ | | | 1 share | 90 days | | ![](https://images.tradeit.app/brokerages/kraken-logo.svg) [Kraken](https://kraken.com) | `kraken` | Crypto | ✓ | | ✓ | ✓ | $1 | 90 days | | ![](https://images.tradeit.app/brokerages/moomoo-logo.svg) [Moomoo](https://moomoo.com) | `moomoo` | Stock | ✓ | ✓ | | | $5 | 90 days | | ![](https://images.tradeit.app/brokerages/public-logo.svg) [Public](https://public.com) | `public` | Stock, Crypto | ✓ | ✓ | | | $1 | 30 days | | ![](https://images.tradeit.app/brokerages/robinhood-logo.svg) [Robinhood](https://robinhood.com) | `robinhood` | Stock | ✓ | ✓ | | | $1 | 90 days | | ![](https://images.tradeit.app/brokerages/tastytrade-logo.svg) [Tastytrade](https://tastytrade.com) | `tastytrade` | Stock | ✓ | ✓ | ✓ | ✓ | $1 | 90 days | | ![](https://images.tradeit.app/brokerages/tradestation-logo.svg) [TradeStation](https://tradestation.com) | `tradestation` | Stock | | ✓ | ✓ | ✓ | 1 share | 90 days | | ![](https://images.tradeit.app/brokerages/tradestation_paper-logo.svg) [TradeStation Paper](https://tradestation.com) | `tradestation_paper` | Stock | | ✓ | ✓ | ✓ | 1 share | 90 days | | ![](https://images.tradeit.app/brokerages/webull-logo.svg) [Webull](https://webull.com) | `webull` | Stock | ✓ | ✓ | ✓ | ✓ | $5 | 90 days | *Order history: connecting a brokerage imports its order history up to 90 days prior, or as far back as the brokerage allows; whichever is longer. Every order from then on is recorded and stays available in Trade It. # Account Setup Source: https://docs.tradeit.app/discord/account-setup Three things matter: link Discord, connect a brokerage, then trade. ## Link Discord [#link-discord] 1. In Discord, run `/login`. 2. Open the Trade It link. 3. Sign in if prompted. 4. Click **Continue with Discord**. 5. Go back to Discord. ## Connect A Brokerage [#connect-a-brokerage] Run: ```text /connect ``` ![Trade It's brokerage connection screen](https://images.tradeit.app/docs/connect_screen.png) Choose your brokerage, finish the connection flow, then return to Discord and run: ```text /accounts ``` to view your connected brokerage accounts and their balance/buying power. ## Manage Account [#manage-account] Open [**Linked Accounts**](https://tradeit.app/account/linked-accounts) from the Trade It menu to see connected identities and linked providers. ![/login response](https://images.tradeit.app/docs/linked_accounts.png) ## Disconnect [#disconnect] Run `/logout` in Discord to open the Linked Accounts page with the Discord disconnect dialog already open. ## Quick Fixes [#quick-fixes] | Problem | Fix | | --- | --- | | Bot says your account is not linked | Run `/login` again and finish the link flow. | | Discord identity is already linked | Sign into the Trade It account that owns that Discord identity, then disconnect it. | | No brokerage accounts show up | Run `/connect` and finish a brokerage connection. | When in doubt, `/help` is the fastest reset button. # Discord Commands Source: https://docs.tradeit.app/discord/commands The Trade It bot makes available a number of slash commands. To use them, just type `/` in Discord, choose the Trade It app, and select the command you want to run. One command lives in the `...` menu: [**Copy Trade**](#copy-trade), which copies any channel post into a private trade draft. ## Command Reference [#command-reference] ### Setup Commands [#setup-commands] | Command | Visibility | What it does | | --- | --- | --- | | `/connect` | Private | Opens Trade It so you can connect a brokerage account. | | `/help` | Private | Shows a welcome message, command list, trading behavior, and dashboard tips. | | `/login` | Private | Sends you to the focused Discord account-linking page. | | `/logout` | Private | Opens the linked accounts page with a Discord disconnect confirmation. | ### Trading Commands [#trading-commands] | Command | Visibility | What it does | | --- | --- | --- | | `/accounts` | Private | Shows your connected brokerage accounts, account value, and buying power. | | `/alert` | Public | Shares a trade alert that other members can review and execute on their own brokerage accounts. | | `/holdings` | Private | Shows holdings for a selected brokerage account. | | `/trade` | Private | Creates a draft trade order from natural language. | | `/trades` | Private | Shows recent trades, each shareable as a public channel trade alert. | | **Right Click → Copy Trade** | Private | Copies any post — text, bot alert, or screenshot — into a private trade draft. | ## Copy Trade [#copy-trade] Copy any trade shared in Discord without retyping a thing. Right-click a message (long-press on mobile), choose **Apps → Trade It → Copy Trade**, and Trade It copies the trade details into a private draft order. Copy Trade works on the posts trading communities actually share: - Plain-text callouts, such as `BTO 1 AAPL 430c Dec 19 @ 12.10` - Alerts posted by other Discord bots - Screenshots of positions, orders, or broker confirmations - Forwarded messages The bot replies with a private summary that opens the trade in-browser, where you can edit the details and execute on any brokerage you have connected. > **Note** > > Copy Trade is private and review-first. Nothing is posted to the channel, and no order is placed until you confirm it in Trade It. ![copy trade command](https://images.tradeit.app/docs/discord_command_copytrade.png) ![copy trade](https://images.tradeit.app/docs/discord_copytrade.png) The bot fills reasonable gaps the way a trader would read the message: `Closed SPXW $7435 Put @ $20.10` becomes a sell-to-close order, `covered my TSLA short` becomes a buy-to-close, and quantity defaults to 1 contract when the message does not state a size. If a detail genuinely cannot be inferred, the bot replies telling you exactly which detail is missing. > **TIP** > > Following a leader who posts entries and exits as screenshots or bot alerts? Copy Trade is the fastest way to mirror a call on your own account — see [Using Copy Trade](/discord/trading#using-copy-trade). ## `/alert` [#alert] Use `/alert` when you want to share a trade idea with a community. It responds with a public message containing the trade details and a **Review & Trade** button. Other members can use this button to execute the shared trade on their own brokerages. > **TIP** > > Already placed the trade? You can share it without retyping the order — run `/trades` and click its [**Share** button](#sharing-a-trade). ### Parameters [#parameters] | Option | Required | What to enter | | --- | --- | --- | | `details` | Yes | The trade to share, such as ticker, action, size, option legs, order type, take profit/stop loss, and price instructions. | | `note` | No | Extra context for the alert card, such as thesis, risk note, or timing. | ### Examples [#examples] ```text /alert details:Buy $100 of AMZN note:Starter position /alert details:Buy 100 shares of AMZN stop loss 10%, take profit 30% /alert details:Sell 1 SPY 600/605 call spread Jan 16 2026 /alert details:Buy 1 AAPL call expiring Friday limit 2.10 note:Earnings momentum idea ``` > **Note** > > Trade alerts do not place a trade for the person sharing them, and they do not immediately place trades for members who click them. Clicking the alert opens the trade in-browser, where members can review or edit the details, and execute it on any brokerage they have connected to Trade It. ![/alert command](https://images.tradeit.app/docs/discord_command_alert_condor.png) ![/alert response](https://images.tradeit.app/docs/discord_alert_condor.png) ![/alert response opened in browser](https://images.tradeit.app/docs/discord_alert2.png) ## `/trade` [#trade] Drafts a trade order. All the details of the drafted trade are returned to review. You may then execute or cancel the draft. ### Parameters [#parameters-1] | Option | Required | What to enter | | --- | --- | --- | | `order` | Yes | The trade to draft in plain English, such as ticker, action, size, option legs, order type, limit or stop price, take profit/stop loss and target account. | ### Examples [#examples-1] ```text /trade order:Buy $100 of AMZN /trade order:Sell 10 shares of AAPL limit 220 /trade order:Buy 1 AMZN 300 call expiring Friday /trade order:Open a bullish MSFT call spread 5% OTM for next month ``` The bot can draft: - Equity orders - Crypto orders - Single-leg option orders - Multi-leg option strategies - Relative requests when you provide enough detail, such as call or put, expiration, and target strike range > **Note** > > If the bot needs more information, it will ask you to run `/trade` again with the missing detail included. Discord bot requests are stateless, so include the full order in the next command. ![/trade command](https://images.tradeit.app/docs/discord_command_trade.png) ![/trade response](https://images.tradeit.app/docs/discord_trade_order.png) ## `/accounts` [#accounts] Shows your connected brokerage accounts, including: - Account name - Account value - Buying power Use this when you need the account id for `/holdings`, or when you want to confirm which brokerages are connected. ![/accounts command](https://images.tradeit.app/docs/discord_command_accounts.png) ![/accounts response](https://images.tradeit.app/docs/discord_accounts.png) ## `/holdings` [#holdings] Shows holdings for one brokerage account. Run `/accounts` first if you need to find the account id. ### Parameters [#parameters-2] | Option | Required | What to enter | | --- | --- | --- | | `account_id` | Yes | The brokerage account id from `/accounts`. | | `refresh` | No | Set to `true` to request fresh holdings data when eligible. Otherwise cached daily data is returned. | ### Examples [#examples-2] ```text /holdings account_id:12345 /holdings account_id:12345 refresh:true ``` ![/holdings command](https://images.tradeit.app/docs/discord_command_holdings.png) ![/holdings response](https://images.tradeit.app/docs/discord_holdings.png) ## `/trades` [#trades] Shows recent trade activity in Discord. Each trade also includes a **Share** button for posting it to the channel as a public trade alert. ### Parameters [#parameters-3] | Option | Required | What to enter | | --- | --- | --- | | `refresh` | No | Set to `true` to request a fresh brokerage sync when eligible. Otherwise existing synced trades are returned. | ![/trades command](https://images.tradeit.app/docs/discord_command_trades.png) ![/trades response](https://images.tradeit.app/docs/discord_trades_2.png) ### Sharing a Trade [#sharing-a-trade] Use the **Share** button to share one of your recent trades to the channel as a public alert (same as the `/alert` command). 1. Run `/trades`. 2. Click **Share**. A modal opens where you can add an optional note to the shared trade. 3. Submit. The alert card posts publicly to the channel, built from the trade's details — asset, action, size, option legs, order type, prices, and any exit criteria, for others to **Review & Trade** on their own brokerages. > **Note** > > Your `/trades` list is private to you; only the alert you post is visible to other members. See [Trade Alerts](/discord/trading#trade-alerts) for what members can do with an alert. #### Channel Permissions [#channel-permissions] Trade It needs to be able to see and post in any channel it shares to. Most channels work with no setup, but if the channel is ***private***, an admin must grant Trade It access to that channel: 1. Open the channel's settings and go to **Permissions**. 2. Add the Trade It app to the permission list. 3. Allow **View Channel** and **Send Messages** for it. ![/trades permissions](https://images.tradeit.app/docs/discord_trades_permissions.png) ## `/connect` [#connect] Opens Trade It so you can connect a brokerage. After connecting, your brokerage account becomes available for use with the `/trade`, `/accounts`, and `/holdings` commands. ![/connect command](https://images.tradeit.app/docs/discord_command_connect.png) ![/connect response](https://images.tradeit.app/docs/discord_connect.png) ![Trade It's brokerage connection screen](https://images.tradeit.app/docs/connect_screen.png) ## `/login` [#login] Links your Discord account to your Trade It account. You can start using slash commands after successfully doing so. ![/login command](https://images.tradeit.app/docs/discord_command_login.png) ![/login response](https://images.tradeit.app/docs/discord_login.png) ![/login response](https://images.tradeit.app/docs/linked_accounts.png) ## `/logout` [#logout] Disconnects the current Discord account from your Trade It account. Slash commands will stop working after doing this. ![/logout command](https://images.tradeit.app/docs/discord_command_logout.png) ![/logout response](https://images.tradeit.app/docs/discord_logout.png) See [Account Setup](/discord/account-setup) for details. # Trade It Discord Bot (beta) Source: https://docs.tradeit.app/discord This document outlines the features of the Trade It Discord Bot and guides you through the initial setup to enhance your community engagement. Integrated directly into Discord and connected to [all major brokerages](/brokerages), the Trade It Bot checks accounts, reviews holdings, scans recent orders, places trade orders in plain English, copies Discord posts into trade drafts, and shares trade alerts that other members can place on their own brokerage accounts in 1 click. ## Setup [#setup] | Step | What to do | | --- | --- | | 1 | [Install the bot](/discord/installation) in your Discord server. | | 2 | Run `/login` to bind your Discord username to your Trade It account. **Note that a Pro plan is required.** | | 3 | Run `/connect` to connect your first brokerage to Trade It. *Skip if you've already done this.* | | 4 | Done! Test the bot by checking your accounts `/accounts` or creating a trade alert `/alert Buy $100 of AMZN`. | ## Features [#features] | Feature | Command | | --- | --- | | Copy any post into a trade draft | **Right Click → Copy Trade** | | Share trade alerts with a community | `/alert` | | Draft stock, crypto, and option trades | `/trade` | | Review connected brokerage accounts | `/accounts` | | Check holdings in an account | `/holdings` | | See recent orders | `/trades` | | Share a recent order as a trade alert | **Share** button on `/trades` | | Connect a new brokerage | `/connect` | ## Why It Works In Discord [#why-it-works-in-discord] - **Fast enough for chat**: Slash commands, concise cards, no dashboard detour for simple actions. - **Community-ready**: Admins share trade alerts; members execute them on their own brokerage in 1 click. - **No fat-fingering**: Trades are created as drafts and require confirmation before placing on a connected brokerage. - **Brokerage-aware**: Target a specific account by id or account name. - **Options-ready**: Single-leg contracts and multi-leg spreads are supported. ## Pages [#pages] - [Installation](/discord/installation) - [Commands](/discord/commands) - [Account Setup](/discord/account-setup) - [Trading & Safety](/discord/trading) # Discord Bot Installation Source: https://docs.tradeit.app/discord/installation Add Trade It to your server, pick the channels where it belongs, and start with `/help`. [Install Trade It In Discord](https://discord.com/oauth2/authorize?client_id=1420881647410352159&permissions=2048&integration_type=0&scope=bot+applications.commands) ## Install [#install] To add the bot to your Discord server: 1. Open the install link above. 2. Choose your server from the dropdown list. ![Discord bot installation screen](https://images.tradeit.app/docs/discord_install.png) 3. Review permissions and click **Authorize**. ![Discord bot authorization screen](https://images.tradeit.app/docs/discord_authorize.png) The bot is now available on your server! ## Permissions [#permissions] Before authorizing, the following permissions will be requested. | Permission | Why it is needed | | --- | --- | | Send messages | Lets the bot respond to commands with cards, buttons, and text. | > **Note** > > Trade It does not require administrator access. It cannot modify channels, nor send messages as any user. It only responds to known [slash and menu commands](/discord/commands). ## Settings [#settings] Configure the bot by right-clicking your server in Discord and navigating to ***Server Settings > Integrations > Bots and Apps > Trade It*** Use Role and Channel permissions to decide where the bot can be used. If you want a quieter rollout, keep it to one private channel first. ![Discord settings screen](https://images.tradeit.app/docs/discord_settings.png) ## Testing [#testing] To test that the bot is working and to see a list of its capabilities, use the `/help` command. You can also test the message context menu by right-clicking any trade callout and choosing **Apps → Trade It → Copy Trade**. ![/help command](https://images.tradeit.app/docs/discord_command_help.png) ![/help response](https://images.tradeit.app/docs/discord_help.png) # Trading And Safety Source: https://docs.tradeit.app/discord/trading Discord is fast. Trading should still be deliberate. ## The Flow [#the-flow] ```text /trade Buy $100 of AMZN ``` Trade It returns a review card with: | Section | What to check | | --- | --- | | Details | Asset, action, quantity, option legs | | Pricing | Market, limit, stop, debit, credit | | Exit Criteria | Take-profit and stop-loss when attached to a Buy | | Total | Estimated cost or credit | | Account | Where the order will route | ## Buttons [#buttons] | Button | Result | | --- | --- | | **Confirm** | Places the order. | | **Cancel** | Cancels the draft. | | **Open in Trade It** | Opens the full trade page. | If placement fails, the card shows the broker error and keeps a Retry button live. ## Exit Criteria [#exit-criteria] Attach a take-profit and/or stop-loss to a simple **Buy** to close the resulting long position automatically. ```text /trade Buy $100 of AMZN take profit 10% stop loss 5% ``` Each exit can be an absolute price (`take profit $110`) or a percentage from the entry (`take profit 5%`), and shows in its own **Exit Criteria** section on the card. Sell and options orders cannot have attached exits. Support varies by brokerage — see [Supported Brokerages](/brokerages). ## Trade Alerts [#trade-alerts] Use `/alert` to share a trade idea without placing an order for yourself or anyone else. ```text /alert details:Buy $100 of AMZN note:Starter position ``` Trade It returns a public alert card with: | Section | What members see | | --- | --- | | Note | Optional context from the person sharing the alert | | Order Details | Asset, action, quantity, option legs, and order type | | Price Details | Limit or stop instructions when included | | Exit Criteria | Take-profit and stop-loss when the alert includes exits | | Button | A **Review & Trade** button that opens Trade It | Each member reviews the trade, edits anything they need like position size or limit price, and places the order through their own connected brokerage. The alert creator cannot execute trades for other members. ### Sharing A Placed Trade [#sharing-a-placed-trade] You can also create an alert from a trade you already placed, instead of typing it out with `/alert`. Run `/trades`, click **Share** on the trade, and add an optional note in the window that opens. The bot builds the same alert card from the trade's existing details and posts it publicly to the channel. See [Sharing a Trade](/discord/commands#sharing-a-trade). ## Using Copy Trade [#using-copy-trade] Not every trade in a community arrives as a Trade It alert. Leaders post text callouts, screenshots, and alerts from other bots. **Copy Trade** copies any of those into a trade draft for your own account: 1. Right-click the message (long-press on mobile). 2. Choose **Apps → Trade It → Copy Trade**. 3. Review the private trade card the bot returns, then click **Review & Trade** to edit and execute it on your own brokerage. The same safety rules apply as everywhere else in Trade It: the response is visible only to you, the trade is review-first, and it routes to your own brokerage. The message author is never involved and other members won't see your trade. The bot reads the message the way a trader would, understanding common terminology. When a detail truly is not there, such as which strike or expiration, it replies naming the missing detail. See [Copy Trade](/discord/commands#copy-trade) for what kinds of messages it can read. ## Account Targeting [#account-targeting] You can let Trade It use your default account: ```text /trade Buy 5 shares of RKLB ``` Or name the account: ```text /trade Buy 5 shares of RKLB in my ETrade account ``` If there is more than one match, use `/accounts` and rerun with the exact account id. ## Options [#options] The bot handles both explicit contracts and plain-English option orders. Good prompts: ```text /trade Buy 1 AMZN 290/300 call spread expiring Jun 5 /trade Buy 1 SPY call expiring Friday 10% OTM /trade Sell 1 AAPL 330 call expiring Dec 5 limit 2.10 ``` Include call or put, expiration, quantity, and price instructions when you have them. If something is missing, the bot will ask you to rerun the command with the missing detail. ## Auto-Execute [#auto-execute] Auto-execute lives in the Trade It dashboard. Turn it on only when your default account and order settings are exactly how you want them. Without auto-execute, Discord trades draft first. # Trade It Source: https://docs.tradeit.app/ Turn any product into a trading platform Connect your platform to Trade It with our AI Skill, OAuth, REST API, and MCP server [Platform Integration](/sdk) [REST API](/api) [MCP Server](/mcp) [Trade Links](/trade-links) [Discord Bot](/discord) ## Platform Integration One portal, two modes: onboard users once, then manage their brokerage connections. Read account data and place user-approved trades. [Platform Integration](/sdk) ## API Endpoints for placing trades, connecting brokerages, and accounts details, trades. [API](/api) ## MCP Server Connect Trade It to Cursor, Claude, Codex, VS Code, Gemini, and other MCP-compatible clients [MCP Server](/mcp) ## Trade Links Best for blogs, newsletters, research products, and communities. Add a link and open a prefilled trading experience instantly. [Trade Links](/trade-links) ## Discord Bot Add trading, account lookup, holdings, and recent trade commands to your Discord community. [Discord Bot](/discord) ## Brokerage List Supported brokerages and platform capabilities [Brokerage List](/brokerages) # Installation Source: https://docs.tradeit.app/installation Add the Trade It MCP server to your MCP-compatible client to connect AI assistants to your brokerage accounts. For the full list of supported brokerages, [see here](/brokerages). ## Server URL [#server-url] - Streamable HTTP (preferred): `https://mcp.tradeit.app/mcp` - SSE (deprecated): `https://mcp.tradeit.app/sse` ## ![](/claude.svg) Claude Code [#claude-code] 1. Run the following command in your terminal to add the Trade It MCP to Claude Code: ```bash claude mcp add --transport http tradeit https://mcp.tradeit.app/mcp ``` 2. Type `/mcp` in Claude to manage your MCP servers and select **tradeit** 3. Select **Authenticate** to begin the OAuth flow 4. Click **Allow Access** when prompted 5. Confirm your MCP server is connected using the `/mcp` command 6. Start prompting! ## ![](/claude.svg) Claude Desktop [#claude-desktop] Add the server to your Claude Desktop configuration (e.g. `~/Library/Application Support/Claude/claude_desktop_config.json`): ```json { "mcpServers": { "tradeit": { "url": "https://mcp.tradeit.app/mcp" } } } ``` Restart Claude Desktop. When you first use a tool that requires brokerage access, you'll be asked to sign in with Trade It and link your accounts. ## ![](/codex.png) Codex [#codex] 1. Run the following command in your terminal to add the Trade It MCP to Codex: ```bash codex mcp add Trade_It -- npx -y mcp-remote@latest https://mcp.tradeit.app/mcp ``` 2. Authenticate with Trade It when prompted 3. Start prompting! ## ![](/cursor.svg) Cursor [#cursor] [Add to Cursor](cursor://anysphere.cursor-deeplink/mcp/install?name=TradeIt&config=eyJ1cmwiOiJodHRwczovL21jcC50cmFkZWl0LmFwcC9tY3AifQ==) 1. Click above to open the MCP configuration in Cursor 2. Click **Install** under "Install MCP Server?" 3. Click **Connect** next to Trade It to begin the authentication process 4. Click **Open** and allow access when prompted 5. Start prompting! ## ![](/gemini.png) Gemini [#gemini] 1. Run the following command in your terminal to add the TradeIt MCP to Gemini CLI: ```bash gemini mcp add --transport http Trade_It ``` 2. Authenticate with Trade It when prompted 3. Start prompting! ## ![](/vscode.svg) VS Code [#vs-code] [Add to VS Code](vscode:mcp/install?%7B%22name%22%3A%22tradeit%22%2C%22type%22%3A%22http%22%2C%22url%22%3A%22https%3A%2F%2Fmcp.tradeit.app%2Fmcp%22%7D) 1. Click above to open VS Code and prompt to install the MCP server 2. Click **Start** above the MCP server name 3. **Allow Access** when prompted 4. Start prompting! ## Other MCP Clients [#other-mcp-clients] Any client that supports MCP over HTTP can use this server. Configure it with the URL above. Authentication uses OAuth; you'll be redirected to sign in with Trade It when connecting your brokerage accounts. ## Linking Brokerages [#linking-brokerages] After installing, visit https://tradeit.app to link your brokerage accounts. This is a one-time setup. See [Supported Brokerages](/brokerages) for the full list of possible brokerages. # Trade It MCP Server Source: https://docs.tradeit.app/mcp URL: https://mcp.tradeit.app Trade It connects AI assistants directly to your brokerage accounts, enabling you to search assets, review account balances, and place real trades — all through natural language. ## What Trade It Can Do [#what-trade-it-can-do] Trade It exposes these tools to MCP-compatible clients: - **Search assets** — Look up stocks and crypto by ticker or name, with real-time prices - **View accounts** — List all linked brokerage accounts with balances - **View holdings** — List holdings for a specific linked account - **View trades** — List trade orders - **Create trades** — Draft buy/sell orders for stocks, ETFs, and options for user review - **Create Trade Links** — Generate shareable trades that other users can review, edit, and execute on their own brokerage accounts - **Execute trades** — Place confirmed draft trades with your broker - **Cancel trades** — Cancel drafts or request cancellation of eligible submitted orders - **Options trading** — Multi-leg options strategies with full OCC format support > **Note** > > Holdings are cached daily by default. Paid plans can request `refresh: true` on `get_holdings` and `get_trades` to pull fresh brokerage data, subject to a 1 request per minute limit per account. For the full tool reference, see [Tools](/tools/). ## Authentication [#authentication] #### OAuth 2.0 [#oauth-2-0] Trade It uses OAuth 2.0 by default. When you first connect the server, you'll be redirected to sign in with your Trade It account. Create an account at [tradeit.app](https://tradeit.app) if you don't have one. Once signed in, Trade It securely manages your brokerage connections. No credentials are stored by the AI client. #### API Key [#api-key] If you prefer not to use the interactive OAuth flow, you can also create [API keys](https://tradeit.app/account/api-keys) from your account instead. Keys can be revoked at any time. ## Getting Started [#getting-started] See [Installation](/installation) for step-by-step setup instructions for Claude, Cursor, VS Code, Codex, and other MCP-compatible clients. ## Usage Examples [#usage-examples] ### Example 1: Search for a Stock [#example-1-search-for-a-stock] > **User:** What's the current price of Tesla? Trade It calls `search_assets` and returns the current price, company name, ticker, exchange, and asset type. --- ### Example 2: Place a Trade [#example-2-place-a-trade] > **User:** Buy $500 of Apple stock Trade It calls `create_trade` and creates a **draft** market order. The AI confirms the order details and reminds you to press Execute when ready. Your trade is never submitted without explicit confirmation. --- ### Example 3: Share A Trade Link [#example-3-share-a-trade-link] > **User:** Create a Trade Link for buying $500 of Apple stock Trade It calls `create_trade_link` and returns a shareable URL. Opening the URL lets another user review the trade, edit details if needed, and place it through their own connected brokerage. --- ### Example 4: Review Your Accounts [#example-4-review-your-accounts] > **User:** Show me my brokerage accounts Trade It calls `get_accounts` and returns all linked accounts with balances, available cash, and brokerage names. You can follow up with trade instructions targeting a specific account. --- ### Example 5: Limit Order [#example-5-limit-order] > **User:** Buy 10 shares of NVDA only if it drops below $800 Trade It calls `create_trade` with `order_type: "limit"` and `limit_price: 800`, creating a draft limit order ready for your confirmation. ### Example 6: Options Debit Spread [#example-6-options-debit-spread] > **User:** Buy a TSLA bull call spread — buy the $250 call and sell the $260 call, both expiring June 20, 2025 Trade It calls `create_options_trade` with two legs and `direction: "debit"`: | Leg | Action | Type | Strike | Expiry | OCC | |-----|--------|------|--------|--------|-----| | 1 | Buy | Call | $250 | Jun 20, 2025 | `250620C00250000` | | 2 | Sell | Call | $260 | Jun 20, 2025 | `250620C00260000` | The result is a **draft** spread order showing both legs, the net debit (maximum loss), and the maximum potential gain ($10 spread width minus the net debit paid). The order is submitted to your broker only after you explicitly confirm. --- ### Example 7: Review Holdings for an Account [#example-7-review-holdings-for-an-account] > **User:** Show me the holdings for account 123 Trade It calls `get_holdings` with `account_id: 123` and returns a normalized list of holdings for that linked brokerage account. The output formats stocks, crypto, and options into a single holdings list. --- ### Example 8: Refresh Latest Trades [#example-8-refresh-latest-trades] > **User:** Refresh my latest trades Trade It calls `get_trades` with `refresh: true` and returns a paginated trade page including `trades`, `next_cursor`, and `has_more`. Pass `next_cursor` into the next call to continue paging through older trades. Fresh refreshes are available to paid plans and partner-linked users, with a 1-minute cooldown per linked account. --- ## Privacy & Support [#privacy-support] - **Privacy Policy:** [tradeit.app/privacy-policy](https://tradeit.app/privacy-policy) - **Support:** [support@tradeit.app](mailto:support@tradeit.app) or [tradeit.app/contact](https://tradeit.app/contact) # Account Source: https://docs.tradeit.app/models/account A brokerage account the user connected. [Get accounts](/api/get-accounts) returns accounts, and [account webhook events](/sdk/webhooks#account-added) send one as `data`. ## Fields [#fields] **`id`** `number | string` Trade It account ID. Pass it as `account_id` in holdings and trade requests. **`created_at`** `string` When the record was created. **`updated_at`** `string` `optional` When the record last changed. **`connection_id`** `number | string` The brokerage login the account belongs to. Accounts on one connection disconnect and reconnect together. **`external_id`** `string` The brokerage's account number. Not included in webhook events. **`name`** `string` `optional` Display name: the brokerage plus the account number's last four digits. **`balance`** [Balance](#balance) Total account value. **`cash`** [Balance](#balance) Cash balance. **`buying_power`** [Balance](#balance) Funds available to trade. **`synced_at`** `string (format: date-time)` `optional` When balances were last synced from the brokerage. **`holdings_synced_at`** `string (format: date-time)` `optional` When holdings were last synced from the brokerage. **`trades_synced_at`** `string (format: date-time)` `optional` When trade history was last synced from the brokerage. ## Brokerage details [#brokerage-details] [Get accounts](/api/get-accounts) returns each account as `{ account, brokerage_metadata, connection }`. These are the fields beside `account`. **`brokerage_metadata`** `object` The brokerage holding the account and what it supports. > **`id`** `number` > > > Trade It brokerage ID. > > > **`name`** `string` > > > Brokerage name. > > > **`fractional_support`** `boolean` > > > Whether the brokerage supports fractional shares. > > > **`minimum_order`** `number` `optional` > > > Smallest order the brokerage accepts, in USD. > > > **`options_support`** `boolean` > > > Whether the brokerage supports options. > > > **`take_profit_support`** `boolean` `optional` > > > Whether the brokerage can attach a take-profit exit to an entry order. > > > **`stop_loss_support`** `boolean` `optional` > > > Whether the brokerage can attach a stop-loss exit to an entry order. **`connection`** `object` The account's brokerage connection. `id` matches the account's `connection_id`. > **`id`** `number | string` > > > The database ID. Use for lookups. > > > **`status`** `enum` `optional` > > > `0` pending, `1` connected, `10` disconnected. > > > `0``1``10` ## Balance [#balance] Money fields are Balance objects. **`amount`** `number` Amount in `currency`. **`currency`** `string` ISO 4217 currency code, such as `USD`. # Holding Source: https://docs.tradeit.app/models/holding A position in a brokerage account. [Get holdings](/api/get-holdings) returns an array of holdings. > **Note** > > Enrichment fields like `market_price` can be absent or `null` when a brokerage does not supply them. `warning` says why. ## Fields [#fields] **`key`** `string` `optional` Stable identifier for the position: the normalized symbol, or the compact OCC symbol for options. **`symbol`** `string` Normalized ticker, crypto pair, or OCC option symbol. **`display_symbol`** `string` `optional` Symbol to show users. **`quantity`** `number` Shares, coins, or contracts held. Negative for a short position. **`average_price`** [Balance](#balance) `deprecated` Brokerage-specific legacy value. Use `average_unit_cost`. **`average_unit_cost`** [Balance](#balance) | null `optional` Average cost per share, coin, or option share, before `multiplier`. Null when the brokerage does not report it. **`description`** `string` `optional` Name of the security, such as `Cloudflare, Inc.` **`type`** `enum` Asset type: `2` for stocks and options, `4` for crypto. `0``2``4``8` **`side`** `enum` `optional` Whether the position is long or short. `long``short` **`instrument_kind`** `enum` `optional` Whether the position is an equity, crypto, or option. `equity``crypto``option` **`option_symbol`** `string` `optional` The option's OCC symbol as the brokerage reports it. **`multiplier`** `number` `optional` Shares each unit controls: 100 for standard options, 1 otherwise. **`total_cost`** [Balance](#balance) | null `optional` `quantity` × `average_unit_cost` × `multiplier`. **`market_price`** [Balance](#balance) | null `optional` Current price per share, coin, or option share. Null when no price is available. **`market_value`** [Balance](#balance) | null `optional` `quantity` × `market_price` × `multiplier`. **`unrealized_pnl`** [Balance](#balance) | null `optional` `market_value` minus `total_cost`. **`unrealized_pnl_percent`** `number | null` `optional` `unrealized_pnl` as a percent of `total_cost`, such as `12.5` for 12.5%. **`price_kind`** `enum` `optional` Where `market_price` came from. `midpoint` is the option bid/ask midpoint. `last_trade``minute_close``midpoint``brokerage``unavailable` **`price_as_of`** `string | null` `optional` When `market_price` was observed. **`delayed`** `boolean` `optional` Whether `market_price` is delayed. **`underlying_symbol`** `string` `optional` The option's underlying ticker. **`warning`** `string` `optional` Why a value is missing, such as `Current price unavailable`. ## Balance [#balance] Money fields are Balance objects. **`amount`** `number` Amount in `currency`. **`currency`** `string` ISO 4217 currency code, such as `USD`. # Trade Source: https://docs.tradeit.app/models/trade An order and its fills. [Get trades](/api/get-trades) and the trade operations return trades, and [`TRADE_UPDATED`](/sdk/webhooks#trade-updated) webhook events send one as `data`. ## Fields [#fields] **`id`** `number | string` Trade It trade ID. Pass it as `trade_id` to execute or cancel the trade. **`created_at`** `string` When the record was created. **`updated_at`** `string` `optional` When the record last changed. **`user_id`** `number | string` The Trade It user who owns the trade. **`asset_id`** `number | string` The traded asset, or the underlying for options. **`account_id`** `number | string | null` The account the trade is sent to. **`source`** `string | null` Where the trade came from: `ios_app`, `chatgpt`, `mcp`, `api`, or `discord`, or `brokerage:<brokerage id>` for trades synced from brokerage history. **`image_url`** `string | null` Screenshot the trade was created from. **`external_id`** `string` The brokerage's order ID. Not included in webhook events. **`type`** `enum` `0` for a simple buy/sell, `1` for options/multi-leg. `0``1` **`action`** `enum` Whether the trade buys or sells. `buy``sell` **`direction`** `enum | null` Whether a multi-leg trade pays (`debit`) or receives (`credit`) its net premium. Null for simple trades. `debit``credit``even` **`total_units`** `number` Shares or coins ordered. A multi-leg trade counts its whole package as `1`. **`filled_units`** `number` Units filled so far. **`canceled_units`** `number` Units canceled. A canceled order can still be partly filled. **`notional_amount`** [Balance](#balance) | null Dollar amount, for orders placed by value instead of units. **`execution_price`** [Balance](#balance) | null Average fill price, always positive. For multi-leg trades, the net cash for the whole package. Null until something fills. **`status`** `enum` Order status. `complete`, `canceled`, `failed`, and `disconnected` are final. `draft``pending``placed``partially_filled``complete``canceled``failed``disconnected` **`order_type`** `enum` How the order is priced. `market``limit``stop``stop_limit` **`limit_price`** [Balance](#balance) | null Limit price, for limit and stop-limit orders. For multi-leg trades, the net premium per spread unit. **`stop_price`** [Balance](#balance) | null Price that triggers a stop or stop-limit order. **`take_profit`** `object | null` `optional` Take-profit exit attached to a buy. > **`value`** `number` > > > Exit trigger level > > > **`unit`** `enum` > > > Absolute price ($) or percent from entry price (%). > > > `$``%` **`stop_loss`** `object | null` `optional` Stop-loss exit attached to a buy. > **`value`** `number` > > > Exit trigger level > > > **`unit`** `enum` > > > Absolute price ($) or percent from entry price (%). > > > `$``%` **`time_in_force`** `enum | null` How long the order stays active. `day``gtc``ioc``fok` **`placed_at`** `string (format: date-time) | null` When the order was sent to the brokerage. **`executed_at`** `string (format: date-time) | null` When the order finished filling. **`error_message`** `string | null` Why the trade failed. **`fee`** [Balance](#balance) | null Fees the brokerage charged. **`legs`** `array of object | null` Legs of a multi-leg trade. Null for simple trades. > Each item has: > > > **`type`** `enum` > > > Whether the leg trades an option or the underlying stock. > > > `option``equity` > > > **`action`** `enum` > > > Whether the leg buys or sells. > > > `buy``sell` > > > **`position_effect`** `enum | null` > > > Whether the leg opens or closes a position. > > > `open``close` > > > **`occ`** `string | null` > > > OCC option contract symbol, e.g. 260717C00435000. Null for stock legs. > > > **`quantity`** `number` > > > Number of option contracts, or shares for a stock leg. > > > **`execution_price`** [Balance](#balance) | null > > > The leg's fill price per share. Null when the brokerage only reports a price for the whole package. **`event`** `enum | null` Set when the trade records an option assignment, exercise, or expiration instead of an order. `assignment``exercise``expiration` **`analysis`** `string | null` Analysis of the screenshot the trade was created from. **`asset`** `object` `optional` The traded asset. Returned by `get_trades`; webhook events only include `asset_id`. > **`id`** `number | string` > > > The database ID. Use for lookups. > > > **`created_at`** `string` > > > When the record was created. > > > **`updated_at`** `string` `optional` > > > When the record last changed. > > > **`name`** `string | null` > > > Company or coin name. > > > **`ticker`** `string` > > > Ticker symbol. > > > **`type`** `enum` > > > Asset type: `2` for stocks, `4` for crypto, `8` for indexes. > > > `0``2``4``8` > > > **`logo_url`** `string | null` > > > Logo image URL. > > > **`description`** `string | null` > > > Short description of the asset. > > > **`exchange`** `string` > > > Exchange the asset trades on. > > > **`mic_code`** `string | null` > > > ISO 10383 market identifier code of the exchange. > > > **`underlying`** `string | null` > > > Underlying ticker, for derivatives. > > > **`country`** `string | null` > > > Country the asset is listed in. > > > **`delisted_at`** `string (format: date-time) | null` > > > When the asset was delisted. ## Balance [#balance] Money fields are Balance objects. **`amount`** `number` Amount in `currency`. **`currency`** `string` ISO 4217 currency code, such as `USD`. # Read accounts Source: https://docs.tradeit.app/sdk/accounts Fetch the user's connected brokerage accounts from your server using their [OAuth access token](/sdk/authentication). **Scopes:** `brokerage:read tool:execute`. ## Server side: fetch accounts [#server-side-fetch-accounts] ```js const response = await fetch('https://api.tradeit.app/api/tool/execute', { method: 'POST', headers: { Authorization: `Bearer ${accessToken}`, 'Content-Type': 'application/json', }, body: JSON.stringify({ toolName: 'get_accounts', params: {} }), }); if (!response.ok) throw new Error(`Account request failed: ${response.status}`); const accounts = await response.json(); ``` **Returns:** [Account[]](/models/account), each wrapped with its `brokerage_metadata` and `connection`. See [Get accounts](/api/get-accounts#example-response) for a sample response. # Set up OAuth and sign in users Source: https://docs.tradeit.app/sdk/authentication Let users authorize your platform with Trade It, then save their tokens on your server. These JavaScript snippets fit into your existing app; use your framework's routes, sessions, and database. Use this guide when you want to customize authorization with your own redirect flow, then use the portal in [Connection mode](/sdk/connect) with the tokens you save. Prefer to have your coding client implement this? Start with the [AI Skill and example prompt](/sdk#build-with-the-ai-skill). | Client side | Server side | | --- | --- | | Show **Sign in with Trade It** and navigate to your authorization route. | Build the authorization URL and redirect to Trade It. | | Show the connected state when the user returns. | Handle the callback, validate state, and exchange the code. | | Call your server for accounts, holdings, trade history, and modal session URLs. | Store and refresh tokens per user; call Trade It with those tokens. | ## 1. Configure your client (server side) [#_1-configure-your-client-server-side] [Create your organization and save its credentials](/sdk#_1-create-your-organization-and-get-credentials). Register your server-side callback URL in Trade It, for example: ```text https://app.example.com/auth/tradeit/callback ``` > **Note** > > The redirect URI must match exactly, including scheme, host, port, path, and trailing slash. Register a separate localhost URL if you need local development. Store these values in your server environment: ```dotenv TRADE_IT_CLIENT_ID=your_client_id TRADE_IT_CLIENT_SECRET=your_client_secret TRADE_IT_REDIRECT_URI=https://app.example.com/auth/tradeit/callback ``` Load them in your server and validate that they are set when your app starts: ```js const clientId = process.env.TRADE_IT_CLIENT_ID; const clientSecret = process.env.TRADE_IT_CLIENT_SECRET; const redirectUri = process.env.TRADE_IT_REDIRECT_URI; ``` > **Note** > > The Client Secret and user tokens must stay on your server. Do not put them in browser code or local storage. ## 2. Discover endpoints (server side) [#_2-discover-endpoints-server-side] Fetch the metadata once when your server starts and use the returned endpoints: ```http GET https://tradeit.app/.well-known/oauth-authorization-server Accept: application/json ``` ```js const response = await fetch( 'https://tradeit.app/.well-known/oauth-authorization-server', { headers: { Accept: 'application/json' } }, ); if (!response.ok) throw new Error('OAuth discovery failed'); const metadata = await response.json(); const authorizationEndpoint = metadata.authorization_endpoint; const tokenEndpoint = metadata.token_endpoint; ``` **Example response** ```json { "authorization_endpoint": "https://auth.tradeit.app/auth/v1/authorize", "token_endpoint": "https://auth.tradeit.app/auth/v1/token" } ``` Trade It supports authorization-code and refresh-token grants, PKCE with `S256`, and client authentication with `client_secret_basic` or `client_secret_post`. The examples below use `client_secret_post`. > **Note** > > Permissions are assigned automatically based on your client type. You do not need to request scopes in the authorization URL. ## 3. Add Sign in with Trade It (client side) [#_3-add-sign-in-with-trade-it-client-side] Link to an authorization route on **your server**: ```html Sign in with Trade It ``` The browser follows your server's redirect to Trade It, where the user signs in and approves access. ## 4. Start authorization with PKCE (server side) [#_4-start-authorization-with-pkce-server-side] In your `/auth/tradeit` handler, generate a new `state` and PKCE verifier for each attempt. Save them in the user's server-side session before redirecting. Here, `session` is your existing server-side session and `userId` is the authenticated platform user. Persist session changes using your framework's session API. ```js import { randomBytes, createHash } from 'node:crypto'; const state = randomBytes(32).toString('base64url'); const codeVerifier = randomBytes(32).toString('base64url'); const codeChallenge = createHash('sha256') .update(codeVerifier).digest('base64url'); session.tradeItOAuth = { state, codeVerifier, userId, createdAt: Date.now() }; const authorizationUrl = new URL(authorizationEndpoint); authorizationUrl.search = new URLSearchParams({ response_type: 'code', client_id: clientId, redirect_uri: redirectUri, state, code_challenge: codeChallenge, code_challenge_method: 'S256', }).toString(); ``` Save the session, then return an HTTP redirect to `authorizationUrl.toString()` using your framework. Require the same authenticated platform user on the start route and callback; this flow links Trade It authorization to that user's platform account. ## 5. Validate the callback (server side) [#_5-validate-the-callback-server-side] Trade It redirects the browser to your registered callback with either: ```text ?code=ONE_TIME_CODE&state=ORIGINAL_STATE ``` or an error such as `?error=access_denied&state=ORIGINAL_STATE`. In your callback handler, read the query parameters and the pending attempt from the same server-side session. `callbackUrl` below is the incoming request URL; `userId` is the current authenticated platform user. ```js const params = new URL(callbackUrl).searchParams; const pending = session.tradeItOAuth; delete session.tradeItOAuth; if (!pending || params.get('state') !== pending.state || pending.userId !== userId || Date.now() - pending.createdAt > 10 * 60 * 1000) { throw new Error('Invalid or expired authorization. Start again.'); } if (params.has('error')) { throw new Error('Trade It authorization was not completed.'); } const code = params.get('code'); if (!code) throw new Error('Missing authorization code'); ``` Persist removal of the pending attempt even on failure, so it cannot be reused. Handle these errors by showing a retry or canceled-authorization state in your client. Only continue to the token exchange after validation succeeds. ## 6. Exchange the code and save tokens (server side) [#_6-exchange-the-code-and-save-tokens-server-side] Send the code, original verifier, and client credentials to the token endpoint. Use the same redirect URI as the authorization request. ```js const response = await fetch(tokenEndpoint, { method: 'POST', headers: { 'Content-Type': 'application/x-www-form-urlencoded' }, body: new URLSearchParams({ grant_type: 'authorization_code', client_id: clientId, client_secret: clientSecret, redirect_uri: redirectUri, code, code_verifier: pending.codeVerifier, }), }); if (!response.ok) throw new Error('Trade It token exchange failed'); const tokens = await response.json(); const tokenRecord = { userId, accessToken: tokens.access_token, refreshToken: tokens.refresh_token, expiresAt: Date.now() + tokens.expires_in * 1000, }; ``` Save `tokenRecord` in your database, keyed by the platform user bound to the authorization attempt. Encrypt tokens at rest and keep them out of logs. After saving, redirect the browser to your platform's connected screen. Return connection status to the client, not OAuth tokens. ## Refresh expired tokens (server side) [#refresh-expired-tokens-server-side] Use the access token returned by OAuth until it approaches expiry. Before calling Trade It, load the current user's token record; refresh it on your server only when it is close to `expiresAt`: ```js const response = await fetch(tokenEndpoint, { method: 'POST', headers: { 'Content-Type': 'application/x-www-form-urlencoded' }, body: new URLSearchParams({ grant_type: 'refresh_token', client_id: clientId, client_secret: clientSecret, refresh_token: stored.refreshToken, }), }); if (!response.ok) throw new Error('Trade It token refresh failed'); const tokens = await response.json(); const updatedRecord = { ...stored, accessToken: tokens.access_token, refreshToken: tokens.refresh_token ?? stored.refreshToken, expiresAt: Date.now() + tokens.expires_in * 1000, }; ``` Here, `stored` is the database record from step 6. Save `updatedRecord` atomically before using the new access token. Serialize refreshes per user so concurrent requests cannot overwrite rotated credentials. If the grant is expired or revoked, ask the user to sign in with Trade It again; a temporary network failure should not erase their saved credentials. ## Use the connection [#use-the-connection] Your client calls your own authenticated server-side routes. Your server loads that user's current access token and sends `Authorization: Bearer ` to Trade It. - [Connection portal](/sdk/connect): the server creates a session URL; the client opens it with the React SDK. - [Accounts](/sdk/accounts), [holdings](/sdk/holdings), and [trade history](/sdk/trade-history): the server reads data; the client displays it. - [Trading](/sdk/trades): the client collects order approval; the embedded modal or your server submits the approved order. ## Troubleshooting [#troubleshooting] | Problem | Check | | --- | --- | | Callback rejected | The registered redirect URI matches both requests exactly. | | Invalid or expired authorization | The session persists across redirects, the platform user is unchanged, and `state` matches. | | Token exchange fails | Correct client credentials, unused code, matching redirect URI and PKCE verifier. | | API returns `403` | The permissions assigned to your client type. Contact Trade It if your integration needs different access. | Before shipping, check successful sign-in, denied consent, invalid state, token refresh, and reconnection after revoked access. Confirm each platform user can access only their own saved Trade It connection. # Connection mode Source: https://docs.tradeit.app/sdk/connect Open the Trade It Portal in **Connection mode** whenever a user wants to add or reconnect a brokerage. Their saved authorization takes them straight to brokerage selection. This is the same portal used in [Onboarding mode](/sdk/onboarding), configured with the user’s access token. The endpoint and SDK method stay the same. ![Brokerage picker showing existing and expired connections.](https://images.tradeit.app/docs/connect_accounts.png?v=4) Select a brokerage ![Brokerage sign-in during connection.](https://images.tradeit.app/docs/connect_brokerage.png) Authorize the brokerage ![Successful brokerage connection.](https://images.tradeit.app/docs/connect_success.png?v=4) Connection ready ## Configure your request [#configure-your-request] **Your backend** · Use the saved authorization Reuse your `POST /api/tradeit/portal` route. Load the signed-in user’s saved Trade It access token and refresh it if expired. Send that token as **Bearer** authentication to select Connection mode. Omit `oauth_options`; use `connect_options` to customize brokerage selection. > **Onboard each user once** > > If the user has not authorized your app, start in [Onboarding mode](/sdk/onboarding) and save their access and refresh tokens. Connection mode reuses that authorization, so there is no new Trade It sign-in, consent screen, or authorization-code exchange. > **Keep tokens on your server** > > Require your platform’s authenticated session and CSRF protection. Return only the portal URL to the browser. Connection mode accepts any valid Bearer token with `brokerage:write` permission, including OAuth access tokens, direct sign-in tokens, and API keys. ## Create Portal URL [#create-portal-url] **Your backend** · `POST https://api.tradeit.app/api/portal` Use the user’s access token with Bearer authentication. Optional `connect_options` work the same way in both modes. ```js const portal = await fetch('https://api.tradeit.app/api/portal', { method: 'POST', headers: { Authorization: `Bearer ${accessToken}`, 'Content-Type': 'application/json', }, body: JSON.stringify({ connect_options: {}, }), }).then(res => res.json()); ``` Pass `portal.url` to your frontend. **Example response** ```json { "url": "https://tradeit.app/connect?ti_token=ti:...&embedded=1", "expiresAt": "2026-10-15T19:35:12.000Z" } ``` > **Portal URL lifetime** > > Create a fresh URL before opening the portal. It expires after **30 minutes**. Treat it as sensitive and keep it out of logs and analytics. ### Request details [#request-fields] | Field | Use | | --- | --- | | `connect_options` | Optional. Omit it or send `{}` to show all active brokerages. | | `connect_options.brokerage_code` | Open one [brokerage](/brokerages) directly. Cannot be combined with `brokerage_filter`. | | `connect_options.brokerage_filter.supports` | Required capabilities: `stock`, `crypto`, `options`, `fractional-shares`, `notional-orders`, `take-profit`, or `stop-loss`. A brokerage must support every listed capability. | | `connect_options.brokerage_filter.include` | Only show these brokerage codes. | | `connect_options.brokerage_filter.exclude` | Hide these brokerage codes. Exclusions take precedence over `include`. | #### Full list [#full-list] Omit `connect_options`, or use: ```json { "connect_options": {} } ``` #### Filtered list [#filtered-list] For example, show options-supporting brokerages except Tastytrade: ```json { "connect_options": { "brokerage_filter": { "supports": ["options"], "exclude": ["tastytrade"] } } } ``` > **Brokerage filter behavior** > > The picker omits inactive brokerages. If nothing matches, it shows every active brokerage. Filters customize the picker; they do not change your app’s permissions. #### One targeted brokerage [#one-targeted-brokerage] Skip the picker and open a specific brokerage’s connection flow: ```json { "connect_options": { "brokerage_code": "charles_schwab" } } ``` > **Keep the authorization current** > > Refresh expired access tokens before requesting a URL. Invalid tokens return `401`; the portal does not automatically switch to Onboarding mode. ## Open the portal [#open-the-portal] **Your frontend** · `npm install @trade-it/react` Use the same `openConnect` method as Onboarding mode. The returned URL opens Connection mode directly. ```tsx import { TradeItModal, useTradeIt } from '@trade-it/react'; function ManageConnectionsButton() { const tradeIt = useTradeIt(); async function openPortal() { const response = await fetch('/api/tradeit/portal', { method: 'POST' }); if (!response.ok) throw new Error('Unable to open the portal'); const { url } = await response.json(); tradeIt.openConnect({ launch: { mode: 'connect', url } }); } return ( <> {tradeIt.modalProps && } ); } ``` The user selects a brokerage and completes its sign-in. Some brokerages open a separate tab; the portal tracks progress and resumes automatically. > **No new authorization event** > > Connection mode uses the tokens you already saved. Your `onAuthorization` callback runs only when the portal is in Onboarding mode. ## Connection Flow [#connection-flow] See the progression from brokerage selection to a completed connection. ### 1. Select a brokerage [#_1-select-a-brokerage] Users choose a brokerage. Existing and expired connections are marked so they can add another account or reconnect. ![Brokerage selection with existing and expired connections labeled.](https://images.tradeit.app/docs/connect_accounts.png?v=4) Choose a brokerage to connect. ### 2. Complete brokerage authentication [#_2-complete-brokerage-authentication] The portal confirms the brokerage and starts its sign-in flow. ![Selected brokerage and the option to start authentication.](https://images.tradeit.app/docs/connect_start.png?v=4) Start the brokerage’s sign-in flow. Some brokerages open a separate tab or window. The portal tracks progress and resumes automatically when authentication finishes. ![Portal waiting for brokerage authentication to finish.](https://images.tradeit.app/docs/connect_in_progress.png?v=4) The portal tracks the connection. ![Brokerage authentication screen in a separate tab.](https://images.tradeit.app/docs/connect_brokerage.png) The user signs in with their brokerage. ### 3. Return to your app [#_3-return-to-your-app] Trade It confirms the connection. Your app can now load the user’s accounts, holdings, and trade history. ![Successful brokerage connection confirmation.](https://images.tradeit.app/docs/connect_success.png?v=4) The connection is ready. # SDK Enums Reference Source: https://docs.tradeit.app/sdk/enums These enums are exported from `@trade-it/react` so you can build trade configs with typed values instead of hardcoded strings. ```ts import { LegType, OrderDirection, OrderType, PositionEffect, TimeInForce, TradeAction, TradeLinkParam, TradeType, TradeUnit, TriggerUnit, } from '@trade-it/react'; ``` ## `TradeType` [#tradetype] Used to choose simple vs options/multi-leg trade mode. | Enum member | Value | Meaning | |---|---|---| | `TradeType.Simple` | `0` | Simple buy/sell trade | | `TradeType.MultiLeg` | `1` | Options / multi-leg trade | ## `TradeAction` [#tradeaction] Used for simple trades and option legs. | Enum member | Value | Meaning | |---|---|---| | `TradeAction.Buy` | `buy` | Buy | | `TradeAction.Sell` | `sell` | Sell | ## `TradeUnit` [#tradeunit] Used for simple trade `amount`. | Enum member | Value | Meaning | |---|---|---| | `TradeUnit.Dollars` | `dollars` | Amount is in dollars | | `TradeUnit.Shares` | `shares` | Amount is in shares | ## `OrderType` [#ordertype] Used for both simple and options trades. | Enum member | Value | Meaning | |---|---|---| | `OrderType.Market` | `market` | Execute at market price | | `OrderType.Limit` | `limit` | Execute at limit price or better | | `OrderType.Stop` | `stop` | Trigger at stop price | | `OrderType.StopLimit` | `stop_limit` | Trigger at stop price, then submit limit order | ## `TimeInForce` [#timeinforce] How long an order remains active. | Enum member | Value | Meaning | |---|---|---| | `TimeInForce.Day` | `day` | End of trading day | | `TimeInForce.GoodTillCanceled` | `gtc` | Good til canceled | | `TimeInForce.ImmediateOrCancel` | `ioc` | Immediate or cancel | | `TimeInForce.FillOrKill` | `fok` | Fill or kill | ## `LegType` [#legtype] Used in options/multi-leg `legs[]`. | Enum member | Value | Meaning | |---|---|---| | `LegType.Option` | `option` | Options contract leg | | `LegType.Equity` | `equity` | Equity/stock leg | ## `PositionEffect` [#positioneffect] Used in options legs to indicate whether the trade opens or closes a position. | Enum member | Value | Meaning | |---|---|---| | `PositionEffect.Open` | `open` | Open a position | | `PositionEffect.Close` | `close` | Close a position | ## `OrderDirection` [#orderdirection] Primarily used in options pricing/context (net debit vs net credit). | Enum member | Value | Meaning | |---|---|---| | `OrderDirection.Debit` | `debit` | Net debit | | `OrderDirection.Credit` | `credit` | Net credit | | `OrderDirection.Even` | `even` | Zero-net limit order | ## `TriggerUnit` [#triggerunit] Used by `takeProfit` and `stopLoss` on simple Buy entries. | Enum member | Value | Meaning | |---|---|---| | `TriggerUnit.Price` | `$` | Absolute exit price | | `TriggerUnit.Percent` | `%` | Percentage move from the entry reference price | ## `TradeLinkParam` [#tradelinkparam] Advanced enum that maps to the short query keys used by Trade Links and Trade It URL parsing. > **Note** > > You usually do **not** need this when using the React SDK, but it can be helpful for debugging or hybrid Trade Link + SDK integrations. | Enum member | Value | Meaning | |---|---|---| | `TradeLinkParam.TradeType` | `tt` | Trade type | | `TradeLinkParam.Action` | `t` | Trade action | | `TradeLinkParam.Direction` | `dir` | Net debit/credit/even direction | | `TradeLinkParam.OrderType` | `ot` | Order type | | `TradeLinkParam.Amount` | `a` | Trade amount | | `TradeLinkParam.Unit` | `u` | Trade unit | | `TradeLinkParam.LimitPrice` | `lp` | Limit price | | `TradeLinkParam.StopPrice` | `sp` | Stop price | | `TradeLinkParam.TimeInForce` | `tif` | Time in force | | `TradeLinkParam.TakeProfit` | `tp` | Take-profit exit trigger | | `TradeLinkParam.StopLoss` | `sl` | Stop-loss exit trigger | | `TradeLinkParam.UtmReferred` | `ref` | Referral tag | | `TradeLinkParam.Legs` | `legs` | Options legs payload | # Read holdings Source: https://docs.tradeit.app/sdk/holdings Fetch an account's holdings from your server using the user's [OAuth access token](/sdk/authentication) and an `account.id` from [Read accounts](/sdk/accounts). **Scopes:** `brokerage:read tool:execute`. ## Server side: fetch positions [#server-side-fetch-positions] ```js const response = await fetch('https://api.tradeit.app/api/tool/execute', { method: 'POST', headers: { Authorization: `Bearer ${accessToken}`, 'Content-Type': 'application/json', }, body: JSON.stringify({ toolName: 'get_holdings', params: { account_id: accountId }, }), }); if (!response.ok) throw new Error(`Holdings request failed: ${response.status}`); const holdings = await response.json(); ``` **Returns:** [Holding[]](/models/holding). See [Get holdings](/api/get-holdings#example-response) for a sample response. # Platform Integration Source: https://docs.tradeit.app/sdk Connect your users’ brokerages to your app. Read accounts, holdings, and trade history, then let users review and approve trades from your product. Embed the Trade It Portal with two modes: **Onboarding** for a user’s first visit, then **Connection** whenever they need to add or reconnect a brokerage. Users own their brokerage connections and delegate access to your app. ## Build with the AI Skill [#build-with-the-ai-skill] Install the [Trade It Skill](https://github.com/trade-it-inc/skills) in your project: ```bash npx skills add trade-it-inc/skills ``` Then give your AI coding client this prompt: ```text Use the $trade-it-skill to integrate Trade It into this platform. Read https://docs.tradeit.app/sdk and its linked guides first. Use our existing framework, authentication, and database. Use POST /api/portal with Basic client credentials for the first visit: put redirect_uri, state, PKCE, and optional email_hint in oauth_options. This opens the Trade It Portal in Onboarding mode: an access overview, sign-in, and brokerage connection in one modal. Supply email_hint to start OTP, or omit it to offer social and email sign-in. Set up server-side PKCE/state validation, the onAuthorization code exchange, and per-user token storage and refresh. For subsequent connections, call the same endpoint with the user’s saved Bearer access token and omit oauth_options. Refresh expired tokens first. Use connect_options to customize the portal in either mode. Keep the client secret and OAuth tokens on the server. Add an account selector and holdings for the selected account. Add trade history using the REST API. Use @trade-it/react for the trade review modal. Require explicit user approval before placing any live trade. Tell me which callback URL to register and which environment variables to set. I will supply credentials through the environment, not this chat. Verify OTP, code exchange, refresh, and reconnect paths. ``` ## 1. Create your organization and get credentials [#_1-create-your-organization-and-get-credentials] 1. Sign in to [Trade It](https://tradeit.app) and open [Organizations](https://tradeit.app/partner). Create your organization with a name, logo URL, and website. 2. Register a redirect URI for each environment. For Onboarding mode, its origin must match the website opening it. 3. Complete checkout and save your **Client ID** and **Client Secret** on your server. The secret is shown only once. ![Partner portal settings screen](https://images.tradeit.app/docs/partner_portal_settings.png) Organization details are editable at any time from the partner portal ## 2. Integrate the Trade It Portal [#_2-integrate-the-trade-it-portal] The Trade It portal is a drop-in modal that explains your app’s access, signs the user in, and connects their first brokerage. Start by hosting the portal in [Onboarding mode](/sdk/onboarding). ![The Trade It Portal’s first step, showing your app’s access, security, and privacy information.](https://images.tradeit.app/docs/onboarding_info_half.png) > **Tokens** > > The portal emits an access and refresh token for each user. Save these and use them to interact with the user's brokerage data. > **Prefer a custom sign-in experience?** > > The [OAuth guide](/sdk/authentication) explains how to use redirects and handle authorization in your own onboarding flow. ## 3. Build the experience [#_3-build-the-experience] That's it! Once users are connected, you're ready to interact with their accounts! Use these guides to understand each capability: | Guide | What you will build | | --- | --- | | [Read accounts](/sdk/accounts) | Show the user’s accounts and let them choose one. | | [Read holdings](/sdk/holdings) | Display positions for the selected account. | | [Read trade history](/sdk/trade-history) | Fetch the user’s recent trades. | | [Place trades](/sdk/trades) | Use the React trade modal or submit user-approved orders through your server. | | [Webhooks](/sdk/webhooks) | Receive account, connection, and trade updates. | Refer to [API](/api) for sample requests/responses. ## 4. Manage subsequent connections [#_4-manage-subsequent-connections] When a user wants to add or reconnect a brokerage, use the portal in [Connection mode](/sdk/connect). The user goes straight to brokerage connection, without signing in or approving access again. ![The Trade It Portal’s first step, showing your app’s access, security, and privacy information.](https://images.tradeit.app/docs/portal_connection_mode_half.png) | Mode | Authorization header | Experience | | --- | --- | --- | | Onboarding · First visit | `Basic` client credentials | Sign in, authorize, connect | | Connection · Later visits | `Bearer` user access token | Connect directly | For integration help, [contact us](https://tradeit.app/contact). # Onboarding mode Source: https://docs.tradeit.app/sdk/onboarding Start each user with the Trade It Portal in **Onboarding mode**. It explains your app’s access, handles sign-in, and connects their first brokerage without leaving your app. After saving their tokens, use the same portal in [Connection mode](/sdk/connect) to add or reconnect brokerages. ![Your app’s access, security, privacy, and Continue button.](https://images.tradeit.app/docs/onboarding_info.png?v=2) Review access ![Six code boxes, resend, and an option to correct the email address.](https://images.tradeit.app/docs/onboarding_otp.png?v=2) Verify account ![Brokerage selection and the option to use connected accounts.](https://images.tradeit.app/docs/onboarding_connect.png?v=2) Connect a brokerage ![Your backend creates an onboarding URL with an optional email hint. Your app opens the Trade It modal. The user reviews access and signs in. Your app receives an authorization event and sends the code to your backend. The modal opens brokerage connection.](/images/sdk/onboarding/flow.svg) ## Configure your client [#configure-your-client] **Your backend** · One-time setup [Create your organization and save its credentials](/sdk#_1-create-your-organization-and-get-credentials). Register a redirect URI on the website where you will open the portal, then set these server environment variables: ```dotenv TRADE_IT_CLIENT_ID=your_client_id TRADE_IT_CLIENT_SECRET=your_client_secret TRADE_IT_REDIRECT_URI=https://app.example.com/auth/tradeit/callback ``` > **Match your website’s origin** > > The `redirect_uri` must use the same scheme, hostname, and port as the website opening the portal. Register a separate URI for each test or production origin. Use HTTPS in production; HTTP localhost is supported for development. The portal sends its authorization event to this origin without navigating to the URI. ## Create Portal URL [#create-portal-url] **Your backend** · `POST https://api.tradeit.app/api/portal` Use your Client ID and Client Secret from step 1 with Basic authentication. Put authorization settings in `oauth_options` and optional brokerage settings in `connect_options`. ```js import { randomBytes, createHash } from 'node:crypto'; // Bind this attempt to your user and protect the code exchange with PKCE. const state = randomBytes(32).toString('base64url'); const verifier = randomBytes(32).toString('base64url'); const credential = Buffer.from(`${encodeURIComponent(clientId)}:${encodeURIComponent(clientSecret)}`).toString('base64'); // Create the portal URL for this user. const portal = await fetch('https://api.tradeit.app/api/portal', { method: 'POST', headers: { Authorization: `Basic ${credential}`, 'Content-Type': 'application/json' }, body: JSON.stringify({ oauth_options: { redirect_uri: redirectUri, state, code_challenge: createHash('sha256').update(verifier).digest('base64url'), email_hint: user.email, // Optional. Omit to show all sign-in options. name: user.name, // Optional. Personalizes the experience. }, connect_options: {}, // Optional. Customizes brokerage selection. }), }).then(res => res.json()); ``` Pass `portal.url` to your frontend. Retain the state, verifier, issuer, token endpoint, and expiry on your server for this user’s authorization attempt. Keep the Client Secret on your server. ### Request details [#request-details] | Field | Use | | --- | --- | | `oauth_options` | Required with Basic authentication. The client ID comes from your credentials. | | `oauth_options.email_hint` | Optional. Starts email OTP when supplied. Omit to show social and email sign-in options. Users can switch methods or correct the address. | | `oauth_options.name` | Optional. The user’s name. | | `connect_options.brokerage_code` | Optional. A [brokerage code](/brokerages) to open directly. Cannot be combined with `brokerage_filter`. | | `connect_options.brokerage_filter` | Optional. `supports` (all required capabilities), `include` (brokerage codes), and `exclude` (brokerage codes). Exclusions take precedence. | | `oauth_options.redirect_uri` | Your exact registered URI, on the same origin as the website opening the portal. The portal stays open instead of redirecting. | | `oauth_options.state`, `oauth_options.code_challenge` | Generated above. State binds the attempt; PKCE protects the code exchange. | > **Portal URL lifetime** > > The URL expires after **30 minutes**. Keep the returned `issuer` and `tokenEndpoint` on your server for step 4. #### Sign-in options [#sign-in-options] > **Choose the first sign-in screen** > > Supply `oauth_options.email_hint` to start with a one-time email code. Omit it to show all social and email sign-in options. Users can switch methods or correct their address in the portal. ```json { "oauth_options": { "redirect_uri": "https://app.example.com/auth/tradeit/callback", "state": "your_random_state", "code_challenge": "your_pkce_challenge", "email_hint": "john@test.com", "name": "John Smith" } } ``` ![Email verification screen with six code boxes, resend, and other sign-in options.](https://images.tradeit.app/docs/onboarding_otp.png?v=2) With email_hint · Email code ![Sign-in choices for Google, Apple, X, Discord, and email.](https://images.tradeit.app/docs/onboarding_social_sign_in.png?v=3) Without email_hint · Sign-in choices #### Connection options [#connection-options] Choose which brokerages users can choose from. These settings have the same behavior as the [Connection mode options](/sdk/connect#request-fields). ##### Full list [#full-list] Omit `connect_options`, or pass an empty object, to show every active brokerage: ```json { "connect_options": {} } ``` ![Full list of active brokerages and the option to use connected accounts.](https://images.tradeit.app/docs/onboarding_connect.png?v=2) ##### Filtered list [#filtered-list] Use `brokerage_filter` to filter by capabilities (`supports`) or brokerage codes (`include` and `exclude`). For example, show options-supporting brokerages except Tastytrade: ```json { "connect_options": { "brokerage_filter": { "supports": ["options"], "exclude": ["tastytrade"] } } } ``` > **Brokerage filter behavior** > > The picker omits inactive brokerages. If nothing matches, it shows every active brokerage. Filters customize the picker; they do not change the access your app requests. ![Brokerage picker showing a filtered list of brokerages.](https://images.tradeit.app/docs/onboarding_connect_exclude.png?v=1) ##### One targeted brokerage [#one-targeted-brokerage] Use `brokerage_code` to skip the picker and open one brokerage’s connection flow directly. Choose a code from the [brokerage list](/brokerages): ```json { "connect_options": { "brokerage_code": "charles_schwab" } } ``` Use either `brokerage_code` or `brokerage_filter` in a request, not both. ![Connection flow opened directly for Charles Schwab.](https://images.tradeit.app/docs/onboarding_connect_schwab.png?v=1) ## Open the portal [#open-the-portal] **Your frontend** · `npm install @trade-it/react` Open the portal on your front end. After the user consents to share data and signs in, their OAuth authorization code is emitted by the modal as an event. Use `onAuthorization` to forward this code to your backend and exchange it for the user's access & refresh tokens. ```tsx import { TradeItModal, useTradeIt } from '@trade-it/react'; function ConnectBrokerageButton() { const tradeIt = useTradeIt({ // Save access on your server while the modal opens brokerage selection. onAuthorization: async authorization => { const saved = await fetch('/api/tradeit/complete', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(authorization), }); if (!saved.ok) throw new Error('Could not save access'); }, }); async function connect() { const response = await fetch('/api/tradeit/portal', { method: 'POST' }); if (!response.ok) throw new Error('Could not start onboarding'); const { url } = await response.json(); tradeIt.openConnect({ launch: { mode: 'connect', url } }); } return ( <> {tradeIt.modalProps && } ); } ``` > **Authorization events instead of redirects** > > In Onboarding mode, the portal sends the authorization code through `onAuthorization` instead of opening `redirect_uri`, so the modal can continue straight to brokerage connection. See [OAuth 2.0 Best Current Practices](https://www.rfc-editor.org/rfc/rfc9700.html#section-4.17) for more info on this approach. Your registered `redirect_uri` still determines the receiving website’s origin and is used when exchanging the code for tokens. ## Save tokens [#save-tokens] **Your backend** · `POST /api/tradeit/complete` Use the token endpoint returned in step 2, the same PKCE `verifier`, and the registered `redirectUri`. `authorization` is the event received by `onAuthorization`. ```js const tokens = await fetch(tokenEndpoint, { method: 'POST', headers: { Authorization: `Basic ${credential}`, 'Content-Type': 'application/x-www-form-urlencoded', }, body: new URLSearchParams({ grant_type: 'authorization_code', code: authorization.code, code_verifier: verifier, redirect_uri: redirectUri, }), }).then(res => res.json()); ``` > **Bind tokens to the correct user** > > Before exchanging, validate the event’s state and issuer against the attempt saved for your signed-in user, and consume that attempt once. Protect your endpoints with authentication and CSRF checks. Save `tokens` securely for that user, then resolve `onAuthorization`; keep codes and tokens out of logs. > **Token Expired?** > > Refresh access with the saved `tokenEndpoint` using the [refresh-token flow](/sdk/authentication#refresh-expired-tokens-server-side). > **Adding another brokerage?** > > Use the [portal in Connection mode](/sdk/connect) with the user’s saved OAuth access token. Call the same `POST /api/portal` endpoint with Bearer authentication and omit `oauth_options`. There’s no need to repeat onboarding while your app’s authorization is valid. # Read trade history Source: https://docs.tradeit.app/sdk/trade-history Fetch the user's recent trades from your server using their [OAuth access token](/sdk/authentication). ## Server side: fetch trade history [#server-side-fetch-trade-history] ```js const response = await fetch('https://api.tradeit.app/api/tool/execute', { method: 'POST', headers: { Authorization: `Bearer ${accessToken}`, 'Content-Type': 'application/json', }, body: JSON.stringify({ toolName: 'get_trades', params: { limit: 20 }, }), }); if (!response.ok) throw new Error(`Trade history request failed: ${response.status}`); const history = await response.json(); ``` **Returns:** a page of [Trade[]](/models/trade) in `trades`. See [Get trades](/api/get-trades#example-response) for a sample response and pagination. # Place Trades Source: https://docs.tradeit.app/sdk/trades Once a user has [signed in](/sdk/authentication) and [connected a brokerage](/sdk/connect), choose how to present and submit orders: - **Client side (embedded modal):** use the React trade modal for order entry, review, and user approval. Your server supplies its authenticated session URL. - **Server side (your own UI):** use the REST API to prepare an order, show it to the user, and submit it after explicit approval. See [Trade through your server](#trade-through-your-server). The embedded modal requires `asset:read brokerage:read trade:write`. Direct API trading requires `trade:write tool:execute`; add `trade:read` to read order status. ## How It Works [#how-it-works] 1. Your server requests an authenticated trade session URL. 2. Your client-side app opens the trade modal via the SDK. 3. You pass a trade configuration (simple or options/multi-leg). 4. The user confirms, sending the order to their brokerage. ## Server side: Request a Trade Session URL [#server-side-request-a-trade-session-url] Call Trade It's API server-side to get a url to the trade portal. The URL is pre-authenticated so the user does not need to log in. ### Request [#request] ```http POST https://api.tradeit.app/api/session/url Content-Type: application/json Authorization: Bearer { "target": "trade" } ``` ### Response [#response] ```json { "url": "https://tradeit.app/t/[ticker]?ti_token=ti:...&embedded=1", "expiresAt": "2026-02-27T19:35:12.000Z", "feature": "trade", "placeholder": "[ticker]" } ``` Trade It returns an authenticated trade URL template. > **Note** > > Request a fresh template immediately before opening the modal. It expires after 30 minutes and should not be cached for reuse. Implement `POST /api/tradeit/trade` on your server using this request. Require your platform session and CSRF protection, load and refresh the current user's Trade It token, and return the session URL response. Keep OAuth tokens on the server and exclude session URLs from logs and analytics. ## Client side: Open the Trade Modal (Simple Trade) [#client-side-open-the-trade-modal-simple-trade] ```tsx import { useState } from 'react'; import { LegType, OrderDirection, OrderType, PositionEffect, TimeInForce, TriggerUnit, TradeAction, TradeItModal, TradeType, TradeUnit, } from '@trade-it/react'; function BuyButton() { const [open, setOpen] = useState(false); const [tradeUrl, setTradeUrl] = useState(null); async function openTrade() { const res = await fetch('/api/tradeit/trade', { method: 'POST' }); if (!res.ok) throw new Error('Unable to open the trade modal'); const data = await res.json(); setTradeUrl(data.url); setOpen(true); } return ( <> {tradeUrl && ( )} ); } ``` > **Note** > > The same modal supports options orders too. Pass a multi-leg config and Trade It opens directly into the options workflow with details prefilled. ## Examples [#examples] Use these examples of common scenarios as jumping off point. ### Example 1: Buy in Dollars [#example-1-buy-in-dollars] *Buy shares of an asset.* ```tsx tradeIt.openTrade({ launch: { mode: 'trade', url: tradeUrl, config: { tradeType: TradeType.Simple, ticker: 'AAPL', action: TradeAction.Buy, amount: 100, unit: TradeUnit.Dollars, orderType: OrderType.Market, takeProfit: { value: 10, unit: TriggerUnit.Percent }, stopLoss: { value: 5, unit: TriggerUnit.Percent }, }, }, }); ``` ![Buy order screen inside the Trade It trade modal](https://images.tradeit.app/docs/trade_buy.png) Buy $100 of Apple stock. ### Example 2: Sell in Shares with Stop-Limit [#example-2-sell-in-shares-with-stop-limit] *Sell shares while setting both stop and limit prices.* ```tsx tradeIt.openTrade({ launch: { mode: 'trade', url: tradeUrl, config: { tradeType: TradeType.Simple, ticker: 'AAPL', action: TradeAction.Sell, amount: 10, unit: TradeUnit.Shares, orderType: OrderType.StopLimit, stopPrice: 260, limitPrice: 250, }, }, }); ``` ![Sell order screen inside the Trade It trade modal](https://images.tradeit.app/docs/trade_sell.png) Sell 10 shares of Apple with stop and limit prices set. ### Example 3: Multi-Leg Options [#example-3-multi-leg-options] *Open a debit spread with prefilled legs and pricing.* ```tsx tradeIt.openTrade({ launch: { mode: 'trade', url: tradeUrl, config: { tradeType: TradeType.MultiLeg, ticker: 'MSFT', direction: OrderDirection.Debit, orderType: OrderType.Limit, limitPrice: 1.25, timeInForce: TimeInForce.GoodTillCanceled, legs: [ { type: LegType.Option, action: TradeAction.Sell, positionEffect: PositionEffect.Open, occ: '270617C00390000', quantity: 5, }, { type: LegType.Option, action: TradeAction.Buy, positionEffect: PositionEffect.Open, occ: '270617C00420000', quantity: 5, }, ], }, }, }); ``` ![Multi-leg options order screen inside the Trade It trade modal](https://images.tradeit.app/docs/trade_options.png) Open a Microsoft debit spread with prefilled legs. ## Config Parameters (`launch.config`) [#config-parameters-launch-config] Configure a particular trade using the parameters below: > **TIP** > > See all enum values on [SDK Enums Reference](/sdk/enums). | Field | Meaning | Type / Enum | Used In | Default | Notes | |---|---|---|---|---|---| | `ticker` | Asset symbol | `string` | `simple` `options` | None | Required. Example: `AAPL`, `BTC-USD` | | `tradeType` | Trade type | `TradeType` | `simple` `options` | `TradeType.Simple` | Use `TradeType.MultiLeg` for options/multi-leg | | `action` | Buy or sell | `TradeAction` | `simple` | `TradeAction.Buy` | Simple trades only | | `amount` | Trade amount | `number` | `simple` | `100` | Interpreted by `unit` | | `unit` | Amount unit | `TradeUnit` | `simple` | `TradeUnit.Dollars` | `Dollars` or `Shares` | | `orderType` | Order type | `OrderType` | `simple` `options` | `OrderType.Market` | `market`, `limit`, `stop`, `stop_limit` | | `limitPrice` | Limit price | `number` | `simple` `options` | None | Used for `limit` / `stop_limit` | | `stopPrice` | Stop trigger price | `number` | `simple` `options` | None | Used for `stop` / `stop_limit` | | `timeInForce` | Order duration | `TimeInForce` | `simple` `options` | `TimeInForce.Day` | `Day`, `GoodTillCanceled`, `ImmediateOrCancel`, `FillOrKill` | | `direction` | Net options price direction | `OrderDirection` | `options` | None | Use `Debit`, `Credit`, or `Even`; required for priced multi-leg orders. | | `takeProfit` | Attached take-profit exit | `TradeItExitTrigger` | `simple` Buy | None | Closes the resulting long position at a gain. Use `TriggerUnit.Price` or `TriggerUnit.Percent`. Support varies by brokerage. | | `stopLoss` | Attached stop-loss exit | `TradeItExitTrigger` | `simple` Buy | None | Closes the resulting long position at a loss. Use `TriggerUnit.Price` or `TriggerUnit.Percent`. Support varies by brokerage. | | `legs` | Options leg payload | `TradeItMultiLegTradeLegConfig[]` | `options` | None | Required for options/multi-leg trades | | `legs[].type` | Leg type | `LegType` | `options` | None | `Option` or `Equity` | | `legs[].action` | Leg action | `TradeAction` | `options` | None | `Buy` or `Sell` | | `legs[].positionEffect` | Position effect | `PositionEffect \| null` | `options` | `null` | Usually `Open` / `Close`; `null` for equity legs | | `legs[].occ` | OCC contract string | `string \| null` | `options` | None | Required for option legs | | `legs[].quantity` | Leg quantity | `number` | `options` | `1` | Contracts for options, shares for equity legs | ## Trade through your server [#trade-through-your-server] Use this path if your platform owns the order form and review screen. All API calls use the current user's OAuth token on your server. 1. [Read accounts](/sdk/accounts) and have the user select the account. 2. Prepare an order with [Create trade](/api/create-trade) or [Create options trade](/api/create-options-trade). 3. Display the returned order's account, symbol, side, quantity, prices, order type, and any option legs. Require explicit approval for that specific order. 4. In a separate authenticated, CSRF-protected confirmation handler, submit the approved draft using [Execute trade](/api/execute-trade). 5. Read [Get trades](/api/get-trades) for order status; an accepted order may not have filled. Offer [Cancel trade](/api/cancel-trade) where eligible. > **Check automatic execution before creating an order** > > Accounts configured for automatic execution may submit an order during `create_trade` or `create_options_trade`. Use accounts with automatic execution disabled for a draft-first flow. If automatic execution is enabled, obtain explicit approval of the exact order before the create call. Always inspect the returned status; do not execute an already submitted order. For example, prepare a limit order from your server with the user's selected `account_id`: ```json { "toolName": "create_trade", "params": { "symbol": "AAPL", "account_id": 304, "buy_or_sell": "buy", "amount": 1, "unit": "shares", "order_type": "limit", "limit_price": 150, "time_in_force": "day" } } ``` Send this JSON to `POST https://api.tradeit.app/api/tool/execute` with `Authorization: Bearer `. Replace `304` with the selected Trade It account ID and the sample order fields with the user's intended order. After review and approval, the confirmation handler sends a **separate** request to the same endpoint: ```json { "toolName": "execute_trade", "params": { "trade_id": 842 } } ``` Replace `842` with the returned draft's `id`. Bind the saved draft and approval to the current platform user; re-review if any order details change. Prevent duplicate confirmation requests and check order status before retrying a submission after a network timeout. # Webhooks Source: https://docs.tradeit.app/sdk/webhooks Trade It can notify you via webhook when events like trade fills and account connections happen. Up to 5 endpoints per organization can be configured at **Organizations → Webhooks**. Events cover your organization's active members, and each endpoint only receives the event types it subscribes to. ![Partner portal Webhooks tab with one endpoint, its event log, and the payload and delivery attempt of an ACCOUNT event](https://images.tradeit.app/docs/webhooks_overview.png) An endpoint, its event log, and the payload and attempts of a delivered event. ## Payload [#payload] Every event is a JSON `POST` with the same envelope: ```json { "id": "0a67c0b8-57ae-4cdf-ab8b-5b249e83c100", "type": "TRADE_UPDATED", "created_at": "2026-10-07T14:31:12.000Z", "data": {} } ``` | Field | Description | | --- | --- | | `id` | Unique event ID, also sent as the `TradeIt-Event-Id` header. Retries reuse it, so deduplicate on it. | | `type` | One of the [event types](#event-types) below. | | `created_at` | When the event happened, as an ISO 8601 timestamp. | | `data` | Snapshot of the [Account](/models/account) or [Trade](/models/trade) the event is about, taken when it happened. Private brokerage identifiers like `external_id` are left out. | ## Event types [#event-types] ### ACCOUNT_ADDED [#account-added] Sent when a brokerage account is linked. Connecting a brokerage sends one for each of its accounts, and a later sync sends one for any new account the brokerage reports. **Data:** [Account](/models/account) ```json { "id": "5f0c7e7a-3b0e-4a43-9a5e-1c2f7d8e9b10", "type": "ACCOUNT_ADDED", "created_at": "2026-10-07T14:30:00.000Z", "data": { "id": 304, "connection_id": 395, "name": "Robinhood x1234", "balance": { "amount": 15420.5, "currency": "USD" }, "cash": { "amount": 3420.5, "currency": "USD" }, "buying_power": { "amount": 3420.5, "currency": "USD" }, "synced_at": "2026-10-07T14:30:00.000Z", "holdings_synced_at": null, "trades_synced_at": null, "created_at": "2026-10-07T14:30:00.000Z", "updated_at": "2026-10-07T14:30:00.000Z" } } ``` ### ACCOUNT_DELETED [#account-deleted] Sent when an account is removed, either because the user deleted its brokerage connection or because the brokerage removed the account from the connection. **Data:** [Account](/models/account) as it was just before removal > **Note** > > The account's `id` stops working in API requests. ```json { "id": "c3d1a9e2-7f4b-4c8e-b1a6-2e9f0d7c5b34", "type": "ACCOUNT_DELETED", "created_at": "2026-10-09T18:02:44.000Z", "data": { "id": 304, "connection_id": 395, "name": "Robinhood x1234", "balance": { "amount": 15873.12, "currency": "USD" }, "cash": { "amount": 2412.08, "currency": "USD" }, "buying_power": { "amount": 2412.08, "currency": "USD" }, "synced_at": "2026-10-09T17:45:10.000Z", "holdings_synced_at": "2026-10-09T17:45:12.000Z", "trades_synced_at": "2026-10-09T06:00:03.000Z", "created_at": "2026-10-07T14:30:00.000Z", "updated_at": "2026-10-09T17:45:12.000Z" } } ``` ### ACCOUNT_DISCONNECTED [#account-disconnected] Sent when an account's brokerage connection breaks, usually because the brokerage revoked access or the login expired. Trades and syncs for the account fail until the user reconnects the brokerage in Trade It. **Data:** [Account](/models/account) > **Note** > > Each account on the connection gets its own event, so a login with three accounts sends three. ```json { "id": "8b2e4f61-0d3a-4e7c-9f15-6a8c2b4d1e90", "type": "ACCOUNT_DISCONNECTED", "created_at": "2026-10-08T03:12:09.000Z", "data": { "id": 304, "connection_id": 395, "name": "Robinhood x1234", "balance": { "amount": 15873.12, "currency": "USD" }, "cash": { "amount": 2412.08, "currency": "USD" }, "buying_power": { "amount": 2412.08, "currency": "USD" }, "synced_at": "2026-10-07T21:00:04.000Z", "holdings_synced_at": "2026-10-07T21:00:06.000Z", "trades_synced_at": "2026-10-07T06:00:03.000Z", "created_at": "2026-10-07T14:30:00.000Z", "updated_at": "2026-10-07T21:00:06.000Z" } } ``` ### ACCOUNT_RECONNECTED [#account-reconnected] Sent when the user reconnects a brokerage, whether or not the connection had broken. Each account on the connection gets its own event. **Data:** [Account](/models/account) > **Note** > > Accounts the brokerage reports for the first time arrive as `ACCOUNT_ADDED` instead. ```json { "id": "e47a0c95-2b6d-4f13-8c7e-91d5a3f6b208", "type": "ACCOUNT_RECONNECTED", "created_at": "2026-10-08T15:20:31.000Z", "data": { "id": 304, "connection_id": 395, "name": "Robinhood x1234", "balance": { "amount": 15873.12, "currency": "USD" }, "cash": { "amount": 2412.08, "currency": "USD" }, "buying_power": { "amount": 2412.08, "currency": "USD" }, "synced_at": "2026-10-07T21:00:04.000Z", "holdings_synced_at": "2026-10-07T21:00:06.000Z", "trades_synced_at": "2026-10-07T06:00:03.000Z", "created_at": "2026-10-07T14:30:00.000Z", "updated_at": "2026-10-07T21:00:06.000Z" } } ``` ### TRADE_UPDATED [#trade-updated] Sent when a trade reaches a final status: `complete`, `canceled`, `failed`, or `disconnected`, which means the brokerage connection broke before the order resolved. **Data:** [Trade](/models/trade) without the nested `asset`; use `asset_id` to look it up > **Note** > > Partial fills and other in-progress changes are not sent. ```json { "id": "0a67c0b8-57ae-4cdf-ab8b-5b249e83c100", "type": "TRADE_UPDATED", "created_at": "2026-10-07T14:31:12.000Z", "data": { "id": 842, "user_id": 1, "account_id": 304, "asset_id": 88, "source": "api", "type": 0, "action": "buy", "direction": null, "order_type": "limit", "time_in_force": "day", "status": "complete", "total_units": 4, "filled_units": 4, "canceled_units": 0, "limit_price": { "amount": 250, "currency": "USD" }, "stop_price": null, "take_profit": null, "stop_loss": null, "notional_amount": null, "execution_price": { "amount": 248.12, "currency": "USD" }, "fee": null, "legs": null, "event": null, "error_message": null, "analysis": null, "image_url": null, "placed_at": "2026-10-07T14:30:58.000Z", "executed_at": "2026-10-07T14:31:10.000Z", "created_at": "2026-10-07T14:30:41.000Z", "updated_at": "2026-10-07T14:31:12.000Z" } } ``` ## Verify the signature [#verify-the-signature] Requests include `TradeIt-Signature: t=,v1=` and `TradeIt-Event-Id`. Compute HMAC-SHA256 with your endpoint's complete `whsec_…` secret over `${timestamp}.${rawBody}`. Compare signatures using a constant-time comparison and reject timestamps more than five minutes from your server's clock. Verify before parsing or acting on the event. ```ts import { createHmac, timingSafeEqual } from 'node:crypto'; export function verifyWebhook(rawBody: Buffer, header: string, secret: string) { const parts = header.split(','); const timestampText = parts.find(part => part.startsWith('t='))?.slice(2) ?? ''; const supplied = parts.find(part => part.startsWith('v1='))?.slice(3) ?? ''; const timestamp = Number(timestampText); if (!/^\d+$/.test(timestampText) || !Number.isSafeInteger(timestamp) || Math.abs(Date.now() / 1000 - timestamp) > 300 || !/^[a-f0-9]{64}$/.test(supplied)) throw new Error('Invalid webhook signature'); const expected = createHmac('sha256', secret).update(`${timestampText}.`).update(rawBody).digest(); if (!timingSafeEqual(expected, Buffer.from(supplied, 'hex'))) throw new Error('Invalid webhook signature'); return JSON.parse(rawBody.toString('utf8')); } ``` > **Note** > > Configure your framework to provide the original request bytes. Re-serializing parsed JSON changes the signed bytes. Keep your clock synchronized and never expose the signing secret in frontend code. ## Delivery and retries [#delivery-and-retries] Persist the event to your own durable inbox, then return a 2xx response promptly. Requests time out after five seconds. Every failed HTTP response, redirect, timeout, or network error retries after 1 minute, 5 minutes, and 30 minutes, for four attempts total. Changes are queued as they are processed; delivery timing depends on queue backlog. > **Note** > > Delivery is **at least once** and may arrive out of order. Deduplicate using `event.id` across retries, which keep the original event body and ID and receive a fresh signature timestamp. Pausing or removing an endpoint stops its queued deliveries; requests already in flight may finish. Secret rotation immediately affects future attempts, so update your receiver promptly. > **Note** > > Only public HTTPS hostnames are supported, and redirects are not followed. ## Event logs [#event-logs] The portal's Events list keeps 30 days of events sent to your endpoints, filterable by status and event type. Select an event to inspect its payload and HTTP attempt history, including response codes, response excerpts, and durations. > **Note** > > Removing an endpoint also removes its event history. # MCP Tools Source: https://docs.tradeit.app/tools This page documents all tools exposed by the TradeIt MCP server. Each tool includes its full parameter schema. ## `create_trade` [#create_trade] Create a trade order for user to review. The trade will not execute until the user confirms and execute_trade is called with the trade ID. You may enable auto-execution by setting "Always Confirm" to false in the Trade It dashboard. If no account is provided, your default account is used. If no order_type is provided, it defaults to a market order. ORDER TYPES: - **market** (default) -> Executes immediately at current market price. No price fields required. - **limit** -> Executes only at a specific limit_price or better. Requires limit_price. - **stop** -> Triggers a market order when stop_price is reached. Requires stop_price. - **stop_limit** -> Triggers a limit order when stop_price is reached. Requires BOTH stop_price and limit_price. TIME IN FORCE (if omitted, brokerage default is used): - **day** -> Expires at end of trading day - **gtc** -> Good til canceled EXIT CRITERIA: - **take profit** -> Closes the position at a certain price or percent above the entry. - **stop loss** -> Closes the position at a certain price or percent below the entry. EXAMPLES: - Buy $1000 of Tesla: {symbol: "TSLA", amount: 1000, unit: "dollars", buy_or_sell: "buy"} - Buy $1000 of Tesla, but only if the price drops to $150 or lower: {symbol: "TSLA", amount: 1000, unit: "dollars", buy_or_sell: "buy", order_type: "limit", limit_price: 150} - Sell 10 shares of Apple if the price falls to $140 or lower: {symbol: "AAPL", amount: 10, unit: "shares", buy_or_sell: "sell", order_type: "stop", stop_price: 140} - Buy a share of Apple if it hits $200: {symbol: "AAPL", amount: 1, unit: "shares", buy_or_sell: "buy", order_type: "stop", stop_price: 200} - Buy 10 shares of Apple if the price rises to $140, but don't pay more than $142 per share: {symbol: "AAPL", amount: 10, unit: "shares", buy_or_sell: "buy", order_type: "stop_limit", stop_price: 140, limit_price: 142} - Buy $1000 of Tesla, take profit at +10%, stop loss at -5%: {symbol: "TSLA", amount: 1000, unit: "dollars", buy_or_sell: "buy", take_profit: {value: 10, unit: "%"}, stop_loss: {value: 5, unit: "%"}} - Buy 5 shares of Apple, sell if it reaches $250 or drops to $180: {symbol: "AAPL", amount: 5, unit: "shares", buy_or_sell: "buy", take_profit: {value: 250, unit: "$"}, stop_loss: {value: 180, unit: "$"}} ### Parameters [#parameters] **`symbol`** `string` `required` Ticker symbol of the asset to trade, e.g. TSLA **`amount`** `number` `required` How much to trade: a dollar value when unit is dollars, or a share count when unit is shares. **`unit`** `enum` `required` Whether amount is in dollars or shares. `dollars``shares` **`buy_or_sell`** `enum` `required` Whether to buy or sell the asset. `buy``sell` **`metadata`** `object` Optional context displayed with the draft trade. > **`image_url`** `string` > > > Link to the screenshot or chart the user shared as the source of this trade idea, shown alongside the draft. **`order_type`** `enum` How the order is priced. Omit for a market order. `market``limit``stop``stop_limit` **`limit_price`** `number` Maximum price per share to pay on a buy, or minimum to accept on a sell, in the asset currency. Set for limit and stop_limit orders. **`stop_price`** `number` Price per share, in the asset currency, that triggers the order. Set for stop and stop_limit orders. **`take_profit`** `object` Take-profit exit for Buy entries. Not supported by all brokerages. > **`value`** `number` `required` > > > Exit trigger level > > > **`unit`** `enum` > > > Absolute price ($) or percent from entry price (%). > > > `$``%` **`stop_loss`** `object` Stop-loss exit for Buy entries. Not supported by all brokerages. > **`value`** `number` `required` > > > Exit trigger level > > > **`unit`** `enum` > > > Absolute price ($) or percent from entry price (%). > > > `$``%` **`time_in_force`** `enum` How long the order stays open: day expires at market close, gtc stays open until canceled. Omit to use the brokerage default. `day``gtc``ioc``fok` **`account_id`** `number | string` ID of the brokerage account to trade in, from get_accounts. Omit to use the user's default account. ## `create_options_trade` [#create_options_trade] Create an options trade order with one or more legs (spreads, single options, etc.). Each leg represents a position in the options trade. For option legs, the OCC (Options Clearing Corporation) format is required. OCC FORMAT: The OCC format is a standardized string format: YYMMDD[C|P]STRIKE - YY: 2-digit year (e.g., 24 for 2024) - MM: 2-digit month, zero-padded (e.g., 01 for January) - DD: 2-digit day, zero-padded (e.g., 19 for the 19th) - C or P: Call or Put option - STRIKE: 8-digit strike price (multiplied by 1000, zero-padded, no decimal point) EXAMPLES: - Single call option: Buy 1 SPX call option with strike 1950, expiring Jan 19, 2024 {symbol: "SPX", legs: [{type: "option", action: "buy", position_effect: "open", occ: "240119C00195000", quantity: 1}]} - Put spread: Buy 1 SPX put (strike 1950) and sell 1 SPX put (strike 1900), both expiring Jan 19, 2024 {symbol: "SPX", legs: [ {type: "option", action: "buy", position_effect: "open", occ: "240119P00195000", quantity: 1}, {type: "option", action: "sell", position_effect: "open", occ: "240119P00190000", quantity: 1} ]} - Mixed leg: Buy 100 shares of SPX and buy 1 call option {symbol: "SPX", legs: [ {type: "equity", action: "buy", position_effect: null, occ: null, quantity: 100}, {type: "option", action: "buy", position_effect: "open", occ: "240119C00195000", quantity: 1} ]} ORDER TYPES: - **market** (default) -> Executes immediately at current market price - **limit** -> Executes only at a specific limit_price or better. Requires limit_price. - **stop** -> Triggers a market order when stop_price is reached. Requires stop_price. - **stop_limit** -> Triggers a limit order when stop_price is reached. Requires BOTH stop_price and limit_price. TIME IN FORCE (if omitted, brokerage default is used): - **day** -> Expires at end of trading day - **gtc** -> Good til canceled DIRECTION: - **debit** -> You pay money to open the position (net cost) - **credit** -> You receive money to open the position (net credit) - **even** -> No money changes hands (zero-net limit order) Note: Option legs must have a valid OCC string. Equity legs should have occ set to null. ### Parameters [#parameters-1] **`symbol`** `string` `required` Ticker symbol of the underlying asset, e.g. SPX or TSLA **`legs`** `array of object` `required` Array of trade legs. At least one leg is required. > Each item has: > > > **`type`** `enum` `required` > > > Whether the leg trades an option contract or shares of the underlying. > > > `option``equity` > > > **`action`** `enum` `required` > > > Whether the leg buys or sells. > > > `buy``sell` > > > **`position_effect`** `enum` > > > Whether an option leg opens a new position or closes an existing one. Use null for equity legs. > > > `open``close` > > > **`occ`** `string` `required` > > > Option contract in OCC format without the root symbol: YYMMDD, C or P, then the strike x1000 zero-padded to 8 digits, e.g. "240119C00195000" for the Jan 19, 2024 $195 call. Use null for equity legs. > > > **`quantity`** `number` `required` > > > Number of contracts for options or shares for equity **`direction`** `enum` Net cash flow of a multi-leg spread: debit when paying, credit when receiving, even for zero-net. Set for multi-leg spreads only. `debit``credit``even` **`limit_price`** `number` Net price per spread unit for limit and stop_limit orders, in the asset currency. Use 0 with direction even for a zero-net spread. **`order_type`** `enum` How the order is priced. Omit for a market order. `market``limit``stop``stop_limit` **`stop_price`** `number` Price per share, in the asset currency, that triggers the order. Set for stop and stop_limit orders. **`time_in_force`** `enum` How long the order stays open: day expires at market close, gtc stays open until canceled. Omit to use the brokerage default. `day``gtc``ioc``fok` **`account_id`** `number | string` ID of the brokerage account to trade in, from get_accounts. Omit to use the user's default account. ## `create_trade_link` [#create_trade_link] Create a shareable Trade Link from a trade configuration. This returns a URL that others can review, edit, and execute on their own brokerage. The tool does not create a brokerage draft trade and does not execute any order. Use this for trade alerts, shared trade ideas, or any flow where the recipient should review the trade before placing it. EXAMPLES: - Share a simple stock idea: {config: {ticker: "TSLA", trade_type: 0, action: "buy", amount: 1000, unit: "dollars"}} - Share a two-leg options spread with a $1.25 net-debit limit: {config: {ticker: "MSFT", trade_type: 1, direction: "debit", order_type: "limit", limit_price: 1.25, legs: [ {type: "option", action: "buy", position_effect: "open", occ: "260717C00435000", quantity: 1}, {type: "option", action: "sell", position_effect: "open", occ: "260717C00440000", quantity: 1} ]}} ### Parameters [#parameters-2] **`config`** `object` `required` > **`ticker`** `string` `required` > > > Ticker symbol of the asset, or the underlying for options, e.g. TSLA > > > **`trade_type`** `enum` > > > 0 for a single buy or sell using action, amount, and unit; 1 for an options or multi-leg trade using legs and direction. > > > `0``1` > > > **`action`** `enum` > > > Whether a simple trade buys or sells. Set when trade_type is 0. > > > `buy``sell` > > > **`amount`** `number` > > > How much a simple trade buys or sells,, as dollars or shares per unit. > > > **`unit`** `enum` > > > Whether amount is a dollar value or a share count. > > > `dollars``shares` > > > **`direction`** `enum` > > > Net cash flow of a multi-leg trade: debit when paying, credit when receiving, even for zero-net. > > > `debit``credit``even` > > > **`legs`** `array of object` > > > Legs of an options or multi-leg trade. Set when trade_type is 1. > > > > Each item has: > > > > > > **`type`** `enum` `required` > > > > > > Whether the leg trades an option or the underlying stock. > > > > > > `option``equity` > > > > > > **`action`** `enum` `required` > > > > > > Whether the leg buys or sells. > > > > > > `buy``sell` > > > > > > **`position_effect`** `enum` `required` > > > > > > Whether the leg opens or closes a position. > > > > > > `open``close` > > > > > > **`occ`** `string` `required` > > > > > > OCC option contract symbol, e.g. 260717C00435000. Null for stock legs. > > > > > > **`quantity`** `number` `required` > > > > > > Number of option contracts, or shares for a stock leg. > > > **`order_type`** `enum` > > > How the order is priced. Omit for a market order. > > > `market``limit``stop``stop_limit` > > > **`limit_price`** `number` > > > Limit price in the asset currency for limit and stop_limit orders; per spread unit for multi-leg trades, where 0 with direction even means zero-net. > > > **`stop_price`** `number` > > > Price in the asset currency that triggers stop and stop_limit orders. > > > **`time_in_force`** `enum` > > > How long the order stays open: day expires at market close, gtc stays open until canceled. Omit to use the brokerage default. > > > `day``gtc``ioc``fok` > > > **`take_profit`** `object` > > > Take-profit exit for Buy entries. Not supported by all brokerages. > > > > **`value`** `number` `required` > > > > > > Exit trigger level > > > > > > **`unit`** `enum` > > > > > > Absolute price ($) or percent from entry price (%). > > > > > > `$``%` > > > **`stop_loss`** `object` > > > Stop-loss exit for Buy entries. Not supported by all brokerages. > > > > **`value`** `number` `required` > > > > > > Exit trigger level > > > > > > **`unit`** `enum` > > > > > > Absolute price ($) or percent from entry price (%). > > > > > > `$``%` > > > **`utm_referred`** `string` > > > Referral source label stored with the link for tracking, e.g. a newsletter name. ## `cancel_trade` [#cancel_trade] Cancel a draft or cancellable brokerage order. Draft trades are canceled immediately. Submitted orders are canceled at the brokerage when their current state permits it. Because an order may fill while cancellation is in progress, always use the returned trade status as the latest known state. ### Parameters [#parameters-3] **`trade_id`** `number | string` `required` ID of the trade to cancel, from create_trade, create_options_trade, or get_trades. ## `execute_trade` [#execute_trade] Execute a draft trade order. Call after reviewing a trade to place it on your brokerage. ### Parameters [#parameters-4] **`trade_id`** `number | string` `required` ID of the draft trade to execute, as returned by create_trade or create_options_trade. ## `get_accounts` [#get_accounts] Get all brokerage accounts for the user and link new ones. Use refresh=true to pull fresh balances and buying power from the brokerage when eligible with a Pro plan; otherwise the last synced values are returned. Check each account's synced_at to see how fresh the values are. Currently supported: Charles Schwab, Coinbase, ETrade, Kraken, Moomoo, Public, Robinhood, Tastytrade, TradeStation, TradeStation Paper, Webull ### Parameters [#parameters-5] **`refresh`** `boolean` When true, requests the freshest available brokerage data. Real-time refresh requires a Pro plan and has a 1 minute per-account cooldown. Omit or false to return the last synced data. ## `get_holdings` [#get_holdings] Get holdings for a brokerage account. Use refresh=true to request fresh data when eligible with a Pro plan; otherwise cached daily data is returned. ### Parameters [#parameters-6] **`account_id`** `number | string` `required` ID of the brokerage account to inspect, from get_accounts. **`refresh`** `boolean` When true, requests the freshest available brokerage data. Real-time refresh requires a Pro plan and has a 1 minute per-account cooldown. Omit or false to return the last synced data. ## `get_trades` [#get_trades] Get the user's recent trades with cursor pagination. Use refresh=true to request fresh brokerage sync when eligible with a Pro plan; otherwise existing synced trades are returned. ### Parameters [#parameters-7] **`limit`** `integer` Number of trades to return per page. Omit for 12. **`cursor`** `number | string` Cursor from a previous get_trades response. Pass next_cursor to continue paginating older trades. **`refresh`** `boolean` When true, requests the freshest available brokerage data. Real-time refresh requires a Pro plan and has a 1 minute per-account cooldown. Omit or false to return the last synced data. ## `search_assets` [#search_assets] Gets info on a stock or crypto by ticker symbol or name. Returns latest price and metadata. EXAMPLES: - Look up Tesla: {query: "TSLA"} - Look up Bitcoin: {query: "BTC"} ### Parameters [#parameters-8] **`query`** `string` `required` The ticker symbol or name of the asset # Trade Links Source: https://docs.tradeit.app/trade-links > **Best for:** blogs, newsletters, research providers, creator communities, Discord servers, and any product that wants to add trading without server-side integration work. Trade Links are the fastest way to turn your investing content into an actionable trading experience. If your strength is: - publishing trade ideas - sharing due diligence - running a paid investing community - writing newsletters - building watchlists and research tools ...you probably don't want to spend months building brokerage integrations and trading UIs. Trade Links let you skip all of that and still offer a real trading experience to your followers. Just share a link with the ticker and trade details (buy/sell, amount, order type, etc.), and your users open a prefilled trading page on Trade It. They can sign up, connect a brokerage, and place the trade in seconds. This is the "start today" path. ## Example 1: Simple Buy Order [#example-1-simple-buy-order] ```txt https://tradeit.app/t/AAPL?tt=0&t=buy&a=100&u=dollars&ot=market&tif=day ``` [See it in action](https://tradeit.app/t/AAPL?tt=0&t=buy&a=100&u=dollars&ot=market&tif=day) ![Brokerage selection screen inside the Trade It connection portal](https://images.tradeit.app/docs/tradelink_buy.png) What the user sees when opening this trade link ## Example 2: Bracket Order [#example-2-bracket-order] Attach entry & exit criteria to a simple Buy entry so the resulting long position opens at a given price and closes automatically. Sell and options do not support bracket orders. Support varies by brokerage (see [Supported Brokerages](/brokerages)). ```txt https://tradeit.app/t/AAPL?tt=0&t=buy&a=100&u=dollars&ot=market&tp=10%25&sl=5%25 ``` [See it in action](https://tradeit.app/t/AAPL?tt=0&t=buy&a=100&u=dollars&ot=market&tp=10%25&sl=5%25) ![Trade example with stop/limit prices and take profit+stop loss](https://images.tradeit.app/docs/trade_entry_exit.png) What the user sees when opening this trade link ## Example 3: Multi-leg Option Order [#example-3-multi-leg-option-order] ```txt https://tradeit.app/t/MSFT?tt=1&ot=market&tif=gtc&legs=%5B%7B%22type%22%3A%22option%22%2C%22action%22%3A%22sell%22%2C%22position_effect%22%3A%22open%22%2C%22occ%22%3A%22270617C00390000%22%2C%22quantity%22%3A5%7D%2C%7B%22type%22%3A%22option%22%2C%22action%22%3A%22buy%22%2C%22position_effect%22%3A%22open%22%2C%22occ%22%3A%22270617C00420000%22%2C%22quantity%22%3A5%7D%5D ``` [See it in action](https://tradeit.app/t/MSFT?tt=1&ot=market&tif=gtc&legs=%5B%7B%22type%22%3A%22option%22%2C%22action%22%3A%22sell%22%2C%22position_effect%22%3A%22open%22%2C%22occ%22%3A%22270617C00390000%22%2C%22quantity%22%3A5%7D%2C%7B%22type%22%3A%22option%22%2C%22action%22%3A%22buy%22%2C%22position_effect%22%3A%22open%22%2C%22occ%22%3A%22270617C00420000%22%2C%22quantity%22%3A5%7D%5D) ![Brokerage selection screen inside the Trade It connection portal](https://images.tradeit.app/docs/trade_options.png) What the user sees when opening this trade link ## Trade Link URL Format [#trade-link-url-format] ```txt https://tradeit.app/t/? ``` Example: - Path ticker: `AAPL` (or crypto like `BTC-USD`) - Query params: trade parameters (simple or multi-leg) ## Parameters [#parameters] These are the parameters that define a trade. Some have defaults if omitted. | Field | Meaning | Example | Used In | Default | Notes | |---|---|---|---|---|---| | `tt` | Trade type | `0` | `simple` `options` | `0` | `0 = simple`, `1 = options` | | `t` | Buy or sell | `buy` | `simple` | `buy` | Simple trades use `buy` / `sell` | | `a` | Amount | `100` | `simple` | `100` | Number of dollars or shares | | `u` | Unit | `dollars` | `simple` | `dollars` | `dollars` or `shares` | | `ot` | Order type | `market` | `simple` `options` | `market` | `market`, `limit`, `stop`, `stop_limit` | | `dir` | Net direction | `credit` | `options` | None | Optional for multi-leg debit or credit spreads | | `lp` | Limit price | `150` | `simple` `options` | None | Used for `limit` / `stop_limit` | | `sp` | Stop price | `140` | `simple` `options` | None | Used for `stop` / `stop_limit` | | `tif` | Time in force | `day` | `simple` `options` | `day` | `day`, `gtc`, `ioc`, `fok` | | `tp` | Take profit | `250` or `10%` | `simple` Buy | None | Attached take-profit exit. Bare number is a price; trailing `%` is a move from the entry reference price. Support varies by brokerage. | | `sl` | Stop loss | `180` or `5%` | `simple` Buy | None | Attached stop-loss exit. Bare number is a price; trailing `%` is a move from the entry reference price. Support varies by brokerage. | | `legs` | Options leg payload | `[ { "type": "option", "action": "buy", "position_effect": "open", "occ": "260320C00200000", "quantity": 1 } ]` | `options` | None | URL-encoded JSON array of leg objects (URL-encode before placing in the query string) | | `legs[].type` | Leg type | `option` | `options` | None | `option` or `equity` | | `legs[].action` | Leg action | `buy` | `options` | None | `buy` or `sell` | | `legs[].position_effect` | Position effect | `open` | `options` | `null` | `open`, `close`; `null` for equity legs | | `legs[].occ` | OCC contract string | `260320C00200000` | `options` | None | Required for option legs; `null` for equity legs | | `legs[].quantity` | Leg quantity | `1` | `options` | `1` | Contracts for options, shares for equity legs | ## Integrate into your platform [#integrate-into-your-platform] To sign users in with Trade It, read their accounts and holdings, and embed connection and trading modals, follow the [Platform Integration guide](/sdk). Start with our AI Skill or use the step-by-step manual setup.