# What running a bot does not solve

A bot fixes speed and consistency. Rate limits, a missing rehearsal, a field that stops arriving, a partial fill and a paused market are not coding problems.

*https://predictionmarkets.tools/guides/what-a-bot-cannot-fix · background to Trading Clients, SDKs & Bots*

**Answer:** A bot supplies speed and consistency. It inherits everything else from the venue: published rate limits per endpoint class, whether a rehearsal environment exists at all, whether breaking changes arrive with a changelog, what happens to the unfilled half of an order, and what becomes of a resting order when a market is paused, clarified or resolved. None of those is a coding problem. Each is read out of the documentation, or discovered afterwards.

There is a point in most people's first automated strategy where the remaining problem looks
like engineering. The analysis is done, the entries are defined, and what is left is that a
human cannot sit at a screen at 03:00 and cannot place four orders in the same second. A bot
fixes both of those, completely and on the first day.

It fixes nothing else, and the things it does not fix are not in your code. They are in the
venue: how often you may ask, whether you can practise, what shape the answers arrive in, how
much of an order you actually get, and what a market is permitted to do to an order you have
already placed. Every one of those is written down somewhere in a venue's own API
documentation, and every one of them is a question a reader can settle in an afternoon before
the first live run rather than in the ten minutes after something has gone quiet.

Everything below is read from venue documentation on 21 September 2026 and dated. None of it has
been run against a funded account by this site. Four doc sets are used throughout because the
point is the spread between them: what one venue publishes, another does not, and the shape of
the answer differs even where both publish one.

## How it works

Split what a trading process does into two halves. The first half is yours: what to trade, at
what price, in what size, on what signal. The second half belongs to the venue, and your code
does not get a vote in it. A bot is an improvement to the first half only, and most of the
expensive surprises live in the second.

### Rate limits are per endpoint class, and a cancel is not an order

The first thing to learn is that "requests per second" is not a unit. It becomes one only once
you know what it is counted against, and the four venues read for this page count against four
different things.

**Polymarket US** publishes the most granular table. On its exchange API the limits are per
participant firm and **per method**, with the documentation stating that each method has its own
bucket and that "Methods displaying the same limit do not share that allowance". Order entry
(`InsertOrder`) and cancel-replace run from 30 requests per second at Tier 1 to 400 at Tier 4.
Plain `CancelOrder` runs from 90 per second to 1,200 — three times the order-entry allowance at
every tier. Batch methods are flat at 50 requests per second across all tiers, carry up to 20
operations per request, and each batch request "counts once toward that method's rate limit,
regardless of the number of operations in the request".

Read endpoints on the same API are quoted in requests per *minute*, not per second, and the
numbers are small: `ListInstruments` and `ListSymbols` at 6 per minute, `GetOrderBook`, `GetBBO`,
`SearchOrders`, `SearchExecutions` and `SearchTrades` at 12 per minute each. The retail API is
simpler and much flatter — a global 20 requests per second per API key across all endpoints, and
20 per second per IP for public unauthenticated calls.

The tiers are not a plan you buy. They are earned from trailing-30-day contract volume share:
Tier 2 at 0.125% to earn and 0.10% to maintain, Tier 3 at 0.50% and 0.225%, Tier 4 at 1.50% and
1.20%. Dropping below the maintain threshold does not cut your limit immediately — the
documentation gives 30 days to climb back before a move down. Read that as what it is: the limit
your process ran comfortably inside last quarter is a variable, and it moves with your own
activity.

**Adjacent** counts by organisation and by two budgets at once. The free public tier is 50
requests per 10 seconds keyed by client IP at the edge; Pro is 30 requests per minute and 20,000
per day; Premium is 180 per minute and 150,000 per day, with the daily budget resetting at 00:00
UTC. On top of that sits a concurrency cap — four simultaneous requests per organisation, with a
request waiting up to two seconds for a slot before it is refused. The sentence worth copying
into your notes is the one that closes off the obvious workaround: "Every API key and
authenticated session in an organization draws from the same budgets. Creating more keys does
not increase throughput."

**Manifold** publishes one number and one sentence: "There is a rate limit of 500 requests per
minute per IP. Please don't use multiple IP addresses to circumvent this limit."

