Sandbox

A full paper-trading environment on the real engine — mint a test key, trade virtual money, reset, and receive sandbox webhooks.

The sandbox lets you build and test an integration end to end with zero real-money risk. It is not a mock: paper orders run on the real LMSR pricing engine against isolated virtual balances (Paper vs live).

Where the sandbox is on

The sandbox is gated by DEVELOPER_SANDBOX_ENABLED, and the flag’s state is per environment:

EnvironmentSandboxWhy
Staging (https://staging.drazill.com)OnStaging (and development) turn it on automatically when the flag is not pinned — apply_staging_demo_product_defaults, app/core/config.py.
Production (https://api.drazill.com)OffProduction keeps every such flag at its False default; arming one there is an explicit owner action.

So the end-to-end flow on this page — mint a drzl_test_ key, trade paper, receive sandbox webhooks — works on staging today, which is exactly the environment the interactive API Explorer targets. Start at Get an API key.

An operator can still pin the flag off for a specific staging window (DEVELOPER_SANDBOX_ENABLED=false). When it is off, test keys cannot be minted, the paper endpoints are unavailable, and the dashboard mints live-class keys only.

Mint a test key

Create a key with environment: "test" (or request the env:paper scope). It carries the drzl_test_ prefix. As with any key, the full secret is shown once — store it.

POST /api/v1/api-keys
{ "name": "My bot (sandbox)", "environment": "test" }

Paper routing

With a drzl_test_ key, the ordinary trading endpoints route onto the paper engine:

You callWith a test key
Trading endpoints (place/cancel orders)Execute as paper trades on isolated paper_* state
Market dataSame real market data as live
A real-money endpoint (e.g. a live deposit/withdrawal)403 TEST_KEY_LIVE_ENDPOINT — a paper key can never touch real funds

Reset

Paper state is yours to reset while iterating (paper positions, balances, and orders live in the isolated paper tables). Fund a fresh paper balance from the staging test-deposit flow and start clean — nothing you do in the sandbox affects real markets or real wallets.

Stage a lifecycle event

Waiting for a market to resolve — or for trading to halt — is a bad way to test the code that handles those events. /api/v1/sandbox lets you make each one happen on demand, against your own paper scope, in any environment, without an admin.

VerbWhat it doesWhat it does not do
POST /sandbox/fillsCompletes (or partially completes) a paper fill at a price you choose: paper trade, position and wallet rows move, and the order.filled webhook fires with livemode: false.Touch any real order, trade or wallet.
POST /sandbox/resolutionsSettles your paper positions on a market at an outcome you choose — $1.00/share for the winner — and delivers a sandbox market.resolved event.Change the real market’s status. This is a settlement drill; paper trading on that market continues afterwards.
POST /sandbox/haltsHalts your paper order placement on a market for up to 60 minutes. Your paper orders are then rejected with the same MARKET_CLOSED error a real halt raises.Halt the market for anyone else, or write the real halt table. DELETE /sandbox/halts/{market_id} clears it early.
GET /sandbox/configThe capability manifest.Say anything at all when the sandbox is off — it returns {"enabled": false} and nothing more.
Python
client = DrazillClient(api_key=api_key, base_url=base_url)
return client.sandbox.stage_fill(
models.SandboxFillRequest(
market_id=market_id,
outcome_id=outcome_id,
side="BUY",
price="0.5000",
quantity="5",
),
# An Idempotency-Key is REQUIRED on every scenario verb: a retried stage
# must not stage twice. Generate it once and reuse it on every retry.
request_options=RequestOptions(idempotency_key=f"replay-quickstart-{uuid.uuid4()}"),
)

These endpoints are reachable only with a drzl_test_ key. A live key gets a 403 — there is no live scope mapping for /api/v1/sandbox at all, and the route refuses a live key again with SANDBOX_LIVE_KEY_REFUSED. Every verb requires an Idempotency-Key header, so a retried request stages the scenario exactly once.

Everything these verbs write lands in paper_* tables scoped to your own key’s user. Real orders, trades, wallets, market halts and AMM price state are untouched by construction — and that is proved, not asserted: a test runs the whole verb set and asserts every real-money table is byte-identical before and after.

Replay real market history

A test key also opens wss://staging.drazill.com/api/v1/ws/replay, which streams a market’s recorded trade tape, quote-at-trade and price ticks — and accepts simulated orders that fill against subsequent recorded prints. See Backtesting & replay for the full contract, including exactly what replay does and does not contain.

Realtime with a test key

A drzl_test_ key with the websocket scope connects to the WebSocket feed exactly like a live key and reads the same real market data:

ChannelWith a test key
prices:, market:, category:Subscribed — same data as live
orderbook:, trades:Subscribed, subject to the same feed tier as a live key
user:{your_id} — your private order/fill/wallet streamRefused, with TEST_KEY_LIVE_CHANNEL

Your user: channel carries live-money activity — real fills, real cancels, real wallet moves. A sandbox credential does not observe it, which is the same separation the REST wall gives you (403 TEST_KEY_LIVE_ENDPOINT), applied to the socket. Two consequences worth knowing before you write the code:

  • A test-key connection is not auto-subscribed to user:{your_id} on connect. The connected frame comes back with an empty channels array. That is expected, not a failed handshake.
  • If you re-authenticate a live-key session with a test key mid-connection, any user: channel that session already held is dropped at that moment.

Paper fills do not currently emit realtime frames — paper activity reaches you through sandbox webhooks instead. So the honest picture is: use the WebSocket with a test key for market data, and webhooks for your paper order lifecycle.

Sandbox webhooks

Webhook endpoints are segregated by livemode. Register an endpoint with livemode: false to receive sandbox events driven by your test-key / paper activity; livemode: true endpoints receive live events. The two streams never cross, so you can wire and verify your webhook handler entirely against paper traffic before going live — including the events the scenario verbs above raise. See Webhooks.

When you’re ready to go live

Mint a drzl_live_ key, point at https://api.drazill.com, and run the same code against real markets — subject to your scopes and the compliance gate.