Heartbeat dead-man's-switch — auto-cancel orders on missed pings.
Register or refresh a dead-man’s-switch heartbeat. If the server stops receiving heartbeats for longer than interval_ms + grace, all resting orders for this API key’s account are auto-cancelled.
Polymarket-compatible: POST /heartbeats (PM-shape root path, no /v1/) accepts the same body and response. Both paths route to this handler.
Bounds: interval_ms must be [1000, 60000]. Bots should ping at half the interval (or finer) to stay ahead of expiry.
Grace window: max(1s, 0.25 * interval_ms).
Storage: Redis-backed sorted set + per-registration hash. Survives api-worker restarts; the sweeper runs on the background leader worker with a 60s leader-election TTL so a leader crash promotes a follower automatically. Refresh/sweep TOCTOU race is closed via Redis WATCH/MULTI — a refresh that arrives between the sweeper’s ZRANGEBYSCORE and its ZREM aborts the dead-man fire and keeps the bot alive.
Authorizations
Issue from /v1/keys (or admin-issued for enterprise tier).
Headers
Your PolySimulator API key
Polymarket-CLOB-compat alias for X-API-Key (underscore form). SDK clients ported from Polymarket can authenticate without changing header names. X-API-Key takes precedence when both are provided.
PM-CLOB-compat dashed-form alias for X-API-Key. Same value semantics as POLY_API_KEY but with HTTP-conventional dash separators. Audit P1 (staging audit 2026-05-16 0817 PR #1296): the per-tier middleware accepts both spellings but the auth dependency originally only matched the underscore form — now both work end-to-end.
PM-CLOB-compat: Authorization: Bearer ps_live_... (or ps_test_...) is accepted as an alias for X-API-Key so py-clob-client and other ported SDKs authenticate without header name changes. Bearer JWTs are NOT accepted here — use the dashboard-auth endpoints for those.
Body
Heartbeat registration / refresh.
interval_ms: how long the server should wait between heartbeats
before declaring the bot dead and cancelling its orders. Bounded
[1000, 60000]. The bot is expected to ping at interval_ms / 2
or so to stay ahead of expiry.
client_label: optional free-form label so a single API key can
register multiple heartbeats from different bot processes. Defaults
to "" (single-stream). Bots that don't multiplex can ignore.