**Limitless** publishes the mechanism and not the figure. Its API reference states that the API
enforces rate limits, that exceeding one returns `429 Too Many Requests`, that you should respect
a `Retry-After` header when present and otherwise back off from one second and double, and that
high-frequency workloads should queue outgoing orders rather than fire them concurrently. For the
actual ceiling it points you at a support address. That is a legitimate design and it has a
consequence for you: there is no number to code against, so the only safe posture is a queue with
a configurable rate you can turn down.

Four venues, four scopes — per firm per method, per organisation, per IP, per API key. A client
library that ships one `rate_limit` setting is making an assumption on your behalf.

### What a retry loop does at the wrong moment

A retry loop is the first thing anybody writes and the last thing anybody reads. Two failure
modes recur, and both come from treating the rejection as a single kind of event.

The first is **retrying something that will never succeed**. Limitless states it directly:
"Never retry `400` or `401` — those indicate a bad request or invalid credentials and will not
succeed on retry." Adjacent draws the same line between two status codes that a loop written
around "if it failed, try again" cannot tell apart: a `429` means a budget ran out and will
refill, whereas a request from an organisation with no paid plan is refused up front with `403`,
and "Unlike a 429, retrying does not help: nothing resets until the organization holds a plan."

The second is more interesting, because it is the *inverse* error — backing off when backing off
is wrong. Polymarket US applies a five-second latency stopgap to inbound orders: an order
received but not processed within five seconds is rejected "to protect you from a bad fill at a
stale price". The documentation then warns, in its own bold, that these rejects "carry the
message `Global Rate Limit Exceeded`, but they are **not** an actual rate limit. You do **not**
need to throttle your traffic in response to them. Treat them as a transient latency reject, not
a signal to back off."

Read what that does to an ordinary bot. The order never reached the book, so nothing was filled
and nothing is resting. The correct response is to re-price against the current book and
resubmit. A process that matches on the string "Rate Limit Exceeded" instead sleeps, doubles,
sleeps again — and comes back to a market that has moved, having done nothing during exactly the
interval it was written to cover. The stopgap applies to new orders and to modifications via
cancel/replace; "Pure cancels are not affected — a standalone cancel is never rejected by this
stopgap", and "You can always cancel an order before you have received an acknowledgement, and
even before it has been processed". Cancelling is the one primitive that stays reachable when
everything else is being rejected, which makes it the right thing to build your safety path
around.

Limitless adds a third shape to the same lesson: a `425 Too Early` is documented as either a
receive-window failure or a maintenance block, distinguished by a `code` in the body, and the two
want different handling — "Re-stamp and retry only for receive-window failures; refresh
maintenance status for maintenance blocks." One status, two responses, and only the body tells
you which.

There is also a cost to getting this wrong that is not measured in missed fills. Polymarket US
lists "Automated retry loops without backoff" among the patterns that "may result in temporary or
permanent restrictions on your API credentials", alongside polling for data available via
streaming and requesting the same unchanged data repeatedly.

### The rehearsal you may not have

"I have tested it" means two very different things, and which one it means is decided by the
venue rather than by you.

Limitless states the harder case in one paragraph, and it is worth quoting whole because the
second sentence is the part that is actually useful: "There is no sandbox, testnet, mock mode, or
Base Sepolia deployment — all integrations run against production with real USDC. To rehearse a
flow without significant capital, place small live orders (e.g. the minimum order size for a CLOB
market) on a low-volume market."

That is a venue telling you plainly that your integration test is a live trade. The advice is
sound and it is also an admission of what a live rehearsal cannot reach: it exercises
authentication, signing, submission, the response shape and your own reconciliation, and it does
not exercise a deep book, your own size moving a price, or any of the rejection paths you will
only meet under load.

Polymarket US is the other case. Its exchange API runs two environments — a preprod at
`api.preprod.polymarketexchange.com` and a prod at `api.prod.polymarketexchange.com`, each with
its own auth domain, each exposing the same `/v1/health` check — and the documented integration
progression is preprod first, then prod, with credentials requested per environment from an
onboarding address. So a rehearsal exists here, on the institutional surface, by application.
Note the detail that will bite a long-running process in either environment: "Tokens must be
refreshed every 3 minutes."

Manifold sits between the two, publishing a dev websocket endpoint beside the production one.

The question to settle before you write a line is therefore not "how do I test this" but "what
does this venue let me test, and what will I only ever find out live". The answer changes which
parts of the strategy you are willing to automate first.

### The API you are running against is not the API you read

Three of the four doc sets read for this page carry a dated changelog. That is the good case, and
it is still not a promise that nothing moves under you.

