TypeScript SDK

drazill — typed, native fetch, with a WebSocket client and webhook verification.

The drazill package is generated from the contract and MIT-licensed. Requires Node.js 18+ (uses native fetch and FormData). Drazill is the canonical client export.

Install

$npm install drazill

The package is unscopeddrazill, not @drazill/sdk — so it matches the Python package name on PyPI exactly.

An unconfigured client talks to staging (https://staging.drazill.com/api/v1), never production — pass baseUrl or set DRAZILL_BASE_URL to target another environment.

Quickstart

Point the client at an environment with DRAZILL_BASE_URL (defaults to staging). List open markets:

quickstart_markets.ts
1const client = new Drazill({ apiKey: API_KEY, baseUrl: BASE_URL });
2console.log(`→ Drazill API @ ${BASE_URL}\n`);
3
4// 1) List a page of open markets.
5const page = await client.markets.listMarkets({ status: "ACTIVE", limit: 5, sort_by: "volume" });
6console.log(`Open markets (${page.total} total, showing ${page.items.length}):`);
7for (const m of page.items) {
8 console.log(`${m.title}`);
9 console.log(` id=${m.id} slug=${m.slug} volume=${m.total_volume}`);
10}

Lifted verbatim from the tested example sdks/typescript/examples/quickstart_markets.ts. See Quickstart for the full walkthrough.

Place an order idempotently

Preview a quote, then place the order binding the quote token and an idempotency key, so a client-side retry can’t double-place:

quickstart_trade.ts
1const idempotencyKey = `quickstart-trade-${crypto.randomUUID()}`;
2const result = (await client.orders.placeOrder(
3 {
4 market_id: market.id,
5 outcome_id: outcomeId,
6 side: "BUY",
7 type: "MARKET",
8 quantity: ORDER_QTY,
9 preview_quote_token: quote.quote_token,
10 },
11 { include_receipt: true },
12 { idempotencyKey },
13)) as any;

WebSocket

Connect, then subscribe per channel with a handler. prices:{outcome_id} gives price ticks, orderbook:{outcome_id} gives depth, trades:{market_id} gives the tape:

Realtime
1const ws = client.ws();
2ws.connect();
3
4ws.subscribe("orderbook:OUTCOME_UUID", (data) => console.log("Order book:", data));
5ws.subscribe("trades:MARKET_UUID", (data) => console.log("New trade:", data));
6ws.subscribe("prices:OUTCOME_UUID", (data) => console.log("Price:", data));
7
8ws.on("connected", () => console.log("Connected"));
9ws.on("disconnected", () => console.log("Disconnected"));
10ws.on("error", (data) => console.log("Error:", data));
11
12ws.disconnect();

(client is the initialized Drazill client from the quickstart.)

Verify webhooks

Verify the signature before trusting an inbound webhook, then construct the typed event:

webhooks.ts
1export async function handleWebhook(
2 rawBody: string,
3 headers: Headers,
4 secret: string,
5) {
6 const isValid = await verifyWebhookSignature(rawBody, headers, secret);
7 if (!isValid) {
8 throw new Error("Invalid Drazill webhook signature");
9 }
10
11 return constructWebhookEvent(rawBody, headers, secret);
12}

The full webhook contract (signing, retries, replay) is under Webhooks.

Retries, pagination & errors

The client accepts a maxRetries option (retries 5xx and 429, honouring Retry-After), exports cursor iterators (paginateCursor / paginateOffset) for for await iteration, and throws typed errors (ApiError, AuthenticationError, RateLimitError, ValidationError) — RateLimitError.retryAfter carries the backoff. See the SDK README and Rate limits.