User Websocket
Authenticated WebSocket channels for real-time account and strategy data.
Connection
wss://api.t.synchronicity.xyz/indexer-ws/wsThe upgrade is gated by an _idx_session cookie — prime it with GET /indexer/session, open the WebSocket with Cookie: _idx_session=…, and on 403 read the fresh cookie from the upgrade response’s Set-Cookie and retry. See Session Cookie — WebSocket.
All messages are JSON.
Authentication
The _idx_session cookie gates the transport; SIWE gates the account identity. Once the socket is open, the account and strategy_detail channels additionally require a SIWE authenticate message — see User Info — Authentication for full SIWE details.
Request:
{
"action": "authenticate",
"accounts": [
{
"account_id": "0x...",
"auth_method": "siwe",
"siwe_message": "...",
"siwe_signature": "0x..."
}
]
}| Field | Required | Description |
|---|---|---|
account_id | yes | Account address (case-insensitive) |
auth_method | no | Defaults to "siwe" |
siwe_message | yes | The EIP-4361 message |
siwe_signature | yes | The signed message |
Multiple accounts can be authenticated in a single message. Subsequent authenticate messages are cumulative.
Success Response:
{
"type": "authenticated",
"success": true,
"account_ids": ["0xabc...", "0xdef..."]
}account_ids contains only the newly authenticated accounts from this request.
Error Response:
If any account in the request fails authentication, the entire request fails:
{
"type": "error",
"message": "signature verification failed for account: 0xabc..."
}Errors
All errors use the format:
{
"type": "error",
"message": "descriptive error message"
}Channels
account
Real-time account state: balances, orders, positions, and margins.
Requires authentication.
Subscribe:
{
"action": "subscribe",
"channel": "account",
"account_ids": ["0xabc..."]
}Unsubscribe:
{
"action": "unsubscribe",
"channel": "account",
"account_ids": ["0xabc..."]
}Snapshot: A full state snapshot is sent immediately on subscribe.
{
"type": "snapshot",
"account_id": "0xabc...",
"state": {
"balance": {
"<token_id>": {
"token": {
"token_id": "...",
"name": "USDT",
"symbol": "USDT",
"decimals": 6
},
"balance": "1000.500000"
}
},
"orderbooks": {
"<orderbook_id>": {
"leverage": 10,
"margin_type": "cross",
"iso_orders_margin": "100.000000",
"iso_pos_margin_from_cross": "50.000000",
"orders": {
"<order_id>": {
"price": "50000.00",
"is_bid": true,
"order_type": "limit",
"size": "1.0",
"size_filled": "0.5",
"size_original": "1.0",
"reduce_only": false,
"parent_twap_id": null,
"sl_tp_side": null,
"client_order_id": "client-123",
"stop_loss": { "price": "49000.00", "size": "1.0", "price_type": "fixed" },
"take_profit": { "price": "51000.00", "size": "1.0", "price_type": "fixed" },
"created_at": 1704067200000
}
},
"position": {
"entry_price": "49500.00",
"mark_price": "50000.00",
"cost": "49500000000",
"size": "1.0",
"is_long": true,
"notional": "50000000000",
"im": "5000000000",
"mm": "2500000000",
"upnl": "500000000",
"margin": "5000000000",
"stop_losses": [
{ "price": "49000.00", "size": "0.5", "conditional_execution_id": "exec-123" }
],
"take_profits": [
{ "price": "51000.00", "size": "0.5", "conditional_execution_id": "exec-124" }
]
},
"margin": {
"max_im": "5000000000",
"order_im_long": "2000000000",
"order_im_short": "1000000000"
},
"twap_orders": {
"<twap_id>": {
"twap_id": "twap-001",
"orderbook_id": 123,
"total_size": "10.0",
"is_bid": true,
"reduce_only": false,
"frequency_ms": 5000,
"slippage": 100,
"start_time": 1704067200,
"end_time": 1704153600,
"total_executed_size": "5.0",
"total_filled_size": "3.50000",
"remaining_size": "5.0",
"elapsed_time": 2500,
"status": "active",
"cancellation_reason": null,
"created_at": 1704067200000
}
}
}
},
"account_perp_summary": {
"equity": "1050.500000",
"cross_equity": "1000.500000",
"balance": "1000.500000",
"upnl": "50.000000",
"cross_margin_ratio": "0.005",
"cross_maintenance_margin": "5.000000",
"cross_account_leverage": "10.0",
"available_balance": "995.500000"
}
}
}Account Notifications
After subscribing to the account channel, you will receive the following notification types as your account state changes.
balance_updated
Sent when a token balance changes (deposits, withdrawals, trades, funding).
{
"type": "balance_updated",
"updated_balance": {
"token": {
"token_id": "stoken_1qyqqq...2z5dp7",
"name": "USD Tether",
"symbol": "USDT",
"decimals": 6
},
"balance": "1050.500000"
}
}order_updated
Sent when an order is created, filled (partially or fully), or cancelled (or partially cancelled). order is always present with the current order state. When fully filled, size will be "0" and size_filled will equal size_original.
{
"type": "order_updated",
"orderbook_id": 1,
"order_id": 12345,
"order": {
"price": "50000.0",
"is_bid": true,
"order_type": "limit",
"size": "0.50000",
"size_filled": "0.10000",
"size_original": "0.50000",
"reduce_only": false,
"parent_twap_id": null,
"sl_tp_side": null,
"client_order_id": "my-order-1",
"stop_loss": { "price": "49000.0", "size": "0.50000", "price_type": "fixed" },
"take_profit": { "price": "51000.0", "size": "0.50000", "price_type": "fixed" },
"created_at": 1704067200000
}
}margin_updated
Sent when margin requirements change for an orderbook.
{
"type": "margin_updated",
"orderbook_id": 1,
"margin": {
"max_im": "5000.000000",
"order_im_long": "2000.000000",
"order_im_short": "1000.000000"
}
}position_updated
Sent when a position changes (new fill, mark price update, liquidation).
{
"type": "position_updated",
"orderbook_id": 1,
"leverage": 10,
"position": {
"entry_price": "49500.0",
"mark_price": "50000.0",
"cost": "49500000000",
"size": "1.00000",
"is_long": true,
"notional": "50000.000000",
"im": "5000.000000",
"mm": "2500.000000",
"upnl": "500.000000",
"margin": "5000.000000",
"stop_losses": [
{ "price": "49000.0", "size": "0.50000", "conditional_execution_id": "exec-123" }
],
"take_profits": [
{ "price": "51000.0", "size": "0.50000", "conditional_execution_id": "exec-124" }
]
}
}trade_created
Sent when one of your orders is filled.
{
"type": "trade_created",
"orderbook_id": 1,
"trade": {
"trade_id": 1,
"order_id": 12345,
"direction": "buy",
"order_price": "50000.0",
"order_type": "limit",
"price": "50000.0",
"size": "0.10000",
"fee": "0.500000",
"closed_pnl": "0.000000",
"total_pnl": "-0.500000",
"created_at": 1704067200000
}
}liquidation_trade_created
Sent when your position is liquidated or ADL’d.
{
"type": "liquidation_trade_created",
"orderbook_id": 1,
"trade": {
"trade_id": 1,
"is_adl": false,
"direction": "sell",
"price": "48000.0",
"size": "1.00000",
"fee": "0.480000",
"closed_pnl": "-2000.000000",
"total_pnl": "-2000.480000",
"created_at": 1704067200000
}
}leverage_updated
Sent when leverage or margin type changes for an orderbook.
{
"type": "leverage_updated",
"orderbook_id": 1,
"leverage": 20,
"margin_type": "crossed",
"margin": {
"max_im": "2500.000000",
"order_im_long": "1000.000000",
"order_im_short": "500.000000"
}
}funding_fee_paid
Sent when a funding payment is applied to your position.
{
"type": "funding_fee_paid",
"orderbook_id": 1,
"payment": "-1.250000",
"size": "1.00000",
"is_long": true,
"funding_rate": "0.000100000000000000",
"created_at": 1704067200000
}account_perp_summary
Sent after any state change that affects account-level metrics.
{
"type": "account_perp_summary",
"equity": "1050.500000",
"cross_equity": "1000.500000",
"balance": "1000.500000",
"upnl": "50.000000",
"cross_margin_ratio": "0.005000",
"cross_maintenance_margin": "5.000000",
"cross_account_leverage": "10.000000",
"available_balance": "995.500000"
}twap_order_created
Sent when a TWAP order is created.
{
"type": "twap_order_created",
"orderbook_id": 1,
"twap_order": {
"twap_id": "twap-001",
"orderbook_id": 1,
"total_size": "10.00000",
"is_bid": true,
"reduce_only": false,
"frequency_ms": 5000,
"slippage": 100,
"start_time": 1704067200,
"end_time": 1704153600,
"total_executed_size": "0.00000",
"total_filled_size": "0.00000",
"remaining_size": "10.00000",
"elapsed_time": 0,
"status": "active",
"cancellation_reason": null,
"created_at": 1704067200000
}
}twap_order_executed
Sent when a TWAP sub-order is executed or when a child order fill is received. Same shape as twap_order_created with updated tracking fields. total_filled_size reflects cumulative filled volume at the time of the notification.
twap_order_cancelled
Sent when a TWAP order is cancelled. cancellation_reason will be "user_request" or "order_creation_failed".
twap_order_completed
Sent when a TWAP order finishes executing all sub-orders. status will be "completed".
position_sltp_updated
Sent when position-level stop losses or take profits are added, removed, or modified.
{
"type": "position_sltp_updated",
"orderbook_id": 1,
"stop_losses": [
{
"price": "49000.0",
"size": "0.50000",
"conditional_execution_id": "exec-123",
"price_type": "fixed"
}
],
"take_profits": [
{
"price": "51000.0",
"size": "0.50000",
"conditional_execution_id": "exec-124",
"price_type": "percentage",
"percentage_bps": 20000
}
]
}Each entry includes a price_type field ("fixed" or "percentage"). For percentage entries, percentage_bps contains the centibips value and price is the resolved absolute trigger price.
sltp_executed
Sent when a stop loss or take profit is triggered.
{
"type": "sltp_executed",
"orderbook_id": 1,
"side": "StopLoss",
"conditional_execution_id": "exec-123",
"trigger_price": "49000.0",
"size": "0.50000"
}side is "StopLoss" or "TakeProfit".
isolated_margin_updated
Sent when isolated margin values change for an orderbook.
{
"type": "isolated_margin_updated",
"orderbook_id": 1,
"iso_orders_margin": "100.000000",
"iso_pos_margin_from_cross": "50.000000"
}Strategies
Strategy-related data is delivered through two mechanisms: summary notifications on the account channel and a dedicated strategy_detail channel. Both require authentication.
Account Channel Strategy Notifications
When subscribed to the account channel, the initial snapshot includes a strategy_summaries field:
{
"type": "snapshot",
"account_id": "0xabc...",
"state": {
"...": "...",
"strategy_summaries": {
"account_id": "0xabc...",
"strategies": {
"<strategy_id>": {
"strategy_id": "strategy-001",
"name": "Grid Trading",
"total_position_value": "50000.000000",
"upnl": "250.000000",
"status": "active",
"positions": { "123": { "size": "1.0", "cost": "49500000000" } },
"active_actions": 2,
"total_actions": 5,
"failed_actions": 0
}
},
"total_strategy_value": "50000.000000"
}
}
}The following strategy update notifications are also sent on the account channel:
| Type | Key Fields |
|---|---|
strategy_summary_updated | strategies, total_strategy_value |
strategy_execution_advanced | strategy_id, completed_action_id, new_action_ids, status |
strategy_execution_failed | strategy_id, action_id, reason |
strategy_cancelled | strategy_id |
strategy_completed | strategy_id |
strategy_detail Channel
Subscribe for detailed strategy state and granular updates.
Subscribe:
{
"action": "subscribe",
"channel": "strategy_detail",
"strategy_ids": ["strategy-001"]
}Unsubscribe:
{
"action": "unsubscribe",
"channel": "strategy_detail",
"strategy_ids": ["strategy-001"]
}Snapshot: Sent on subscribe.
{
"type": "strategy_detail_snapshot",
"strategy_id": "strategy-001",
"name": "Grid Trading Bot",
"description": "...",
"status": "active",
"active_action_ids": ["action-001", "action-002"],
"failed_actions": [],
"strategy_orders": [
{
"client_order_id": "client-123",
"orderbook_id": 123,
"order_id": 456,
"order": { "..." : "..." }
}
],
"upnl_usd": "250.000000",
"positions": [
{ "orderbook_id": 123, "size": "1.0", "cost": "49500000000", "upnl": "500000000" }
],
"created_at": 1704067200000,
"updated_at": 1704067200000
}Update:
{
"type": "strategy_pnl_updated",
"strategy_id": "strategy-001",
"total_rpnl": "1000.000000",
"total_upnl": "250.000000",
"positions": [
{ "orderbook_id": 123, "size": "1.0", "cost": "49500000000", "rpnl": "500.000000", "active": true, "upnl": "500000000" }
]
}Example Session
const ws = new WebSocket('wss://api.t.synchronicity.xyz/indexer-ws/ws');
// 1. Authenticate
ws.send(JSON.stringify({
action: 'authenticate',
accounts: [{
account_id: '0x123abc...',
auth_method: 'siwe',
siwe_message: '...',
siwe_signature: '0x...'
}]
}));
// 2. Subscribe to account updates
ws.send(JSON.stringify({
action: 'subscribe',
channel: 'account',
account_ids: ['0x123abc...']
}));
// Handle messages
ws.onmessage = (event) => {
const msg = JSON.parse(event.data);
console.log(msg.type, msg);
};Snapshot Summary
| Channel | Snapshot on subscribe? |
|---|---|
account | Yes |
strategy_detail | Yes |
Data Types
- All numeric values (prices, volumes, balances) are strings to preserve precision.
- Timestamps on orders/trades are milliseconds (Unix epoch).
is_bid:true= buy,false= sell.is_long:true= long,false= short.account_id: lowercase string.orderbook_id: uint64.order_id: uint64.trade_id: uint64.