Bots EndpointBot Trades
Update Transaction
Update a specific transaction within a bot trade
Update fields of a specific transaction within a bot trade. This is commonly used to update transaction status when orders are filled, update fill prices, or modify stop prices. When transaction status changes, the trade status is automatically recalculated.
Endpoint
PATCH /api/bots/:slug/trades/:tradeId/transactions/:transactionIdAuthentication
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) |
tradeId | string | Yes | UUID of the trade |
transactionId | string | Yes | UUID of the transaction to update |
Slug Validation
The slug must match the regex pattern: /^[a-zA-Z0-9_-]+$/
Request Body
{
status?: string; // Transaction status
filledAt?: string; // ISO timestamp when filled
filledQuantity?: string; // Filled quantity
avgFillPrice?: string; // Average fill price
stopPrice?: string; // Stop price for stop orders
price?: string; // Limit price for limit orders
brokerParentOrderId?: string; // Broker parent order ID (for bracket orders)
metadata?: Record<string, unknown>; // Transaction metadata
notes?: string; // Notes
}Request Body Schema
| Field | Type | Required | Description |
|---|---|---|---|
status | string | No | Transaction status (e.g., "open", "filled", "cancelled") |
filledAt | string (ISO timestamp) | No | When the transaction was filled |
filledQuantity | string | No | Quantity that was filled |
avgFillPrice | string | No | Average fill price |
stopPrice | string | No | Stop price for stop orders |
price | string | No | Limit price for limit orders |
brokerParentOrderId | string | No | Broker parent order ID (for bracket orders) |
metadata | object | No | Transaction metadata |
notes | string | No | Notes |
Validation Rules
- At least one field must be provided
filledAtis converted from ISO timestamp string to Date object- When
statusis updated, the trade status is automatically recalculated - If trade status becomes "closed" after recalculation,
netPnlandclosedAtare automatically set
Allowed Fields
Only the following fields can be updated:
statusfilledAtfilledQuantityavgFillPricestopPricepricebrokerParentOrderIdmetadatanotes
Response
Success Response (200 OK)
{
"success": true,
"transaction": {
"id": "222e4567-e89b-12d3-a456-426614174002",
"botTradeId": "111e4567-e89b-12d3-a456-426614174001",
"transactionGroup": "entry",
"symbol": "AAPL",
"assetType": "stock",
"side": "buy",
"type": "market",
"quantity": 100,
"status": "filled",
"filledAt": "2024-01-15T10:30:10.000Z",
"filledPrice": "150.25",
"avgFillPrice": "150.25",
"transactionDate": "2024-01-15T10:30:05.000Z"
},
"trade": {
"id": "111e4567-e89b-12d3-a456-426614174001",
"status": "open",
"lastUpdateAt": "2024-01-15T10:30:10.000Z"
}
}Response Schema
| Field | Type | Description |
|---|---|---|
success | boolean | Always true for successful requests |
transaction | object | Updated transaction object |
trade | object | Updated trade object (included if status was recalculated) |
Notes
- If
statusis updated, thetradeobject is included in the response showing the recalculated trade status - Trade status recalculation happens automatically when transaction status changes
- If the trade becomes "closed" after recalculation,
netPnlandclosedAtare set automatically
Error Responses
400 Bad Request
Invalid JSON:
{
"error": "Invalid JSON in request body",
"code": "BAD_REQUEST"
}No valid fields to update:
{
"error": "No valid fields to update",
"code": "BAD_REQUEST"
}Missing required parameters:
{
"error": "Bot slug, trade ID, and transaction ID are required",
"code": "BAD_REQUEST"
}Invalid slug format:
{
"error": "Invalid slug format. Only alphanumeric characters, hyphens, and underscores are allowed.",
"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"
}Trade not found:
{
"error": "Trade not found",
"code": "NOT_FOUND"
}Transaction not found:
{
"error": "Transaction not found",
"code": "NOT_FOUND"
}500 Internal Server Error
{
"error": "Internal server error",
"code": "INTERNAL_SERVER_ERROR"
}Code Examples
TypeScript
async function updateBotTransaction(
botSlug: string,
tradeId: string,
transactionId: string,
apiKey: string,
updates: {
status?: string;
filledAt?: string;
filledPrice?: string;
avgFillPrice?: string;
filledQuantity?: string;
stopPrice?: string;
price?: string;
brokerParentOrderId?: string;
metadata?: Record<string, unknown>;
notes?: string;
}
) {
const response = await fetch(
`https://api.example.com/api/bots/${botSlug}/trades/${tradeId}/transactions/${transactionId}`,
{
method: "PATCH",
headers: {
"Content-Type": "application/json",
"x-api-key": apiKey,
},
body: JSON.stringify(updates),
}
);
if (!response.ok) {
const error = await response.json();
throw new Error(`Failed to update transaction: ${error.error}`);
}
return await response.json();
}
// Example: Mark transaction as filled
const result = await updateBotTransaction(
"my-bot",
"111e4567-e89b-12d3-a456-426614174001",
"222e4567-e89b-12d3-a456-426614174002",
"your-api-key",
{
status: "filled",
filledAt: new Date().toISOString(),
filledPrice: "150.25",
avgFillPrice: "150.25",
filledQuantity: "100"
}
);
console.log(`Transaction ${result.transaction.id} updated to ${result.transaction.status}`);
if (result.trade) {
console.log(`Trade status recalculated: ${result.trade.status}`);
}Python
from typing import Optional, Dict, Any
from datetime import datetime
import requests
def update_bot_transaction(
bot_slug: str,
trade_id: str,
transaction_id: str,
api_key: str,
updates: Dict[str, Any]
) -> Dict[str, Any]:
"""
Update a bot transaction.
Args:
bot_slug: Bot identifier
trade_id: UUID of trade
transaction_id: UUID of transaction to update
api_key: Bot API key
updates: Dictionary of fields to update
Returns:
Response dictionary with updated transaction and optionally trade
Raises:
requests.HTTPError: If the request fails
"""
url = f"https://api.example.com/api/bots/{bot_slug}/trades/{trade_id}/transactions/{transaction_id}"
headers = {
"Content-Type": "application/json",
"x-api-key": api_key
}
response = requests.patch(url, json=updates, headers=headers)
response.raise_for_status()
return response.json()
# Example: Mark transaction as filled
result = update_bot_transaction(
bot_slug="my-bot",
trade_id="111e4567-e89b-12d3-a456-426614174001",
transaction_id="222e4567-e89b-12d3-a456-426614174002",
api_key="your-api-key",
updates={
"status": "filled",
"filledAt": datetime.now().isoformat(),
"filledPrice": "150.25",
"avgFillPrice": "150.25",
"filledQuantity": "100"
}
)
print(f"Transaction {result['transaction']['id']} updated to {result['transaction']['status']}")
if "trade" in result:
print(f"Trade status recalculated: {result['trade']['status']}")Use Cases
Update Fill Information
// Update transaction when order is filled
await updateBotTransaction("my-bot", tradeId, transactionId, apiKey, {
status: "filled",
filledAt: new Date().toISOString(),
filledPrice: "150.25",
avgFillPrice: "150.25",
filledQuantity: "100"
});Update Stop Price
# Update stop loss price as market moves
update_bot_transaction(
bot_slug="my-bot",
trade_id=trade_id,
transaction_id=transaction_id,
api_key=api_key,
updates={
"stopPrice": "400.00"
}
)Update Stop Price
// Adjust stop loss price
await updateBotTransaction("my-bot", tradeId, transactionId, apiKey, {
stopPrice: "148.00" // Move stop loss up
});Add Transaction Notes
# Add notes about the transaction
update_bot_transaction(
bot_slug="my-bot",
trade_id=trade_id,
transaction_id=transaction_id,
api_key=api_key,
updates={
"notes": "Partial fill - remaining quantity pending",
"metadata": {
"partialFill": True,
"remainingQuantity": 50
}
}
)Automatic Trade Status Recalculation
// When marking exit transaction as filled, trade status is automatically recalculated
const result = await updateBotTransaction("my-bot", tradeId, exitTransactionId, apiKey, {
status: "filled",
filledAt: new Date().toISOString(),
filledPrice: "155.00"
});
// Trade status may change to "closed" if all exit transactions are filled
if (result.trade && result.trade.status === "closed") {
console.log(`Trade closed with PnL: ${result.trade.netPnl}`);
}