A lightweight, fully-typed WebSocket client for the Deribit API (v2). Built on JSON-RPC 2.0 over WebSocket with automatic reconnection, scope-aware authentication, and generic response modifiers.
- Installation
- Quick Start
- Client Initialization
- Architecture
- API Surface
- Response Shape
- Response Modifiers
- Error Handling
- Enums & Types Reference
- Scope & Permissions
- WebSocket Behavior
- Build & Distribution
npm install @wrytes/deribit-api-client
# or
pnpm add @wrytes/deribit-api-clientimport { createDeribitClient, createDeribitClientPublic, GrantType, Currency } from '@wrytes/deribit-api-client'
// Public client — no credentials needed
const client = createDeribitClientPublic()
const currencies = await client.market.getCurrencies({})
console.log(currencies.result)
// Authenticated client
const authClient = createDeribitClient({
type: GrantType.client_credentials,
baseUrl: 'wss://www.deribit.com/ws/api/v2',
clientId: 'YOUR_CLIENT_ID',
clientSecret: 'YOUR_CLIENT_SECRET',
})
const summary = await authClient.account.getAccountSummary({ currency: Currency.BTC })
console.log(summary.result)
// Close the connection when done
authClient.close()Use createDeribitClientPublic for read-only market data that does not require authentication.
import { createDeribitClientPublic, GrantType } from '@wrytes/deribit-api-client'
// Uses wss://www.deribit.com/ws/api/v2 by default
const client = createDeribitClientPublic()
// Override the base URL (e.g. testnet)
const testClient = createDeribitClientPublic({
type: GrantType.client_public,
baseUrl: 'wss://test.deribit.com/ws/api/v2',
})Use createDeribitClient with GrantType.client_credentials to access private endpoints. Authentication happens automatically when the WebSocket connection opens.
import { createDeribitClient, GrantType } from '@wrytes/deribit-api-client'
const client = createDeribitClient({
type: GrantType.client_credentials,
baseUrl: 'wss://www.deribit.com/ws/api/v2',
clientId: 'YOUR_CLIENT_ID',
clientSecret: 'YOUR_CLIENT_SECRET',
})Type definitions:
type ClientPublicOptions = {
type: GrantType.client_public
baseUrl: string
}
type ClientCredentialsOptions = {
type: GrantType.client_credentials
baseUrl: string
clientId: string
clientSecret: string
}
type ClientOptions = ClientPublicOptions | ClientCredentialsOptionsDeribitApiClient
├── .account → AccountMapping
├── .market → MarketMapping
├── .trading → TradingMapping
├── .wallet → WalletMapping
├── .authentication → AuthenticationMapping
├── .session → SessionMapping (placeholder)
└── .subscription → SubscriptionMapping (placeholder)
Internally, all methods call client.send(), which:
- Verifies the WebSocket is open (reconnects if needed)
- Validates that the client has required auth/scope for private endpoints
- Sends a JSON-RPC 2.0 request with a unique numeric ID
- Returns a
Promisethat resolves when the matching response arrives (10s timeout)
The core send signature (for library authors / contributors):
send<RequestParams, ApiResult, Modifier = RequestQuery<ApiResult>>(
method: string,
scope: string[],
params: RequestParams,
callback?: (data: RequestQuery<ApiResult>) => Modifier
): Promise<Modifier>All account methods require an authenticated client with at least account:read scope.
Returns a full account summary for a single currency.
import { Currency } from '@wrytes/deribit-api-client'
const res = await client.account.getAccountSummary({
currency: Currency.BTC,
extended: true, // include user details and fees (optional)
subaccount_id: 123, // optional
})
console.log(res.result.balance)
console.log(res.result.equity)
console.log(res.result.margin_balance)Params:
| Field | Type | Required | Description |
|---|---|---|---|
currency |
Currency |
Yes | Target currency |
subaccount_id |
number |
No | Subaccount to query |
extended |
boolean |
No | Include user details and fee info |
Returns account summaries for all currencies in a single call.
const res = await client.account.getAccountSummaries({ extended: false })
console.log(res.result.summaries) // GetAccountSummariesItem[]Returns the current position for a specific instrument.
const res = await client.account.getPosition({
instrument_name: 'BTC-PERPETUAL',
})
// Returns GetPositionResultAll | GetPositionResultOption
// Discriminated by `kind` field
if (res.result.kind === 'option') {
console.log(res.result.delta) // option-specific fields
} else {
console.log(res.result.size)
}Returns portfolio margin calculations and risk metrics for a currency.
const res = await client.account.getPortfolioMargins({
currency: Currency.ETH,
simulated_positions: { 'ETH-PERPETUAL': 1.5 }, // optional
})Returns a paginated transaction history for a currency and time window.
import { TransactionQuery } from '@wrytes/deribit-api-client'
const res = await client.account.getTransactionLog({
currency: Currency.BTC,
start_timestamp: 1700000000000,
end_timestamp: Date.now(),
query: TransactionQuery.trade,
count: 50,
continuation: undefined, // use res.result.continuation for next page
})
console.log(res.result.logs) // TransactionLog[]
console.log(res.result.continuation) // pass this to get the next pageAll market methods are public — no authentication required.
Returns all supported currencies with their withdrawal configurations.
const res = await client.market.getCurrencies({})
console.log(res.result) // MarketGetCurrenciesResult[]Returns all instruments for a currency, optionally filtered by kind.
import { InstrumentKind } from '@wrytes/deribit-api-client'
const res = await client.market.getInstruments({
currency: 'BTC',
kind: InstrumentKind.option,
expired: false, // exclude expired instruments
})Returns market data (bid, ask, last, volume, funding, etc.) for all instruments in a currency.
const res = await client.market.getBookSummaryByCurrency({
currency: Currency.ETH,
kind: InstrumentKind.future,
})Returns market book data for a single instrument.
const res = await client.market.getBookSummaryByInstrument({
instrument_name: 'BTC-PERPETUAL',
})
console.log(res.result.mark_price)
console.log(res.result.current_funding)
console.log(res.result.volume_usd)Returns the current spot index price and estimated delivery price for an index.
const res = await client.market.getIndexPrice({
index_name: 'btc_usd',
})
console.log(res.result.index_price)
console.log(res.result.estimated_delivery_price)Returns historical delivery prices for a given index, with pagination.
import { MarketGetDeliveryPricesNames } from '@wrytes/deribit-api-client'
const res = await client.market.getDeliveryPrices({
index_name: MarketGetDeliveryPricesNames.btc_usd,
offset: 0,
count: 25,
})Returns OHLC candles for a volatility index over a time range.
const res = await client.market.getVolatilityIndexData({
currency: 'BTC',
start_timestamp: 1700000000000,
end_timestamp: Date.now(),
resolution: '3600', // 1 | 60 | 3600 | 43200 | 86400 | '1D'
})
// res.result.data: VolatilityIndexDataPoint[]
// res.result.continuation: string | undefinedAll trading methods require an authenticated client.
| Method | Required Scope |
|---|---|
buy |
trade:read_write |
sell |
trade:read_write |
cancel |
trade:read_write |
getOpenOrdersByCurrency |
trade:read |
getOpenOrdersByInstrument |
trade:read |
getOrderState |
trade:read |
Places a buy order.
import { OrderType, TimeInForce } from '@wrytes/deribit-api-client'
const res = await client.trading.buy({
instrument_name: 'BTC-PERPETUAL',
amount: 10,
type: OrderType.limit,
price: 60000,
time_in_force: TimeInForce.good_til_cancelled,
post_only: true,
reduce_only: false,
label: 'my-order-1',
})
console.log(res.result.order) // OrderState
console.log(res.result.trades) // Trade[]Places a sell order. Same parameters and return shape as buy.
const res = await client.trading.sell({
instrument_name: 'ETH-PERPETUAL',
amount: 1,
type: OrderType.market,
})Cancels an open order by ID.
const res = await client.trading.cancel({
order_id: 'ETH-123456789',
})
console.log(res.result.order_state) // 'cancelled'Returns all open orders for a currency.
const res = await client.trading.getOpenOrdersByCurrency({
currency: 'BTC',
kind: 'future', // optional
type: 'limit', // optional
})
console.log(res.result) // OrderState[]Returns all open orders for a specific instrument.
const res = await client.trading.getOpenOrdersByInstrument({
instrument_name: 'BTC-PERPETUAL',
})Returns the current state of a single order.
const res = await client.trading.getOrderState({
order_id: 'BTC-987654321',
})
console.log(res.result.filled_amount)
console.log(res.result.order_state)All wallet methods require an authenticated client.
| Method | Required Scope |
|---|---|
withdraw |
wallet:read_write |
cancelWithdrawal |
wallet:read_write |
cancelTransferById |
wallet:read_write |
createDepositAddress |
wallet:read_write |
getWithdrawals |
wallet:read |
getDeposits |
wallet:read |
getTransfers |
wallet:read |
getCurrentDepositAddress |
wallet:read |
Initiates a withdrawal.
import { WalletWithdrawPriority } from '@wrytes/deribit-api-client'
const res = await client.wallet.withdraw({
currency: Currency.BTC,
address: '1A1zP1eP5QGefi2DMPTfTL5SLmv7Divf0a',
amount: 0.01,
priority: WalletWithdrawPriority.high,
})Returns paginated withdrawal history.
const res = await client.wallet.getWithdrawals({
currency: Currency.ETH,
count: 20,
offset: 0,
})
console.log(res.result.count) // total withdrawals
console.log(res.result.data) // WalletGetWithdrawalsItem[]Returns paginated deposit history.
const res = await client.wallet.getDeposits({
currency: Currency.USDC,
count: 20,
offset: 0,
})Returns paginated internal transfer history.
const res = await client.wallet.getTransfers({
currency: Currency.BTC,
count: 10,
})Returns the current deposit address for a currency, or null if none exists.
const res = await client.wallet.getCurrentDepositAddress({
currency: Currency.BTC,
})
if (res.result) {
console.log(res.result.address)
}Generates a new deposit address for a currency.
const res = await client.wallet.createDepositAddress({
currency: Currency.ETH,
})
console.log(res.result.address)Cancels a pending withdrawal by numeric ID.
const res = await client.wallet.cancelWithdrawal({
currency: Currency.BTC,
id: 42,
})Cancels an internal transfer by numeric ID.
const res = await client.wallet.cancelTransferById({
currency: Currency.BTC,
id: 7,
})The authentication mapping is used internally when the client is initialized with GrantType.client_credentials. Direct usage is available for custom flows.
import { GrantType } from '@wrytes/deribit-api-client'
const res = await client.authentication.auth({
grant_type: GrantType.client_credentials,
client_id: 'YOUR_CLIENT_ID',
client_secret: 'YOUR_CLIENT_SECRET',
})
console.log(res.result.access_token)
console.log(res.result.scope)
console.log(res.result.expires_in)Every method returns a Promise<RequestQuery<Result>>, which is a discriminated union:
// Success
type RequestQueryReceived<ApiResult> = {
jsonrpc: `${number}.${number}`
id: number
result: ApiResult // the actual payload
testnet: boolean
usDiff: number // server processing time (microseconds)
usIn: number // time until request received (microseconds)
usOut: number // time until response sent (microseconds)
}
// API-level error
type RequestQueryError = {
jsonrpc: `${number}.${number}`
id: number
error: {
code: number
message: string
data?: any
}
testnet: boolean
usDiff: number
usIn: number
usOut: number
}
type RequestQuery<ApiResult> = RequestQueryReceived<ApiResult> | RequestQueryErrorCheck for errors by inspecting the response:
const res = await client.market.getIndexPrice({ index_name: 'btc_usd' })
if ('error' in res) {
console.error(res.error.message)
} else {
console.log(res.result.index_price)
}Every method accepts an optional second argument — a callback that transforms the raw response before the Promise resolves. This is useful for extracting just the result or reshaping data inline.
// Return only the result payload, not the full JSON-RPC envelope
const price = await client.market.getIndexPrice(
{ index_name: 'eth_usd' },
(res) => ('result' in res ? res.result.index_price : null)
)
console.log(price) // number | nullThe generic type parameter is inferred from the modifier's return type:
// TypeScript infers res as number
const balance = await client.account.getAccountSummary(
{ currency: Currency.BTC },
(data) => ('result' in data ? data.result.balance : 0)
)Client-level errors are thrown (not returned) and have a code and message:
| Error | Code | Cause |
|---|---|---|
ErrorClientNotReady |
-1 |
WebSocket is not in OPEN state |
ErrorClientRequestTimeout |
-2 |
No response received within 10 seconds |
ErrorClientRestrictedToPublic |
-3 |
Private method called on a public client |
ErrorClientRestrictedToScope |
-4 |
Client lacks required scope for the method |
import {
ErrorClientNotReady,
ErrorClientRequestTimeout,
ErrorClientRestrictedToPublic,
ErrorClientRestrictedToScope,
} from '@wrytes/deribit-api-client'
try {
const res = await client.trading.buy({ ... })
} catch (err: any) {
if (err.code === ErrorClientRestrictedToPublic.code) {
console.error('Use an authenticated client for trading.')
} else if (err.code === ErrorClientRequestTimeout.code) {
console.error('Request timed out.')
}
}API-level errors (invalid params, insufficient balance, etc.) are returned in the response body — see Response Shape.
enum GrantType {
client_public = 'client_public'
client_credentials = 'client_credentials'
client_signature = 'client_signature'
refresh_token = 'refresh_token'
}enum Currency {
BTC = 'BTC'
ETH = 'ETH'
USDC = 'USDC'
USDT = 'USDT'
EURR = 'EURR'
}enum InstrumentKind {
future = 'future'
option = 'option'
spot = 'spot'
future_combo = 'future_combo'
option_combo = 'option_combo'
}enum OrderType {
limit = 'limit'
market = 'market'
stop_limit = 'stop_limit'
stop_market = 'stop_market'
}enum TimeInForce {
good_til_cancelled = 'good_til_cancelled'
good_til_day = 'good_til_day'
fill_or_kill = 'fill_or_kill'
immediate_or_cancel = 'immediate_or_cancel'
}enum WalletWithdrawPriority {
insane = 'insane'
extreme_high = 'extreme_high'
very_high = 'very_high'
high = 'high'
mid = 'mid'
low = 'low'
very_low = 'very_low'
}Filter type for getTransactionLog:
enum TransactionQuery {
trade, maker, taker, open, close, liquidation,
buy, sell, withdrawal, delivery, settlement, deposit,
transfer, option, future, correction, block_trade, swap
}enum GetPositionDirection {
buy = 'buy'
sell = 'sell'
zero = 'zero'
}type OrderState = {
order_id: string
instrument_name: string
direction: 'buy' | 'sell'
order_type: string
order_state: 'open' | 'filled' | 'rejected' | 'cancelled' | 'untriggered'
amount: number
filled_amount: number
price: number
average_price: number
label: string
creation_timestamp: number
last_update_timestamp: number
time_in_force: string
reduce_only: boolean
post_only: boolean
}type Trade = {
trade_id: string
order_id: string
instrument_name: string
direction: 'buy' | 'sell'
amount: number
price: number
fee: number
fee_currency: string
timestamp: number
}type RateLimit = {
rate: number // requests per second
burst: number // maximum burst capacity
}
type AccountLimits = {
matching_engine: {
block_rfq_maker: RateLimit
cancel_all: RateLimit
guaranteed_mass_quotes: RateLimit
maximum_mass_quotes: RateLimit
maximum_quotes: RateLimit
spot: RateLimit
trading: { total: RateLimit }
}
limits_per_currency: boolean
non_matching_engine: RateLimit
}Supported index names for delivery prices — covers major crypto pairs with _usd, _usdc, and _usdt suffixes:
ada_usd, algo_usd, avax_usd, bch_usd, btc_usd, doge_usd, dot_usd, eth_usd,
link_usd, ltc_usd, matic_usd, near_usd, shib_usd, sol_usd, trx_usd, uni_usd,
usdc_usd, xrp_usd, btcdvol_usdc, ethdvol_usdc,
... and _usdc / _usdt variants of the above
When authenticated, the client stores scopes returned by the auth endpoint and uses them to validate private requests. The scopes correspond to the Deribit OAuth 2.0 permission model:
| Scope | Methods |
|---|---|
account:read |
All client.account.* methods |
trade:read |
getOpenOrdersByCurrency, getOpenOrdersByInstrument, getOrderState |
trade:read_write |
buy, sell, cancel |
wallet:read |
getWithdrawals, getDeposits, getTransfers, getCurrentDepositAddress |
wallet:read_write |
withdraw, createDepositAddress, cancelWithdrawal, cancelTransferById |
Requesting a method without the required scope will throw ErrorClientRestrictedToScope.
- Protocol: WebSocket JSON-RPC 2.0
- Default URL:
wss://www.deribit.com/ws/api/v2 - Testnet URL:
wss://test.deribit.com/ws/api/v2 - Auto-reconnect: 60 seconds after connection closes
- Request timeout: 10 seconds per individual request
- Authentication: Automatic on socket open for
client_credentialsclients
JSON-RPC 2.0 request format:
{
"jsonrpc": "2.0",
"id": 1,
"method": "public/get_index_price",
"params": { "index_name": "btc_usd" }
}Responses are matched to pending requests by their id field. Unmatched or timed-out requests are rejected via the timeout error.
# Install dependencies
pnpm install
# Build for distribution (CommonJS + ESM + type defs)
pnpm npm:build
# TypeScript compile only
pnpm build
# Publish to npm
pnpm npm:publishOutput:
| File | Format | Use |
|---|---|---|
dist/index.js |
CommonJS | Node.js require() |
dist/index.mjs |
ESM | import / bundlers |
dist/index.d.ts |
TypeScript | IDE type checking |
Built with tsup. Source in src/, compiled to dist/.
MIT