PeakBot Docs
Bots EndpointBot Trades

Update Trade

Update trade fields including status, PnL, and error information

Update an existing bot trade. This endpoint allows you to update trade status, profit/loss, error information, and other trade metadata. When updating status to "closed", the system automatically updates open exit transactions and recalculates trade status.

Endpoint

PATCH /api/bots/:slug/trades/:tradeId

Authentication

All requests require bot API key authentication via the x-api-key header.

headers: {
  'x-api-key': 'your-bot-api-key'
}

Path Parameters

ParameterTypeRequiredDescription
slugstringYesBot identifier (alphanumeric, hyphens, underscores only)
tradeIdstringYesUUID of the trade to update

Slug Validation

The slug must match the regex pattern: /^[a-zA-Z0-9_-]+$/

Request Body

{
  status?: string;                    // Trade status
  closedAt?: string;                  // ISO timestamp when trade closed
  netPnl?: string;                    // Net profit/loss as decimal string
  errorMessage?: string;              // Error message if trade failed
  errorAt?: string;                    // ISO timestamp when error occurred
  metadata?: Record<string, unknown>;  // Additional metadata
  expirationDate?: string;            // Expiration date for options/derivatives
}

Request Body Schema

FieldTypeRequiredDescription
statusstringNoTrade status (e.g., "open", "closed", "error")
closedAtstring (ISO timestamp)NoWhen the trade was closed
netPnlstringNoNet profit/loss as decimal string
errorMessagestringNoError message if trade failed
errorAtstring (ISO timestamp)NoWhen the error occurred
metadataobjectNoAdditional metadata
expirationDatestringNoExpiration date for options/derivatives

Validation Rules

  • At least one field must be provided
  • closedAt and errorAt are converted from ISO timestamp strings to Date objects
  • When status is set to "closed":
    • All open exit transactions are automatically updated to "filled" status
    • Trade status is recalculated based on transaction states
    • closedAt is set from calculation if not provided
    • netPnl is calculated and set if not provided

Allowed Fields

Only the following fields can be updated:

  • status
  • closedAt
  • netPnl
  • errorMessage
  • errorAt
  • metadata
  • expirationDate

Response

Success Response (200 OK)

{
  "success": true,
  "trade": {
    "id": "111e4567-e89b-12d3-a456-426614174001",
    "botId": "123e4567-e89b-12d3-a456-426614174000",
    "symbol": "AAPL",
    "tradeType": "long",
    "status": "closed",
    "signalAt": "2024-01-15T10:30:00.000Z",
    "openedAt": "2024-01-15T10:30:05.000Z",
    "closedAt": "2024-01-15T15:30:00.000Z",
    "netPnl": "525.50",
    "metadata": {}
  }
}

Response Schema

FieldTypeDescription
successbooleanAlways true for successful requests
tradeobjectUpdated trade object

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 slug or tradeId:

{
  "error": "Bot slug and trade 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"
}

500 Internal Server Error

{
  "error": "Internal server error",
  "code": "INTERNAL_SERVER_ERROR"
}

Code Examples

TypeScript

async function updateBotTrade(
  botSlug: string,
  tradeId: string,
  apiKey: string,
  updates: {
    status?: string;
    closedAt?: string;
    netPnl?: string;
    errorMessage?: string;
    errorAt?: string;
    metadata?: Record<string, unknown>;
    expirationDate?: string;
  }
) {
  const response = await fetch(
    `https://api.example.com/api/bots/${botSlug}/trades/${tradeId}`,
    {
      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 trade: ${error.error}`);
  }

  return await response.json();
}

// Example: Close a trade
const result = await updateBotTrade(
  "my-bot",
  "111e4567-e89b-12d3-a456-426614174001",
  "your-api-key",
  {
    status: "closed",
    closedAt: new Date().toISOString(),
    netPnl: "525.50"
  }
);

console.log(`Trade ${result.trade.id} updated to status: ${result.trade.status}`);

Python

from typing import Optional, Dict, Any
from datetime import datetime
import requests

def update_bot_trade(
    bot_slug: str,
    trade_id: str,
    api_key: str,
    updates: Dict[str, Any]
) -> Dict[str, Any]:
    """
    Update a bot trade.
    
    Args:
        bot_slug: Bot identifier
        trade_id: UUID of trade to update
        api_key: Bot API key
        updates: Dictionary of fields to update
        
    Returns:
        Response dictionary with updated trade
        
    Raises:
        requests.HTTPError: If the request fails
    """
    url = f"https://api.example.com/api/bots/{bot_slug}/trades/{trade_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: Close a trade
result = update_bot_trade(
    bot_slug="my-bot",
    trade_id="111e4567-e89b-12d3-a456-426614174001",
    api_key="your-api-key",
    updates={
        "status": "closed",
        "closedAt": datetime.now().isoformat(),
        "netPnl": "525.50"
    }
)

print(f"Trade {result['trade']['id']} updated to status: {result['trade']['status']}")

Use Cases

Close Trade with PnL

// Close trade and set profit/loss
await updateBotTrade("my-bot", tradeId, apiKey, {
  status: "closed",
  closedAt: new Date().toISOString(),
  netPnl: "525.50"
});

Record Trade Error

# Record an error that occurred during trade execution
update_bot_trade(
    bot_slug="my-bot",
    trade_id=trade_id,
    api_key=api_key,
    updates={
        "status": "error",
        "errorMessage": "Order rejected by broker: Insufficient funds",
        "errorAt": datetime.now().isoformat()
    }
)

Automatic Status Recalculation

// When closing a trade, the system automatically:
// 1. Updates all open exit transactions to "filled"
// 2. Recalculates trade status
// 3. Sets closedAt if not provided
// 4. Calculates netPnl if not provided

await updateBotTrade("my-bot", tradeId, apiKey, {
  status: "closed"
  // closedAt and netPnl will be calculated automatically
});