Engine events
Everything the execution engine does, replayed from a sequence number and then live.
Self-hosted. Served by synpath serve on your own machine or host, which must be running. Nothing here runs on Synpath's servers.
The trading API's own socket. It sends the engine's journal events: orders accepted, rejected, cancelled and edited, fills booked, complex orders created, halts and resumes, reconciliation and end-of-day reports. Pass since to replay from a sequence number first, so a client that reconnects does not miss the fill that happened while it was away.
Served by your self-hosted server (synpath serve). Needs an access token with view permission, as a query parameter or a bearer header; events are filtered to the accounts the token may see. On the machine the server runs on, the token is in ~/.synpath/servers.json.
Query parameters
| Name | Type | Description |
|---|---|---|
key | string | Your server's access token. Authorization: Bearer <token> works too where headers can be set. |
since | integerdefault 0 | Replay every event after this sequence number, then stay live. 0 replays the whole journal. |
kinds | string | Comma-separated kinds to receive, e.g. order.accepted,fill.booked. Omit for all. |
Frame
One journal event per text frame, as JSON.
| Name | Type | Description |
|---|---|---|
seq | integer | Journal sequence number. Save it and pass it back as since. |
ts | integer | ms since epoch. |
kind | string | One of the kinds below. |
key | string | What the event is about: an order id, a fill id, a venue. |
payload | object | The order, fill, or report, as in the REST API. |
dropped | integer | Live only: events dropped because this client fell behind. Replay from seq to recover them. |
Kinds
| Name | Type | Description |
|---|---|---|
order.accepted, order.rejected, order.canceled, order.edited, order.failed, order.in_doubt | | Venue orders through their lifecycle. |
fill.booked | | A fill applied to the ledger, with the realized P&L it produced. |
managed.created, managed.restored | | Complex orders created, and resumed after a restart. |
intent.pending, intent.adopted, intent.swept, intent.unresolved | | Recovery of orders the process was sending when it died. |
risk.rejected, risk.configured | | A refusal, with the rule that refused; a new rule set. |
engine.started, engine.stopped, engine.halted, engine.resumed, engine.book_paused, engine.lease_lost | | The engine's own state. |
reconcile.done, settlement.booked, eod.report | | Reconciliation against the venues, settlements, the daily report. |
import asyncio, json, os
import websockets
TOKEN = os.environ["SYNPATH_ACCESS_TOKEN"] # your self-hosted server (synpath serve)'s access token
async def main(since: int = 0):
url = f"ws://127.0.0.1:8000/trading/ws/events?key={TOKEN}&since={since}&kinds=order.accepted,fill.booked"
async with websockets.connect(url) as ws:
async for raw in ws:
event = json.loads(raw)
print(event["seq"], event["kind"], event["key"])
since = event["seq"] # save it; pass it back after a reconnect
asyncio.run(main()){
"seq": 1843,
"ts": 1789655011496,
"kind": "fill.booked",
"key": "kalshi:072210b7-9701-9f67-dbeb-8607028b7a25",
"payload": {
"id": "072210b7-9701-9f67-dbeb-8607028b7a25",
"order_id": "01a0afc0-46e8-7596-b183-1ff448331615",
"market_id": "kalshi:KXELONMARS-99",
"side": "buy",
"price": "0.10",
"amount": "2",
"fee": "0.0014",
"book": "alpha",
"realized": "0"
},
"dropped": 0
}
