API Reference

Capandex exposes API endpoints for backtesting, market data, and exchange key management. All endpoints require authentication via Supabase auth cookies.

Authentication

All API requests require authentication. Capandex uses Supabase Auth, and the session is managed through HTTP-only cookies. When you are logged in to the Capandex dashboard, your requests are automatically authenticated.

All requests must include the Supabase auth cookie. If the cookie is missing or expired, the API returns a 401 Unauthorized response.

Engine Endpoints

GET/api/engine/status?executionId=X

Get the current status of an execution session, including performance metrics.

Query Parameters

executionIdstringrequiredThe execution session ID

Response

{
  "executionId": "exec_abc123",
  "status": "running",
  "startedAt": "2025-01-15T10:30:00Z",
  "currentTick": 42,
  "pnl": 125.50,
  "pnlPercent": 1.26,
  "openPositions": 1,
  "totalTrades": 5
}
POST/api/engine/backtest

Run a backtest on a flow using historical candle data. Returns full performance metrics.

Request Body

flowIdstringrequiredThe flow to backtest
exchangestringrequiredExchange to source data from
symbolstringrequiredTrading pair (e.g., BTC/USDT)
timeframestringrequiredCandle timeframe (1m, 5m, 15m, 1h, 4h, 1d)
startDatestringrequiredISO 8601 start date
endDatestringrequiredISO 8601 end date

Response

{
  "backtestId": "bt_xyz789",
  "status": "completed",
  "metrics": {
    "pnl": 1250.00,
    "pnlPercent": 12.5,
    "winRate": 0.62,
    "maxDrawdown": 450.00,
    "maxDrawdownPercent": 4.2,
    "sharpeRatio": 1.85,
    "profitFactor": 2.1,
    "totalTrades": 48,
    "winningTrades": 30,
    "losingTrades": 18
  },
  "equityCurve": [
    { "timestamp": "2025-01-01T00:00:00Z", "equity": 10000 },
    { "timestamp": "2025-01-02T00:00:00Z", "equity": 10125 }
  ]
}

Market Data

GET/api/market?exchange=X&action=symbols

Get the list of available trading symbols for an exchange.

Query Parameters

exchangestringrequiredExchange name (binance, okx, bybit, etc.)
actionstringrequiredMust be "symbols"

Response

{
  "symbols": [
    "BTC/USDT",
    "ETH/USDT",
    "SOL/USDT",
    "..."
  ]
}
GET/api/market?exchange=X&symbol=Y

Get the current ticker data for a symbol on an exchange.

Query Parameters

exchangestringrequiredExchange name
symbolstringrequiredTrading pair (e.g., BTC/USDT)

Response

{
  "symbol": "BTC/USDT",
  "last": 42150.50,
  "bid": 42148.00,
  "ask": 42153.00,
  "volume": 15234.56,
  "change24h": 2.35,
  "timestamp": "2025-01-15T10:30:00Z"
}
GET/api/exchanges

List all supported exchange configurations. Returns active exchanges with their display names and ccxt IDs.

Response

{
  "exchanges": [
    {
      "id": "binance",
      "name": "Binance",
      "ccxt_id": "binance",
      "is_active": true,
      "sort_order": 1
    }
  ]
}

Exchange Keys

GET/api/exchange-keys

List all saved exchange connections for the authenticated user. Secrets are never returned.

Response

{
  "keys": [
    {
      "id": "key_abc123",
      "exchange": "binance",
      "label": "Main Account",
      "createdAt": "2025-01-10T08:00:00Z",
      "isValid": true
    }
  ]
}
POST/api/exchange-keys

Save a new exchange API key. The key and secret are encrypted with AES-256-GCM before storage.

Request Body

exchangestringrequiredExchange name (binance, okx, bybit, mexc, coinbase, kraken)
labelstringHuman-readable label for this key
apiKeystringrequiredThe API key from the exchange
secretstringrequiredThe API secret from the exchange
passphrasestringPassphrase (required for OKX)

Response

{
  "id": "key_abc123",
  "exchange": "binance",
  "label": "Main Account",
  "createdAt": "2025-01-15T10:30:00Z"
}
DELETE/api/exchange-keys

Delete a saved exchange API key. This action is permanent.

Request Body

idstringrequiredThe key ID to delete

Response

{
  "deleted": true
}
POST/api/exchange-keys/validate

Validate exchange API credentials by attempting to fetch account info. Does not save the key.

Request Body

exchangestringrequiredExchange name
apiKeystringrequiredThe API key to validate
secretstringrequiredThe API secret to validate
passphrasestringPassphrase (for OKX)

Response

{
  "valid": true,
  "permissions": ["read", "trade"],
  "account": {
    "balance": 5234.50
  }
}

Flows

GET/api/flows/[flowId]/versions

List all saved versions for a flow, ordered by version number (newest first). Returns metadata with node/edge counts instead of full payloads.

Response

{
  "versions": [
    {
      "id": "ver_abc123",
      "flow_id": "flow_xyz",
      "version": 3,
      "change_description": "Added RSI filter",
      "node_count": 8,
      "edge_count": 7,
      "created_at": "2025-01-15T10:30:00Z"
    }
  ]
}
POST/api/flows/[flowId]/versions

Manually save a named version snapshot of the current flow state. Maximum 50 versions per flow (oldest auto-deleted).

Request Body

descriptionstringDescription of the changes in this version

Response

