Skip to main content
Two things answer with no account, no key, and no card:
  1. The Pick of the Day ledger on api.0xinsider.com, which is production data.
  2. The sandbox at https://0xinsider.com/sandbox, which answers every documented operation with its example payload.
Start with the first, use the second to shape your code, then swap 2 things for live data.

1 request, real data

One settled entry, as the route returned it:
The hash was published 1 hour before kickoff, and the nonce and the payload came after the game settled. SHA-256 over the payload bytes plus the decoded nonce reproduces commitment_hash, so you can check the pick did not move. A live pick is sealed: it carries the hash, sealed_at, and kickoff, and nothing that states a side or a price. The route takes no parameters and returns the whole ledger, one entry per (pick_date, pick_rank), with entry_count, sealed_count, opened_count, and uncommitted_count alongside entries. Any query parameter you add is ignored and named in the X-Query-Ignored response header. 0xinsider/picks mirrors it into a public git history and ships a verify.py. That is the whole onboarding for read-and-verify work. Nothing below is needed for it.

Every other operation: the sandbox

The sandbox is the second servers entry of the OpenAPI document. Append any documented path to https://0xinsider.com/sandbox and you get that operation’s documented example: the same envelope, the same field names, the same types, the same cursor keys. Every response carries X-Oxi-Sandbox: true. Every value is one the live API could return: a grade is a grade letter, platform is polymarket, an address is 40 hex characters, and a trader’s id is trd_ plus that address. None of it is real. The wallets all start 0x51ab and no Polymarket wallet does, the markets are named “Sandbox Rovers” and “Sandbox Open”, and the seven rows never change. The sandbox proves your parsing, your error branches, your pagination and your request shapes. It proves nothing about grades, prices, or flow.

Page through a list

Every cursor-paginated list serves the same seven rows.
Follow next_cursor until it is null: sbx_3 gives rows 4 to 6, sbx_6 gives the last row with has_more: false and next_cursor: null. Write the loop here and it terminates. A cursor the sandbox did not issue, or one past the end, is 400 bad_request with error.reason cursor_expired, which is what the live API returns for a cursor that no longer resolves.

It refuses what the live API refuses

Documented query parameters and JSON request bodies are checked against the same OpenAPI document the sandbox answers from:
  • a value outside its schema is 400 with error.reason invalid_query;
  • a body that is missing, is not JSON, or does not fit the request schema is 400 invalid_body, with error.param naming the field;
  • a body without Content-Type: application/json is 415 unsupported_media_type;
  • an unknown query name is ignored and reported in X-Query-Ignored, and X-Query-Validation: strict makes it 400 unknown_query_parameter. Successful reads also carry X-Effective-Query.
So a client that sends a shape the live API rejects finds out here, before it has a key.

Simulate an error before you meet one

Any status the operation documents works: 400, 401, 402, 403, 404, 423, 429, 500, or 503. A 429 or 503 carries Retry-After: 60 and error.retry_at. Write the branch for each one here, where a mistake costs nothing. Errors lists the codes.

The sandbox key is optional

A 201 returns an oxi_sk_test_ key, the sandbox base URL, and every URL on the path to live access. Use it when your client or your agent framework insists on a credential. The sandbox answers the same with or without it, nothing is stored, and the key cannot be listed or revoked. The live API refuses it with 401 invalid_api_key and error.reason sandbox_api_key. That is deliberate: a sandbox key can never touch production data by accident. Register an agent has the fields.

Move to live data

Live data is a paid product. 3 steps, and only the first has a wait:
1

Subscribe to Pro

Pricing. Without it every data route answers 402 subscription_required.
2

Generate the key

Developers, then Generate token. The full key shows once.
3

Change 2 things in your code

The base URL becomes https://api.0xinsider.com, and every request carries Authorization: Bearer $OXINSIDER_API_KEY. Field names, envelopes, and cursors do not change.
Every official client makes step 3 one line:

What this does not give you

  • A free tier on production data. The 6 public routes, the Remote MCP handshake, and the sandbox are everything that works without a key. Everything else needs Pro.
  • Real numbers from the sandbox. A pnl of 1284500.42 belongs to a wallet that does not exist.
  • A stream, a Markdown context document, or an export file from the sandbox. Those answer 400 there.
  • A sandbox key that works on the live API, or a live key that changes a sandbox answer.

Go next

Quickstart

The same 5 reads, keyless first, then live.

Python client

pip install 0xinsider, sandbox in 3 lines.

Go client

go get github.com/0xinsider/0xinsider-go.

Authentication

The 6 public routes, the 2 credentials, and where a key belongs.