PolySocket Documentation
Connect to the PolySocket feed, authenticate with an API key, send wallet addresses in a subscribe command, and receive flat Polymarket wallet activity events for your own bot, dashboard, alerting, or API stack.
Connect, auth, listen.
Open a WebSocket connection and send an auth message as the first client message. Subscribe with wallet addresses for that live connection, then route activity messages with `observed_at_unix_ns` and `tx_hash` into your own stack.
{ "type": "auth", "api_key": "YOUR_API_KEY", "scope": "account" }{ "type": "subscribe", "wallets": ["0x885278f0e304bc2d53f805af2ab779cb6011c569"] }{
"type": "auth_ok",
"connection_id": "conn_1777766498121579485_100",
"account_id": "acct_sample",
"plan": "basic_weekly_2",
"wallet_count": 0,
"wallet_limit": 2,
"include_tx": false
}{
"type": "subscribed",
"scope": "custom",
"wallet_count": 1
}First-message auth.
Clients authenticate immediately after opening the socket. API keys are stored server-side as SHA-256 hashes. Plaintext keys are only shown once and should never be committed or published.
wss://feed.polysocket.dev/v1| Plan code | Live wallet capacity | WebSocket limit |
|---|---|---|
basic_weekly_2 | 2 | 100 |
basic_monthly_20 | 20 | 100 |
scale_monthly_100 | 100 | Unlimited |
Connection-edge abuse controls.
The production feed keeps auth, billing, database, and rate-limit checks off the wallet-event fanout path. Abuse controls run at handshake, private sync, command parsing, and connection liveness boundaries.
| Control | Limit | Effect |
|---|---|---|
| WebSocket upgrade attempts | 240/minute/IP | Excess attempts are rejected with HTTP 429 and temporarily blocked. |
| Bad WebSocket auth attempts | 30/minute/IP | Excess invalid credentials are rejected with HTTP 429 and temporarily blocked. |
| Bad account-sync bearer attempts | 10/minute/IP | Excess invalid sync tokens are rejected with HTTP 429 and temporarily blocked. |
| Temporary abuse block | 15 minutes | Applies only to the specific abuse key or IP. |
| Client command frame size | 8 KiB | Oversized client text or binary commands are rejected and the connection is closed. |
| Subscribe wallet array length | 100 wallets | Larger arrays receive too_many_wallets. Lower account plan wallet limits still apply after deduplication. |
| Server heartbeat | Protocol Ping every 15 seconds | Clients should let their WebSocket library answer with protocol Pong. |
| Heartbeat timeout | 45 seconds without protocol Pong | The server closes stale connections. |
Account access stays managed.
Approved accounts manage feed access and API keys through the PolySocket account surface. Internal provisioning, billing, and operational sync details are not part of the public WebSocket API.
Flat wallet activity messages.
When a watched wallet appears in the upstream Polygon wallet feed, PolySocket publishes a flat activity message to matching subscribers.
{
"event_id": "polygon:0x71a325...bf2ce:0x885278...1c569",
"observed_at_unix_ns": 1777766595870568021,
"wallet": "0x885278f0e304bc2d53f805af2ab779cb6011c569",
"tx_hash": "0x71a325019e713fb2234578d55e66e17b25a6f3868f6075a126356e7cc96bf2ce",
"role": "maker",
"side": "buy",
"side_raw": 0,
"price": 0.17,
"shares": 9.19,
"notional_usd": 1.5623,
"token_id": "70244509752957369974591345556629529797103276141600347856253643886913568219784",
"outcome_token_id": "70244509752957369974591345556629529797103276141600347856253643886913568219784",
"exchange_contract": "0xe111180000d2663c0091e4f400237545b87b996b",
"maker": "0x885278f0e304bc2d53f805af2ab779cb6011c569",
"signer": "0xa928b536ee1fedc96655820da2593ac50b1abb46",
"maker_amount_raw": "1562300",
"taker_amount_raw": "9190000"
}| Field | Type | Description |
|---|---|---|
event_id | string | Stable event ID formatted as polygon:{tx_hash}:{wallet}. |
observed_at_unix_ns | integer | PolySocket gateway observation timestamp in Unix nanoseconds. |
wallet | string | Normalized lowercase watched wallet address. |
tx_hash | string | Normalized lowercase Polygon transaction hash. |
role | string | Matched order role, currently maker or taker. |
side | string | Trade side from the matched order. Values are buy or sell when decoded. |
side_raw | integer | Raw decoded order side when present. BUY is 0 and SELL is 1. |
price | number | notional_usd / shares. |
shares | number | Outcome shares from the matched order. |
notional_usd | number | USDC notional, normalized from 6 decimals. |
token_id / outcome_token_id | string | Polymarket CLOB outcome token ID. |
exchange_contract | string | Polymarket exchange contract address that matched the order. |
maker, signer | string | Order maker and signer addresses. |
maker_amount_raw, taker_amount_raw | string | Raw integer order amounts. For buys, maker amount is USDC and taker amount is shares; for sells, maker amount is shares and taker amount is USDC. |
tx | object | Only present when include_tx, full_tx, or include_payload is true. |
Client command frames.
All client commands are JSON text frames. The first meaningful client command must be auth, and each client command frame must be 8 KiB or smaller.
{
"type": "subscribe",
"wallets": ["0x885278f0e304bc2d53f805af2ab779cb6011c569"]
}{
"type": "unsubscribe",
"wallets": ["0x885278f0e304bc2d53f805af2ab779cb6011c569"]
}{ "type": "ping", "ts": 1777766595 }{ "type": "pong", "ts": 1777766595 }| Error code | Meaning |
|---|---|
unknown_command | Client sent an unsupported JSON command type. |
invalid_wallet | Client sent a malformed wallet address. |
too_many_wallets | Client sent more than 100 wallet entries or exceeded the account wallet_limit after deduplication. |
message_too_large | Client command exceeded 8 KiB; the connection closes. |
auth_required | First meaningful client message was not auth; the connection closes. |
unauthorized | Auth message had a missing, invalid, inactive, or disallowed credential; the connection closes. |
connection_limit | Account exceeded its concurrent WebSocket limit; the connection closes. |
Decoded summaries by default.
The default feed sends a readable, low-latency summary. To receive the full upstream transaction object in addition to the decoded summary, opt in per connection.
{
"type": "auth",
"api_key": "YOUR_API_KEY",
"include_tx": true,
"scope": "account"
}Include the full upstream transaction object.
Alias for include_tx=true.
Alias for include_tx=true.
Polymarket-aware detection.
PolySocket customer subscriptions are wallet subscriptions, but matching is not a naive from/to transaction filter. The gateway decodes Polymarket exchange calls, checks taker and maker orders, and can match watched wallets by maker or signer.
- Supports direct exchange and fee-module contract calls.
- Unwraps one Gnosis Safe execTransaction layer when present.
- Supports older matchOrders and newer matchOrdersV2 flows.
- Matches against order maker and signer addresses.
- Drops ambiguous multi-token matches instead of emitting misleading signals.
0xe3f18acc55091e2c48d883fc8c8413319d4ab7b0
0xe111180000d2663c0091e4f400237545b87b996b
0xe2222d279d744050d28e00520010520000310f59
Consume events in common runtimes.
const apiKey = process.env.POLYSOCKET_API_KEY;
const wallets = ["0x885278f0e304bc2d53f805af2ab779cb6011c569"];
const ws = new WebSocket("wss://feed.polysocket.dev/v1");
ws.addEventListener("open", () => {
ws.send(JSON.stringify({
type: "auth",
api_key: apiKey,
scope: "account"
}));
});
ws.addEventListener("message", (event) => {
const msg = JSON.parse(event.data);
if (msg.type === "auth_ok") {
console.log("connected", msg.connection_id);
ws.send(JSON.stringify({
type: "subscribe",
wallets
}));
}
if (msg.observed_at_unix_ns && msg.tx_hash) {
routeToYourSystem(msg);
}
});import asyncio
import json
import os
import websockets
async def main():
api_key = os.environ["POLYSOCKET_API_KEY"]
wallets = ["0x885278f0e304bc2d53f805af2ab779cb6011c569"]
async with websockets.connect("wss://feed.polysocket.dev/v1", ping_interval=None, max_queue=None) as ws:
await ws.send(json.dumps({
"type": "auth",
"api_key": api_key,
"scope": "account"
}))
async for raw in ws:
msg = json.loads(raw)
if msg.get("type") == "auth_ok":
await ws.send(json.dumps({
"type": "subscribe",
"wallets": wallets
}))
if "observed_at_unix_ns" in msg and "tx_hash" in msg:
print(msg["wallet"], msg["tx_hash"], msg["observed_at_unix_ns"])
asyncio.run(main())use futures_util::{SinkExt, StreamExt};
use serde_json::{json, Value};
use tokio_tungstenite::connect_async;
#[tokio::main]
async fn main() -> anyhow::Result<()> {
let api_key = std::env::var("POLYSOCKET_API_KEY")?;
let wallets = ["0x885278f0e304bc2d53f805af2ab779cb6011c569"];
let (mut ws, _) = connect_async("wss://feed.polysocket.dev/v1").await?;
ws.send(json!({
"type": "auth",
"api_key": api_key,
"scope": "account"
}).to_string().into()).await?;
while let Some(msg) = ws.next().await {
let parsed: Value = serde_json::from_str(&msg?.into_text()?)?;
if parsed["type"] == "auth_ok" {
ws.send(json!({
"type": "subscribe",
"wallets": wallets
}).to_string().into()).await?;
}
if parsed["observed_at_unix_ns"].is_number() && parsed["tx_hash"].is_string() {
println!("wallet={} tx={}", parsed["wallet"], parsed["tx_hash"]);
}
}
Ok(())
}Runtime checks stay minimal.
GET https://feed.polysocket.dev/healthz returns ok when the feed edge is reachable.
AsyncAPI is published at /asyncapi.yaml and HTTP endpoint OpenAPI is published at /openapi.yaml.
Public /metrics returns 404 by design. Runtime metrics are local to DEDI for operators.
A feed, not a trading bot.
A WebSocket feed, structured event source, latency-focused input layer, and API surface for wallet activity monitoring.
A copy trading bot, execution venue, wallet manager, custody product, strategy engine, or position-sizing engine.
Your bot, network path, routing, queue position, order type, and execution latency determine actual fills.