{
  "id": "ver_abc123",
  "flow_id": "flow_xyz",
  "version": 4,
  "change_description": "Added stop-loss node",
  "created_at": "2025-01-15T10:30:00Z"
}
POST/api/flows/[flowId]/versions/[versionId]/restore

Restore a flow to a previous version. The current state is auto-saved as a new version before restoring.

Response

{
  "restored": true,
  "version": 2
}
GET/api/flows/[flowId]/performance

Get detailed performance metrics for a flow based on its closed positions. Includes win rate, Sharpe ratio, drawdown, and equity curve.

Query Parameters

fromstringISO 8601 start date filter
tostringISO 8601 end date filter

Response

{
  "totalTrades": 48,
  "winRate": 0.62,
  "pnl": 1250.00,
  "pnlPercent": 12.5,
  "maxDrawdown": 450.00,
  "maxDrawdownPercent": 4.2,
  "sharpeRatio": 1.85,
  "profitFactor": 2.1,
  "equityCurve": [
    { "timestamp": 1704067200000, "equity": 10000 },
    { "timestamp": 1704153600000, "equity": 10125 }
  ]
}

Notifications

GET/api/notifications

List notifications for the authenticated user with optional filtering and pagination.

Query Parameters

typestringFilter by type (e.g., trade, engine, system)
unreadOnlystringSet to "true" to return only unread notifications
limitnumberNumber of results (default 50)
offsetnumberPagination offset (default 0)

Response

{
  "notifications": [
    {
      "id": "notif_abc",
      "type": "trade",
      "title": "Order Filled",
      "message": "BTC/USDT buy 0.1 filled at $42,150",
      "read_at": null,
      "action_url": "/history",
      "created_at": "2025-01-15T10:30:00Z"
    }
  ],
  "total": 25
}
PATCH/api/notifications

Mark all notifications as read for the authenticated user.

Response

{
  "success": true
}
PATCH/api/notifications/[id]

Mark a single notification as read.

Response

{
  "success": true
}
DELETE/api/notifications/[id]

Permanently delete a single notification.

Response

{
  "success": true
}

AI Keys

GET/api/ai-keys

Check if the user has an Anthropic API key saved. Returns a masked hint but never the full key.

Response

{
  "hasKey": true,
  "hint": "sk-ant-****"
}
POST/api/ai-keys

Save an Anthropic API key. The key is encrypted with AES-256-GCM before storage. Must start with 'sk-ant-'.

Request Body

apiKeystringrequiredAnthropic API key (must start with sk-ant-)

Response

{
  "success": true,
  "hint": "sk-ant-****"
}
DELETE/api/ai-keys

Remove the saved Anthropic API key.

Response

{
  "success": true
}
POST/api/ai-keys/validate

Validate the stored Anthropic API key by calling the Anthropic models endpoint.

Response

{
  "valid": true
}

Chat

POST/api/chat

Send a message to the AI trading assistant. Returns a Server-Sent Events (SSE) stream. Requires a saved Anthropic API key.

Request Body

messagesarrayrequiredArray of {role, content} message objects
flowContextobjectCurrent flow context (nodes, edges, settings) for context-aware responses
flowIdstringFlow ID to persist chat messages to the database

Response

SSE stream:
data: {"text":"I can help"}
data: {"text":" you with"}
data: {"text":" that strategy."}
data: [DONE]
GET/api/chat/messages?flowId=X

Load saved chat messages for a flow.

Query Parameters

flowIdstringrequiredThe flow ID to load messages for

Response

{
  "messages": [
    {
      "id": "msg_abc",
      "role": "user",
      "content": "How should I set up RSI?",
      "created_at": "2025-01-15T10:30:00Z"
    }
  ]
}
DELETE/api/chat/messages?flowId=X

Delete all chat messages for a flow.

Query Parameters

flowIdstringrequiredThe flow ID to clear messages for

Response

{
  "success": true
}

Profile & Preferences

GET/api/profile/preferences

Get the user's notification preferences.

Response

{
  "notification_preferences": {
    "engine_start": true,
    "engine_stop": true,
    "trade_executed": true,
    "engine_error": true
  }
}
PATCH/api/profile/preferences

Update the user's notification preferences.

Request Body

notification_preferencesobjectrequiredObject with notification type keys and boolean values

Response

{
  "success": true
}

Dashboard

GET/api/dashboard/multi-flow

Get an overview of all flows with PnL, trade counts, win rates, and error counts. Used by the dashboard.

Response

{
  "flows": [
    {
      "id": "flow_abc",
      "name": "BTC Momentum",
      "status": "running",
      "symbol": "BTC/USDT",
      "exchange": "binance",
      "pnl": 125.50,
      "pnlPct": 1.26,
      "tradeCount": 12,
      "winRate": 0.75,
      "errorCount": 0,
      "openPositions": 1,
      "executionId": "exec_xyz"
    }
  ],
  "aggregate": {
    "totalPnl": 350.00,
    "totalPnlPct": 1.75,
    "totalTrades": 28,
    "runningFlows": 2,
    "errorFlows": 0,
    "totalOpenPositions": 3
  }
}
GET/api/dashboard/balance

Get the aggregated USD balance across all connected exchanges. Only stablecoin balances are included in the total.

Response

{
  "totalUsd": 15234.50,
  "exchanges": [
    {
      "exchange": "binance",
      "label": "Main Account",
      "balanceUsd": 10000.00
    },
    {
      "exchange": "okx",
      "label": "Trading",
      "balanceUsd": 5234.50
    }
  ]
}