Manifold versions by path prefix and is explicit about what lies outside it: there is a `/v0`
surface, and a set of internal endpoints that "are not preceeded by /v0 and are even more subject
to sudden changes than the official API endpoints". Its changelog is short and dated, and it does
record removals — the 30 October 2024 entry removes an endpoint outright. Elsewhere a documented
endpoint is marked deprecated in favour of a more versatile replacement and left in place, which
is the kinder pattern and also the one that lets a process keep running on a surface nobody is
maintaining.

Limitless shows deprecation happening *inside* a field rather than to an endpoint. Its order
event frames carry a `timestamp` that the documentation marks "Deprecated — kept for backward
compatibility", whose meaning is now source-dependent, beside three additive semantic timestamps.
The guidance is blunt: "Do not substitute one for another", and "any missing semantic timestamp
arrives as `null` rather than a value copied from another field". Nothing was renamed. The name
is identical, the field still arrives, and what it means depends on which frame you are looking
at.

Adjacent's changelog contains the clearest worked example of how this actually breaks a running
process, and it is not a rename either. On 27 August 2026, `GET /api/v1/events` began returning
`total` and `total_pages` as `null` when a `search` parameter is set, with callers directed to
page using `has_next` instead. The changelog explains why — the old total was bounded by the
search's internal candidate window rather than the matched set, so it under-reported broad
queries and changed as you paged through the same results — and the change is unambiguously a
correction. It is also a field that used to be an integer and is now sometimes nothing. A loop
built as a range over `total_pages` raises on the next run, which is the lucky outcome; one that
coerces a missing value to zero iterates zero times, returns an empty result set, and reports
success.

The same changelog is full of the more common variant, which is a field that simply stops
arriving: `latest_price` "is omitted when the rate's last print is older than seven days",
`volume` "is omitted when the print did not record it", event `volume` and `open_interest` are
omitted "when no child market reports a value" while "A measured zero still serializes as `0`".
Read those three together and you have the actual failure mode: code that indexes the key
directly raises, and code that reaches for it defensively with a default of zero turns "nobody
has priced this in a week" into "this is worth nothing" — and then trades on it.

So the honest answer to "what happens to my process when a field is renamed" is that a rename is
the rare case and the one you notice. The common case is a field that becomes nullable, becomes
conditional, or changes what it counts, and that one is silent.

### The half of the order that did not fill

Polymarket US documents its fill model in four numbered lines and then works the example, and it
is the clearest statement of this in the sector. Every order is processed as a marketable limit
order. If enough size is available your order fills entirely; if not, "you receive a **partial
fill**", and "The unfilled portion stays on the order book as an **open order** until it is
filled or canceled". The worked case: buy 1,000 Yes contracts when the best ask is $0.52, and if
only 600 are available at that price, "you receive a partial fill for 600 contracts. The
remaining 400 stay on the order book at $0.52 as an open order until they are filled or
canceled. Your execution price reflects only the portion that filled."

Manifold describes the same outcome on a hybrid book: an order that crosses "would fill partially
or completely depending on current unfilled limit bets and the AMM's liquidity. Any remaining
portion of the bet not filled would remain to be matched against in the future."

The default on both is that the remainder is a live order you now own. Three branches go wrong,
and all three are what a first draft does:

1. **Treat the order as filled.** Your own position book now disagrees with the venue's. Anything
   sized off it — a hedge leg, a stop, a max-exposure check — is sized against a fill that partly
   did not happen.
2. **Resubmit the whole order.** You now have the original remainder *and* a fresh order resting.
   The moment liquidity returns you are filled at roughly double the size you intended, at a
   price you chose for the smaller one.
3. **Forget it.** It fills four hours later, at your price, into a market your strategy has since
   changed its mind about. Nothing failed; nothing logged an error.

On Limitless there is a further step between submission and fill that a synchronous mental model
has no room for. Some markets apply a taker delay, and on those the order endpoint "returns right
away with `execution.settlementStatus: "DELAYED"` and an `eligibleAt` timestamp instead of
blocking until settlement". The fill is then observed on the order-event stream as a provisional
`MATCHED` frame followed by a terminal `MINED` or `FAILED`, and the documentation is explicit
that the timeline is not bounded by `eligibleAt`: "Maintenance mode can postpone delayed fills
beyond `eligibleAt`; keep the order open in your integration until a terminal event arrives."
Maker orders sent `postOnly` are never delayed, and a market's current delay is readable as
`settings.takerDelayMs` on the market response.

