Skip to main content
0xinsider on PyPI is the official Python client: one method for every operation in the OpenAPI document, typed from that document’s own schemas, a typed exception per API error, and paginate, which follows cursors for you. Source at 0xinsider/0xinsider-python.
You install 0xinsider and import oxinsider, because a Python module name cannot start with a digit. It needs Python 3.9 or newer and has one dependency, httpx. This page describes the released 0.4.0, which covers all 67 operations in the OpenAPI document it was generated from.

Run it without a key

Client.sandbox() points at https://0xinsider.com/sandbox and sends no credential. Every documented operation answers there with its example payload. Start without a key has the rules, including sandbox_status for error branches:

Then live data

Client() with no argument reads OXINSIDER_API_KEY, the same name the CLI and the MCP server use. Pass api_key= to supply it yourself, from your secret manager rather than a file in the repository. A live key needs an account with an active Pro subscription; see Authentication. Nothing else changes between the two clients. The methods, the arguments, the envelopes, and the cursor keys are the same.

Keep financial values exact

The trader and positions responses keep their display-safe numeric fields and add exact decimal atoms when their source values are verified. Use Python’s Decimal on the atom’s value; do not convert it through float.
Each atom also carries unit, scale, and basis. The exact block or an optional member can be absent when its source is unavailable; an absent value is not zero.

Method names

Every operation is a method named after its operationId in snake case: listLeaderboard becomes list_leaderboard, getMarketIntel becomes get_market_intel. Each returns the decoded JSON body, envelope included.
Compare OPENAPI_SHA256 with shasum -a 256 of https://0xinsider.com/api/v1/openapi.json to see whether your release is behind the API.

Types

Every operation is typed from the same document it is generated from. oxinsider.types holds a TypedDict for each request body, response envelope, and schema, and your editor infers them with no annotation of your own.
Nothing is validated, converted, or copied at runtime. The methods return the decoded JSON exactly as they always have, so upgrading changes what your type checker sees and nothing that runs. An omitted key and a null value are different facts, and neither is a zero. Read an optional field with .get() and say so when it is absent. A filter that guarantees a field does not change its type: min_grade="A" means every row has a grade, but the type still calls it optional, because the schema does. Read it with .get(), or cast the row when you are sure. A field this release does not know yet is still in the dictionary you get back. To read one, call client.request(...), which is typed Any, or upgrade the package. Resolving these annotations at runtime with typing.get_type_hints needs Python 3.10 or newer; reading the dictionaries does not.

Pagination

paginate follows next_cursor to the last page, keeping your filters fixed and moving only the cursor. Pagination has the cursor rules. It checks each page before yielding it and before spending another request, so a broken walk stops instead of looking like a finished one:
error.reason is invalid_envelope (the response is not a cursor-paginated list), invalid_data (data is not a list), missing_cursor (has_more is true with nothing to continue from), or repeated_cursor (a cursor this walk already requested, caught before the duplicate request). A PaginationError is a malformed response, never an exhausted collection. Pass progress=oxinsider.PaginationProgress() to read where a walk got to, and resume from progress.cursor (refetch the last page) or progress.next_cursor (continue past it). progress.stopped_by is set only when the walk ended on its own terms, which is what tells a partial walk from a complete one.

Headers on a successful call

client.with_response.<method>(...) calls the same operation and returns an ApiResponse instead of the body alone. Without it, a 200 discards everything but the body, including the ETag you need to revalidate with. monthly_quota, batch_rate_limit, request_cost, retry_after, and header(name) are there too. A header the API did not send reads None, never 0. A missing budget is unknown, not exhausted.

Errors

Every non-2xx response raises. The class follows the status, and status, code, and retry_after are attributes on it. All of them inherit oxinsider.OxinsiderError. The ones that carry an API body also inherit oxinsider.OxinsiderApiError. Errors lists every error.code behind them.

Other behavior worth knowing

What this client does not do

  • Place an order or hold a Polymarket key. Every method is a read except your own webhook and export calls.
  • Round anything. Money and price fields keep the API’s precision, so round them only when you display them.
  • Treat a missing field as 0. Missing means the provider did not report it.
  • Regenerate itself. A release names the document it was built from, and a newer operation needs a newer release.

Go next

Start without a key

Everything that works without a key.

Quickstart

The same 5 reads in curl, Python, and Go.

Authentication

Where a key belongs, and OAuth for an app with users.

Errors

Every code these exceptions carry.