Create Trade
Create a bot trade with associated transactions
Create a new bot trade with one or more entry transactions. This endpoint creates both the trade record and all associated transactions atomically in a database transaction. Note: Exit transactions (stop losses, take profits, trailing stops, trim exits) should be added separately using the Add Transactions endpoint after the trade is created.
Endpoint
POST /api/bots/:slug/tradesAuthentication
All requests require bot API key authentication via the x-api-key header.
headers: {
'x-api-key': 'your-bot-api-key'
}Path Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
slug | string | Yes | Bot identifier (alphanumeric, hyphens, underscores only) |
Slug Validation
The slug must match the regex pattern: /^[a-zA-Z0-9_-]+$/
Request Body
{
symbol: string; // Required: Trade symbol
tradeType: string; // Required: Type of trade
status: string; // Required: Trade status
signalAt: string; // Required: ISO timestamp when signal was generated
openedAt?: string; // Optional: ISO timestamp when trade opened
closedAt?: string; // Optional: ISO timestamp when trade closed
expirationDate?: string; // Optional: Expiration date for options/derivatives
netPnl?: string; // Optional: Net profit/loss
errorMessage?: string; // Optional: Error message if trade failed
errorAt?: string; // Optional: ISO timestamp when error occurred
lastUpdateAt?: string; // Optional: ISO timestamp of last update
metadata?: Record<string, unknown>; // Optional: Additional metadata
transactions: Array<{ // Required: Array of transactions
transactionGroup: "entry" | "exit";
exitType?: string; // Required for exit transactions
trimLevel?: number; // Required for trim exits
symbol: string; // Required: Transaction symbol
assetType: string; // Required: "stock", "option", etc.
side: string; // Required: "buy", "sell"
type: string; // Required: Order type
quantity: number; // Required: Quantity
transactionDate: string; // Required: ISO timestamp
stopPrice?: string; // Optional: Stop price
price?: string; // Optional: Limit price
optionType?: string; // Optional: "call" or "put" for options
strikePrice?: string; // Optional: Strike price for options
expirationDate?: string; // Optional: Expiration for options
status?: string; // Optional: Transaction status
filledAt?: string; // Optional: ISO timestamp when filled
filledPrice?: string; // Optional: Fill price
filledQuantity?: string; // Optional: Filled quantity
avgFillPrice?: string; // Optional: Average fill price
broker?: string; // Optional: Broker code
brokerAccountNumber?: string; // Optional: Broker account number
brokerOrderId?: string; // Optional: Broker order ID
brokerParentOrderId?: string; // Optional: Broker parent order ID (for bracket orders)
notes?: string; // Optional: Notes
metadata?: Record<string, unknown>; // Optional: Transaction metadata
}>;
}Request Body Schema
Trade Fields
| Field | Type | Required | Description |
|---|---|---|---|
symbol | string | Yes | Primary symbol for the trade |
tradeType | string | Yes | Type of trade (e.g., "long", "short", "spread") |
status | string | Yes | Trade status (e.g., "open", "closed", "error") |
signalAt | string (ISO timestamp) | Yes | When the trading signal was generated |
openedAt | string (ISO timestamp) | No | When the trade was opened |
closedAt | string (ISO timestamp) | No | When the trade was closed |
expirationDate | string | No | Expiration date for options/derivatives |
netPnl | string | No | Net profit/loss as decimal string |
errorMessage | string | No | Error message if trade failed |
errorAt | string (ISO timestamp) | No | When the error occurred |
lastUpdateAt | string (ISO timestamp) | No | Last update timestamp |
metadata | object | No | Additional metadata (defaults to {}) |
transactions | array | Yes | Array of transactions (must not be empty) |
Transaction Fields
| Field | Type | Required | Description |
|---|---|---|---|
transactionGroup | "entry" | "exit" | Yes | Whether this is an entry or exit transaction |
exitType | string | Yes* | Exit type (required if transactionGroup is "exit") |
trimLevel | number | Yes** | Trim level (required if exitType is "trim") |
symbol | string | Yes | Transaction symbol (may differ from trade symbol for options) |
assetType | string | Yes | Asset type (e.g., "stock", "option") |
side | string | Yes | Side of transaction ("buy" or "sell") |
type | string | Yes | Order type (e.g., "market", "limit", "stop") |
quantity | number | Yes | Quantity/shares |
transactionDate | string (ISO timestamp) | Yes | Transaction date/time |
stopPrice | string | No | Stop price for stop orders |
price | string | No | Limit price for limit orders |
optionType | string | No | Option type ("call" or "put") |
strikePrice | string | No | Strike price for options |
expirationDate | string | No | Expiration date for options |
status | string | No | Transaction status (e.g., "open", "filled") |
filledAt | string (ISO timestamp) | No | When transaction was filled |
filledPrice | string | No | Fill price |
filledQuantity | string | No | Filled quantity |
avgFillPrice | string | No | Average fill price |
broker | string | No | Broker code |
brokerAccountNumber | string | No | Broker account number |
brokerOrderId | string | No | Broker order ID |
brokerParentOrderId | string | No | Broker parent order ID (for bracket orders) |
notes | string | No | Notes |
metadata | object | No | Transaction metadata (defaults to {}) |
* Required when transactionGroup is "exit"
** Required when exitType is "trim"
Validation Rules
Trade Level:
symbolmust be a non-empty stringtradeTypemust be a non-empty stringstatusmust be a non-empty stringsignalAtmust be a valid ISO timestamp stringtransactionsmust be a non-empty array
Transaction Level:
transactionGroupmust be exactly"entry"or"exit"- If
transactionGroupis"exit",exitTypeis required - If
exitTypeis"trim",trimLevelis required and must be a number symbol,assetType,side,typemust be non-empty stringsquantitymust be a numbertransactionDatemust be a valid ISO timestamp string
Option Symbol Parsing:
- For options with
assetType: "option", the system automatically extracts the underlying symbol from Tradier format:TICKER + YYMMDD + C/P + STRIKE - Example:
"AAPL230120C00150000"extracts underlying symbol"AAPL"
Response
Success Response (200 OK)
{
"success": true,
"data": {
"botTrade": {
"id": "111e4567-e89b-12d3-a456-426614174001",
"botId": "123e4567-e89b-12d3-a456-426614174000",
"symbol": "AAPL",
"tradeType": "long",
"status": "open",
"signalAt": "2024-01-15T10:30:00.000Z",
"openedAt": "2024-01-15T10:30:05.000Z",
"netPnl": null,
"metadata": {}
},
"transactions": [
{
"id": "222e4567-e89b-12d3-a456-426614174002",
"botTradeId": "111e4567-e89b-12d3-a456-426614174001",
"transactionGroup": "entry",
"symbol": "AAPL",
"underlyingSymbol": "AAPL",
"assetType": "stock",
"side": "buy",
"type": "market",
"quantity": 100,
"status": "open",
"transactionDate": "2024-01-15T10:30:05.000Z"
},
{
"id": "333e4567-e89b-12d3-a456-426614174003",
"botTradeId": "111e4567-e89b-12d3-a456-426614174001",
"transactionGroup": "exit",
"exitType": "stop",
"symbol": "AAPL",
"underlyingSymbol": "AAPL",
"assetType": "stock",
"side": "sell",
"type": "stop",
"stopPrice": "145.00",
"quantity": 100,
"status": "open",
"transactionDate": "2024-01-15T10:30:05.000Z"
}
]
}
}Response Schema
| Field | Type | Description |
|---|---|---|
success | boolean | Always true for successful requests |
data | object | Created trade and transactions |
data.botTrade | object | Created bot trade object |
data.transactions | array | Array of created transaction objects |
Error Responses
400 Bad Request
Invalid JSON:
{
"error": "Invalid JSON in request body",
"code": "BAD_REQUEST"
}Missing required field:
{
"error": "symbol is required and must be a string",
"code": "BAD_REQUEST"
}Invalid transaction group:
{
"error": "transactions[0].transactionGroup must be 'entry' or 'exit'",
"code": "BAD_REQUEST"
}Missing exit type:
{
"error": "transactions[0].exitType is required for exit transactions",
"code": "BAD_REQUEST"
}Missing trim level:
{
"error": "transactions[0].trimLevel is required for trim exits",
"code": "BAD_REQUEST"
}Empty transactions array:
{
"error": "transactions array cannot be empty",
"code": "BAD_REQUEST"
}401 Unauthorized
Missing API key:
{
"message": "API key required. Include x-api-key header."
}403 Forbidden
Invalid API key:
{
"message": "Invalid API key for this bot"
}404 Not Found
Bot not found:
{
"error": "Bot with slug 'my-bot' not found",
"code": "NOT_FOUND"
}500 Internal Server Error
{
"error": "Internal server error",
"code": "INTERNAL_SERVER_ERROR"
}Code Examples
TypeScript
interface Transaction {
transactionGroup: "entry" | "exit";
exitType?: string;
trimLevel?: number;
symbol: string;
assetType: string;
side: string;
type: string;
quantity: number;
transactionDate: string;
stopPrice?: string;
price?: string;
// ... other optional fields
}
async function createBotTrade(
botSlug: string,
apiKey: string,
trade: {
symbol: string;
tradeType: string;
status: string;
signalAt: string;
transactions: Transaction[];
openedAt?: string;
}
) {
const response = await fetch(`https://api.example.com/api/bots/${botSlug}/trades`, {
method: "POST",
headers: {
"Content-Type": "application/json",
"x-api-key": apiKey,
},
body: JSON.stringify(trade),
});
if (!response.ok) {
const error = await response.json();
throw new Error(`Failed to create trade: ${error.error}`);
}
return await response.json();
}
// Example: Simple long trade with entry transaction
const trade = await createBotTrade("my-bot", apiKey, {
symbol: "AAPL",
tradeType: "long",
status: "open",
signalAt: new Date().toISOString(),
openedAt: new Date().toISOString(),
transactions: [
{
transactionGroup: "entry",
symbol: "AAPL",
assetType: "stock",
side: "buy",
type: "market",
quantity: 100,
transactionDate: new Date().toISOString(),
status: "filled",
filledAt: new Date().toISOString(),
filledPrice: "150.25"
}
]
});
console.log(`Trade created: ${trade.data.botTrade.id}`);
// Note: Exit transactions (stop loss, take profit, etc.) should be added separately
// using the add-transactions endpointPython
from typing import List, Dict, Any, Optional
from datetime import datetime
import requests
def create_bot_trade(
bot_slug: str,
api_key: str,
symbol: str,
trade_type: str,
status: str,
signal_at: str,
transactions: List[Dict[str, Any]],
opened_at: Optional[str] = None
) -> Dict[str, Any]:
"""
Create a bot trade with transactions.
Args:
bot_slug: Bot identifier
api_key: Bot API key
symbol: Trade symbol
trade_type: Type of trade
status: Trade status
signal_at: ISO timestamp when signal was generated
transactions: List of transaction dictionaries
opened_at: Optional ISO timestamp when trade opened
Returns:
Response dictionary with created trade and transactions
Raises:
requests.HTTPError: If the request fails
"""
url = f"https://api.example.com/api/bots/{bot_slug}/trades"
payload = {
"symbol": symbol,
"tradeType": trade_type,
"status": status,
"signalAt": signal_at,
"transactions": transactions
}
if opened_at:
payload["openedAt"] = opened_at
headers = {
"Content-Type": "application/json",
"x-api-key": api_key
}
response = requests.post(url, json=payload, headers=headers)
response.raise_for_status()
return response.json()
# Example: Simple long trade with entry transaction
trade = create_bot_trade(
bot_slug="my-bot",
api_key="your-api-key",
symbol="AAPL",
trade_type="long",
status="open",
signal_at=datetime.now().isoformat(),
opened_at=datetime.now().isoformat(),
transactions=[
{
"transactionGroup": "entry",
"symbol": "AAPL",
"assetType": "stock",
"side": "buy",
"type": "market",
"quantity": 100,
"transactionDate": datetime.now().isoformat(),
"status": "filled",
"filledAt": datetime.now().isoformat(),
"filledPrice": "150.25"
}
]
)
print(f"Trade created: {trade['data']['botTrade']['id']}")
# Note: Exit transactions (stop loss, take profit, etc.) should be added separately
# using the add-transactions endpointUse Cases
Simple Long Trade with Stop Loss
// Entry buy + stop loss exit
await createBotTrade("my-bot", apiKey, {
symbol: "AAPL",
tradeType: "long",
status: "open",
signalAt: new Date().toISOString(),
transactions: [
{
transactionGroup: "entry",
symbol: "AAPL",
assetType: "stock",
side: "buy",
type: "market",
quantity: 100,
transactionDate: new Date().toISOString()
},
{
transactionGroup: "exit",
exitType: "stop",
symbol: "AAPL",
assetType: "stock",
side: "sell",
type: "stop",
stopPrice: "145.00",
quantity: 100,
transactionDate: new Date().toISOString()
}
]
});Options Trade
# Options trade with call option
trade = create_bot_trade(
bot_slug="my-bot",
api_key=api_key,
symbol="AAPL230120C00150000", # Tradier option format
trade_type="long_call",
status="open",
signal_at=datetime.now().isoformat(),
transactions=[
{
"transactionGroup": "entry",
"symbol": "AAPL230120C00150000",
"assetType": "option",
"side": "buy",
"type": "limit",
"price": "5.50",
"quantity": 10,
"optionType": "call",
"strikePrice": "150.00",
"expirationDate": "2023-01-20",
"transactionDate": datetime.now().isoformat()
}
]
)Multiple Entry Transactions
// Create trade with multiple entry transactions (e.g., scaling in)
const trade = await createBotTrade("my-bot", apiKey, {
symbol: "TSLA",
tradeType: "long",
status: "open",
signalAt: new Date().toISOString(),
transactions: [
{
transactionGroup: "entry",
symbol: "TSLA",
assetType: "stock",
side: "buy",
type: "limit",
price: "240.00",
quantity: 50,
transactionDate: new Date().toISOString()
},
{
transactionGroup: "entry",
symbol: "TSLA",
assetType: "stock",
side: "buy",
type: "limit",
price: "238.00",
quantity: 50,
transactionDate: new Date().toISOString()
}
]
});Note: Exit transactions (stop losses, take profits, trailing stops, trim exits) should be added after trade creation using the Add Transactions endpoint.