The consequence is worth stating flatly: on those markets a `200` from the order endpoint is not
a fill, and "did my order fill" is not a question the submit response answers. It is answered by
the stream, correlated back by client order id. The same changelog adds the matching constraint
on the immediate-or-cancel types — "FAK and FOK orders can only be cancelled while they wait out
a taker delay. On markets without one they complete immediately and cannot be cancelled."

### The states your code has no branch for

The fills are the part people think about. The states below are the part that has no branch at
all, because the code was written while a market was open and normal.

**A scheduled pause.** Polymarket US "operates nearly 24/7, with a recurring weekly maintenance
window every **Thursday from 2:00–4:00 AM ET**".

**An unscheduled one.** From the same page: "Trading may be paused without prior notice to
protect market participants or ensure system stability. Service resumes once operational
integrity is restored." Nothing about that arrives as an exception in your process. Prices stop
moving, the fills stop, and a mean-reversion signal reading a frozen book is reading a number
that means something different from what it meant an hour earlier.

**A rewording.** Polymarket US posts clarifications to a market's rules — additional context that
"specif[ies] how the existing rules should be understood, resolve ambiguous language, and ensure
markets resolve according to the intended criteria", and which, the page says, "do not change the
market question". Two things follow for an automated position. Before a clarification lands, the
documentation says "Liquidity may be reduced", "Spreads may widen" and "Volatility can increase
when there is uncertainty" — so the thin book your sizing logic just met may be a signal about
the rules rather than about the market. And when it lands: "When a clarification is posted,
Polymarket US may cancel resting orders so they are not executed under clarified rules."

That last sentence deserves its own line. The exchange can cancel your resting orders, for a
reason that is neither an error nor about you, and a reconciliation routine that counts only its
own cancels will find a discrepancy it has no explanation for. The right design is to treat the
venue's order state as authoritative and your own as a cache.

