WakeTrades

API for AI Agents

Real-Time Stream

A WebSocket for agents. WakeTrades pushes every copy event and every move of your leaders as it happens, and takes commands back (pause, close, emergency stop). Open GET /api/v1/stream with your session token.

The stream is a WebSocket between your agent and its copier. WakeTrades pushes every event as it happens: the same events as the webhook, plus each move of the leaders you follow. Your agent can send commands back on the same connection.

Open the Stream

GET wss://waketrades.com/api/v1/stream with the header Authorization: Bearer <session token>.

  • It uses the same session token as the rest of the API (Sign In With a Wallet). When the token expires, the stream closes with code 4001: sign in again and reopen it.
  • You can keep up to 3 streams open at the same time per account. Beyond that, you get 429 too_many_streams.
  • A request without the Upgrade: websocket header gets 426 upgrade_required.
  • Browsers can't add an Authorization header to a WebSocket: open the stream from a server or an agent runtime.

Python (websockets library)

import asyncio, json, websockets

async def run(token: str):
    async with websockets.connect("wss://waketrades.com/api/v1/stream",
                                  additional_headers={"Authorization": f"Bearer {token}"}) as ws:
        print(json.loads(await ws.recv()))                      # hello
        await ws.send(json.dumps({"id": "1", "type": "positions"}))
        async for raw in ws:
            msg = json.loads(raw)
            print(msg["type"], msg.get("data"))

JavaScript (Node) (ws library)

import WebSocket from "ws";

const ws = new WebSocket("wss://waketrades.com/api/v1/stream", { headers: { Authorization: `Bearer ${token}` } });
ws.on("open", () => ws.send(JSON.stringify({ id: "1", type: "positions" })));
ws.on("message", (raw) => {
  const msg = JSON.parse(raw);
  console.log(msg.type, msg.data);
});

First Message

{
  "type": "hello",
  "protocol": "waketrades.stream.v1",
  "account": "0xyour_wallet",
  "expiresAt": 1791633600000,
  "commands": ["ping", "status", "positions", "orders", "journal", "pause", "resume", "close_position", "close_all", "emergency_stop"]
}

expiresAt is when your session token ends, in ms.

Events

Events have the same shape as webhook events: { "id", "type", "created", "account", "data" }.

  • Every event of your copier: the types listed in Webhooks, and also the ones the webhook doesn't push (skip, error, state, payment, limit_placed…). A skip carries a stable skip code (too_small, full, late, not_unified…), like GET /orders. Muting notifications doesn't change the stream.
  • Your leaders' moves, as WakeTrades sees them, sent before your copy reacts:
type When
leader_open A leader you follow opens a position
leader_add, leader_cut The leader increases or reduces it
leader_close The leader closes it
leader_flip The leader reverses it (long to short, or short to long)
leader_tpsl The leader changes the take profit or stop loss of a position opened since you follow them
{
  "id": "evt_mg8k2l1c_4be01a7d",
  "type": "leader_open",
  "created": 1791633600000,
  "account": "0xyour_wallet",
  "data": { "leader": "0xleader…", "coin": "ETH", "side": 1, "sz": 4, "prevSz": 0, "entryPx": 2450.5, "leverage": 10, "leverageType": "cross", "mid": 2451 }
}

side is 1 for long and -1 for short. sz is the leader's size in coins now (0 after a close), and prevSz the size before. tpsl, when known, lists the take profits and stops as [price, share of the position].

The stream doesn't keep events while you're disconnected. After a reconnection, catch up with the journal command or GET /api/v1/journal.

Commands

Send JSON: { "id": "your-id", "type": "<command>" }. Each command gets one answer with the same id:

{ "type": "result", "id": "your-id", "ok": true, "data": { } }
{ "type": "result", "id": "your-id", "ok": false, "error": "alert_channel_required", "message": "…" }
Command Fields What it does
ping Answers { "pong": true }
status Copying state, exposure level, leaders, open copies, trial and plan dates
positions Copied positions with stop and take profit, like GET /positions (read again at most every 30 seconds, or right after an order is sent; longer during a Hyperliquid outage or heavy load)
orders n (1 to 100, default 20) Copy orders, including skipped trades and why, like GET /orders
journal n (1 to 100, default 20) Recent events, newest first
pause Stop opening new copies; open ones stay managed
resume Resume copying (needs Telegram or a webhook)
close_position coin Close one copy at market
close_all Close every copy at market and pause
emergency_stop The same as POST /emergency-stop: close everything and pause, with what it doesn't do (keyRevoked: false)

Error codes: bad_request, unknown_command, alert_channel_required, command_failed, geo_blocked (write commands from a restricted jurisdiction, checked when the stream opens) and rate_limited (more than 60 commands per minute on one stream, or more than 180 per minute on all of an account's streams, reconnections included).

Close Codes

Code Why
4001 The session token expired
4003 The account was deleted or suspended

Last updated October 21, 2026