On this page
Polymarket
Artery exposes all five Polymarket hosts as a single namespace. Every
endpoint returns the upstream JSON shape unmodified, wrapped in { native, meta }.
Endpoints
| Artery | Upstream |
|---|---|
GET /v1/polymarket/markets | gamma-api.polymarket.com/markets |
GET /v1/polymarket/markets/:conditionId | Gamma /markets/:id |
GET /v1/polymarket/events | Gamma /events |
GET /v1/polymarket/search?q= | Gamma /public-search |
GET /v1/polymarket/search-v2?q= | Gamma /search-v2 |
Cloudflare WAF
Polymarket fronts every host with Cloudflare. Calling clob.polymarket.com with curl or default
axios UA returns 403 Forbidden. Artery's @artery/transport package automatically injects a
Chrome 131 User-Agent + Origin / Referer so all requests pass.
If you bypass Artery and call Polymarket directly, replicate this header
set or you will hit 403 on /auth/api-key.
Planned additions
POST /v1/polymarket/orders— place CLOB order via Safe ModuleDELETE /v1/polymarket/orders/:id— cancelPOST /v1/polymarket/positions/redeem— redeem settled marketsPOST /v1/polymarket/delegation/initiate— Safe Module setup flow
These are scaffolded but require a Polygon Amoy testnet wallet for
end-to-end validation. See Linear QF-10297 for the full spec.
Trade-feed transport
Artery intentionally does not ingest or redistribute Polymarket's full
market trade stream. It watches only customer-bound wallets and emits one
account-perspective broker.trade.executed for the V2 OrderFilled row whose
on-chain maker equals the bound Safe. A taker-only counterparty row is not a
second customer execution. The source contracts are CTF_EXCHANGE and
NEG_RISK_EXCHANGE; two wallet-filtered transports are available through
art.polymarket.live_feed_mode:
| Mode | How it works | Use when |
|---|---|---|
rpc_polling | Worker polls Polygon RPC with bound-wallet maker topics every ~6s | Emergency fallback; works with any Polygon RPC. Latency: 6–12s |
moralis_streams (default) | Moralis pushes wallet-filtered unconfirmed logs with low latency | Production; needs Moralis API key + a publicly reachable webhook URL |
Switching from RPC polling to Moralis is hot. Switching into RPC polling
requires a rolling restart so only the worker holding the per-source leader
lease starts the poller. Production also requires the immutable
ART_ALLOW_PROD_RPC_POLLING=true break-glass flag; without it the effective
mode remains Moralis. Both modes feed the same canonical wallet-fill
persistence and webhook path.
Moralis Streams mode
Artery uses the first unconfirmed observation for an idempotent provisional execution notification. It does not write speculative fills into the final trade ledger or advance the confirmed feed watermark. The confirmed replay performs those authoritative state updates and does not notify again.
When live_feed_mode = moralis_streams, Artery maintains a single
Moralis Stream (per-deployment) that watches the two V2 exchange
contracts and filters server-side to the union of all customer-bound
wallets. New bindings are durably queued for one second, deduplicated, and
synced in batches of up to 100 addresses per upstream call. A Postgres-backed
rolling budget coordinates all replicas and both Polymarket streams against
Moralis's five address-add requests per five minutes limit. Healthy periodic
reconciliation performs no stream update or address mutation.
Configuration lives under art.polymarket.moralis_streams.*:
| Setting | Required | Description |
|---|---|---|
api_key | yes | Moralis API key (secret) |
webhook_secret | yes | Shared secret for Moralis x-signature verification (keccak of exact JSON body + secret) |
webhook_url | yes | Publicly reachable URL of POST /v1/internal/polymarket/streams-webhook |
stream_id | auto | Populated on first start; manual edits trigger a re-resolve |
Operator surface lives at /streams in the internal admin — current
mode, configured-vs-unset checklist, upstream stream status (address
count + drift vs local mirror), last webhook timestamp, plus
Re-sync addresses (idempotent) and Recreate stream (destructive)
actions. The webhook handler verifies x-signature using Moralis's documented
exact-body-plus-account-secret input.
Funding classification
The dedicated wallet ledger stream observes collateral ERC-20 and position
ERC-1155 logs together. External Deposit/Withdraw is emitted only after block
confirmation and transaction-level classification. If the same wallet and
transaction has a maker fill or position transfer, its collateral leg is
trade/settlement cash flow and is excluded from account Activity and
broker.funding.updated. This decision is persisted and reused by historical
backfill, so an unknown router address cannot turn a Buy into a false Withdraw.
Terms-of-service note
Polymarket's Developer Agreement forbids redistribution of order book and market data except as explicitly permitted. Artery's pass-through model — your client provides Polymarket credentials per request — keeps you within those bounds. Ask Polymarket BD before exposing data through Artery as a public product.