**A resolution you were not watching for.** Limitless emits a `marketResolved` event carrying the
winning outcome and a `resolutionDate`, both to lifecycle subscribers and automatically to anyone
already subscribed to that market's room, so there is no separate subscription to remember. What
happens to an order still resting at that moment is not stated on that page — which is exactly
the sort of gap to settle with the venue before a funded run rather than during one. Who decides
that outcome, and against what source, is
[who decides the outcome](https://predictionmarkets.tools/guides/who-decides-the-outcome).

**A resolution that comes back.** Manifold documents a `POST /unresolve` endpoint that
"Unresolves a market". Resolution is therefore not necessarily terminal, and a process that
closes its books on a resolution event and never reads that market again has no branch for the
market reopening underneath it.

**A market that ended while its successor trades.** Limitless separates a market's instance slug
from its stable slug, with a dedicated endpoint to resolve the stable one and an `include`
parameter that returns successor-round data. A recurring market therefore has a new instance each
round. A bot holding a hard-coded instance slug keeps fetching a market that has ended, gets a
valid `200` every time, sees no new trades, and concludes the market is quiet. There is no error
anywhere in that sequence.

### The one thing this page does not cover

Authentication, key custody and what signing software can do with your account are a subject of
their own and a different set of documents.
[Where your key lives when software trades for you](https://predictionmarkets.tools/guides/where-your-key-lives) is that page,
and it is the one to read first if the bot you are about to run asks for a private key.

## What it costs

Most of what this page describes has no fee attached. The costs that do exist are worth naming
with their units, because two of them are priced in something other than money.

- **A rate-limit tier is priced in volume, not in dollars.** On Polymarket US's exchange API,
  Tier 2 is earned at 0.125% of trailing-30-day exchange-wide contract volume and maintained at
  0.10%; Tier 4 at 1.50% and 1.20%. You cannot buy the headroom, and if your own volume falls you
  have 30 days before the limit follows it down.
- **A rehearsal on a venue without one costs a live trade.** Limitless's own suggestion is a
  minimum-size order on a low-volume market, which means the fee schedule applies to your test
  suite. What a fill is actually charged, in the four incompatible units venues publish it in, is
  [what a trade actually costs](https://predictionmarkets.tools/guides/what-a-trade-actually-costs).
- **Reading is metered, and the read budgets are what decide your architecture.**
  `ListInstruments` and `ListSymbols` at 6 requests per minute and `GetOrderBook` at 12 make a
  polling design impossible rather than merely inefficient — and the documentation's own remedy is
  free: "Streaming connections don't count against the REST rate limit." The catalogue's
  [streaming feeds](https://predictionmarkets.tools/collections/streaming-feeds) collection is the set of cards where that
  option exists.
- **A daily budget is spent, not merely hit.** Adjacent's Pro tier is 30 requests per minute
  *and* 20,000 per day, organisation-wide, resetting at 00:00 UTC. An agent stuck in a retry loop
  at nine in the morning does not pause; it spends the rest of the day's allowance, for every
  process in the organisation, on nothing.
- **A partial fill costs the spread on the remainder**, plus whatever a half-sized position did
  while a hedge leg was sized for a whole one. Why the book was thin in the first place is
  [where liquidity comes from](https://predictionmarkets.tools/guides/where-liquidity-comes-from).
- **And a retry loop can cost the credential.** Polymarket US reserves temporary or permanent
  restrictions on API credentials for sustained over-limit traffic and automated retry loops
  without backoff.

## What you can do about it

Each of these is an afternoon at most, and each is cheaper before the first funded run than after
it.

**Read the venue's rate-limit page before you read the client library's.** Write down one word
per limit: is it per IP, per API key, per organisation, or per firm per method? That word decides
whether a second process doubles your headroom or halves it. Adjacent's documentation answers it
explicitly — more keys do not buy more throughput — and most do not.

**Budget cancels separately from orders, and build the safety path on cancel.** Polymarket US
gives cancels three times the order-entry allowance at every tier, exempts standalone cancels
from the latency stopgap, and states that you can cancel before you have received an
acknowledgement or before the order has been processed. That combination is a design instruction:
whatever else is failing, "cancel everything" should be the path that still works.

**Branch on the status code and the documented reason field, never on a message string.** The
Polymarket US latency stopgap is the case that proves it — a reject reading `Global Rate Limit
Exceeded` that the venue tells you not to back off for. Where a venue gives you a structured
reason, use it: Limitless returns `409 Conflict` with `reason: "ORDER_RELEASE_IN_PROGRESS"` and
`retryable: true` on a cancel that races a release, and a field called `retryable` exists so that
your loop does not have to guess.

**Treat a submit response as an intent and reconcile from the venue's own stream.** Subscribe to
the order and position feeds, correlate by your own client order id, and let the venue's view of
your open orders be authoritative. Every venue read for this page pushes you the same way for the
same reason, and on the delayed-settlement markets it is not an optimisation but the only correct
reading.

**Give the remainder a named branch.** Every order path needs an explicit case for "partially
filled, remainder resting", and the decision — cancel the rest, leave it, or replace it at a new
price — belongs in the strategy, written down, before the first time it happens. The default of
having no branch is branch three above: it fills later, at your price, for reasons that have
expired.

**Rehearse in whatever rehearsal exists, and write down what it does not reach.** If the venue
runs a preprod, ask for credentials and use it. If it does not, do what Limitless suggests —
minimum size, low-volume market, live — and then list explicitly what that did not test: depth,
your own size moving the price, and every rejection path that only appears under load. A
rehearsal you have characterised is worth more than one you trust.

**Subscribe to market lifecycle events and write the four branches.** Paused, clarified,
resolved, un-resolved. A bot with no branch for a paused market does not stop; it keeps reading a
frozen price as though it were a live one. A bot with no branch for a clarification treats an
exchange-initiated cancel as a bug in its own reconciliation.

**Resolve recurring markets through whatever stable identifier the venue offers**, rather than
pinning the instance you looked at on the day you wrote the code. A hard-coded slug for a weekly
market fails by returning valid, empty, successful responses forever.

**Pin a version, and read the changelog on a schedule you actually keep.** Where a venue
publishes one — Limitless, Adjacent and Manifold all do — put it on a calendar, because the
entries that matter to you will not be the ones labelled breaking. They will be the ones that add
a `null`, drop a key when a value is unavailable, or change what a count counts.

**Assert on the shape you receive, and fail loudly rather than defaulting.** The common failure is
not a renamed field, it is a missing one. A default of zero for an absent price turns "not priced
recently" into "priced at nothing", and that is a value your strategy will happily act on.
Validate the response against the shape you expect, and make an unexpected one stop the process
rather than feed it.

**Ask the key question separately.** What the bot can do with your account, and whether you can
take that permission back, is not on this page:
[where your key lives](https://predictionmarkets.tools/guides/where-your-key-lives) is. The rest of the maintenance and liveness
questions about the clients themselves — whether a library still speaks the venue's current API
at all — are on the [trading clients and bots](https://predictionmarkets.tools/categories/trading-clients-and-bots) page.

**And then the part no amount of this fixes.** Automation executes a strategy; it does not supply
one. Every item above makes a process lose less to mechanics, and none of them make a process
profitable, because none of them touch the question of whether the positions were worth taking.
A strategy with no edge, run by hand, loses slowly enough to notice. The same strategy automated
loses at whatever frequency the rate limits allow, in the small hours, correctly, and exactly as
designed.

## Tools this bears on

- [py-clob-client](https://predictionmarkets.tools/tools/py-clob-client.md) — Polymarket's own Python CLOB client - archived, and declared non-functional by its README.
- [kalshi-python](https://predictionmarkets.tools/tools/kalshi-python.md) — Kalshi's own generated Python client - closed-source, and unreleased since September 2025.
- [limitless-sdk](https://predictionmarkets.tools/tools/limitless-sdk.md) — Limitless Exchange's own async Python SDK - CLOB and NegRisk orders, WebSocket, MIT.
- [Polymarket US Python SDK](https://predictionmarkets.tools/tools/polymarket-us-python.md) — Official SDK for Polymarket US - installs as polymarket-us, unreleased since January.

## FAQ

### Which venues in this catalogue have a sandbox?

It has to be checked per venue, and the honest answers span the whole range. Limitless states plainly that there is no sandbox, testnet or mock mode and that every integration runs against production with real USDC. Polymarket US runs a preprod environment for its exchange API, on separate auth domains, with credentials requested per environment. Manifold publishes a dev websocket endpoint beside the production one.

### What should a bot do when it gets a 429?

Read the body, not the message string. Adjacent names the budget that blocked you and sends a Retry-After header; a 403 from Adjacent means the organisation holds no plan and retrying never helps. Polymarket US asks you to stop, wait at least a second and back off exponentially. Limitless says never to retry a 400 or a 401 at all.

### Does a 200 response mean my order filled?

Not on every venue. On a Limitless market with a taker delay, the order endpoint returns immediately with a settlement status of DELAYED and an eligibleAt timestamp, and the fill is observed on the order-event stream as a provisional match followed by a terminal mined or failed frame. The documentation asks you to keep the order open in your integration until a terminal event arrives.

### Can the exchange cancel my resting orders?

Yes, and not only for a fault of yours. Polymarket US documents that when a clarification is posted to a market's rules it may cancel resting orders so they are not executed under the clarified reading. That is a normal, documented event rather than an error, and a process that assumes an order it placed is still on the book will be wrong about its own position.

## Sources

1. [Rate Limits (Retail API)](https://docs.polymarket.us/api-reference/rate-limits) — Polymarket US, read 2026-09-21
2. [Rate Limits (Trader Guide)](https://docs.polymarket.us/trader-guide/rate-limits) — Polymarket US, read 2026-09-21
3. [Environments](https://docs.polymarket.us/trader-guide/environments) — Polymarket US, read 2026-09-21
4. [Trading Hours](https://docs.polymarket.us/learn/trading/access-and-limits/trading-hours) — Polymarket US, read 2026-09-21
5. [Market Clarification](https://docs.polymarket.us/learn/markets/clarifications) — Polymarket US, read 2026-09-21
6. [Order Types](https://docs.polymarket.us/learn/trading/basics/order-types) — Polymarket US, read 2026-09-21
7. [For Developers](https://docs.limitless.exchange/developers/introduction) — Limitless Exchange, read 2026-09-21
8. [API Reference, Rate limits](https://docs.limitless.exchange/api-reference/introduction) — Limitless Exchange, read 2026-09-21
9. [Order Events](https://docs.limitless.exchange/developers/websocket/order-events) — Limitless Exchange, read 2026-09-21
10. [Error Handling & Retry, Python SDK](https://docs.limitless.exchange/developers/sdk/python/error-handling) — Limitless Exchange, read 2026-09-21
11. [Changelog](https://docs.limitless.exchange/changelog) — Limitless Exchange, read 2026-09-21
12. [Manifold API](https://docs.manifold.markets/api) — Manifold, read 2026-09-21
13. [Rate limits](https://docs.adjacent.markets/rate-limits) — Adjacent, read 2026-09-21
14. [Changelog](https://docs.adjacent.markets/changelog) — Adjacent, read 2026-09-21

*Last updated 2026-09-21. A reference page, corrected in place — not a dated post.*
