---
title: "Hyperliquid JavaScript & TypeScript SDK for Node.js | Siebly"
description: "Hyperliquid JavaScript SDK preview with TypeScript-first Info and Exchange clients, Spot and perpetual workflows, WebSockets, WebSocket API requests, Testnet, proxies, and examples."
canonical: "https://siebly.io/sdk/hyperliquid/javascript"
---

# Hyperliquid JavaScript SDK

Build with the Hyperliquid REST API and WebSockets using the JavaScript SDK, TypeScript-first declarations, and Node.js-compatible runtime patterns.

Use the same TypeScript-first REST API and WebSocket clients from plain JavaScript or TypeScript in Node.js-compatible runtimes.

## Install

```shell
# Via your favourite package manager, e.g. npm:
npm install @siebly/hyperliquid-api
# or pnpm:
pnpm install @siebly/hyperliquid-api
# or yarn:
yarn add @siebly/hyperliquid-api
```

- [npm: @siebly/hyperliquid-api](https://www.npmjs.com/package/@siebly/hyperliquid-api)
- [GitHub repository](https://github.com/sieblyio/hyperliquid-api)
- [README](https://github.com/sieblyio/hyperliquid-api#readme)
- [Hyperliquid examples](/examples/Hyperliquid)

## Coverage

- Perpetuals
- Spot
- Account State
- WebSockets
- WebSocket API
- Testnet
- Framework-neutral JavaScript snippets that stay approachable in Node.js-compatible runtimes.
- TypeScript-first package declarations for stricter services, shared libraries, and editor-assisted integrations.

## Integration Profile

**REST API:** Use the Hyperliquid SDK for Info queries, account state, asset resolution, and signed Exchange actions across perpetual and Spot markets.

**WebSockets:** Use WebsocketClient for public and address-scoped subscriptions, or WebsocketAPIClient for awaitable Info and signed Exchange requests over WebSocket.

**Reliability:** Keep network, asset, account address, signer, and transport explicit; inspect every Exchange response status and rebuild account state after a stream gap.

## Quickstart

Get started with just a few lines of JavaScript. TypeScript, while not required, is absolutely recommended. TypeScript declarations are included with all our SDKs and provide convenient definitions on request & response fields, WebSocket payloads, and generally safer integrations.

### REST API

```typescript
import { RestClient } from '@siebly/hyperliquid-api';

const client = new RestClient();

async function main() {
  try {
    const status = await client.getExchangeStatus();
    console.log('Exchange status:', status);
  } catch (error) {
    console.error('Exchange-status request failed:', error);
  }

  try {
    const mids = await client.getAllMids();
    console.log('BTC midpoint:', mids.BTC);
  } catch (error) {
    console.error('Midpoint request failed:', error);
  }

  try {
    const metadata = await client.getPerpMetadata();
    const btc = metadata.universe.find((asset) => asset.name === 'BTC');
    console.log('BTC perpetual metadata:', btc);
  } catch (error) {
    console.error('Perpetual metadata request failed:', error);
  }

  try {
    const orderBook = await client.getOrderBook({
      coin: 'BTC',
    });
    console.log('Best bid:', orderBook?.levels[0][0]);
    console.log('Best ask:', orderBook?.levels[1][0]);
  } catch (error) {
    console.error('Order-book request failed:', error);
  }

  try {
    const candles = await client.getCandles({
      coin: 'BTC',
      interval: '1h',
      startTime: Date.now() - 24 * 60 * 60 * 1000,
    });
    console.log('Latest hourly candle:', candles.at(-1));
  } catch (error) {
    console.error('Candle request failed:', error);
  }

  try {
    const trades = await client.getRecentTrades({
      coin: 'BTC',
    });
    console.log('Most recent trade:', trades[0]);
  } catch (error) {
    console.error('Recent-trade request failed:', error);
  }
}

main();
```

[View the source example](https://github.com/sieblyio/hyperliquid-api/blob/main/examples/rest-public.ts)

### WebSocket Streams

```typescript
import { WebsocketClient } from '@siebly/hyperliquid-api';

const client = new WebsocketClient();

async function main() {
  client
    .on('open', ({ wsKey }) => {
      console.log('WebSocket opened:', wsKey);
    })
    .on('reconnecting', ({ wsKey, event }) => {
      console.log('WebSocket reconnecting:', wsKey, event);
    })
    .on('reconnected', ({ wsKey }) => {
      console.log('WebSocket reconnected:', wsKey);
    })
    .on('close', ({ wsKey }) => {
      console.log('WebSocket closed:', wsKey);
    })
    .on('exception', ({ wsKey, event }) => {
      console.error('WebSocket exception:', wsKey, event);
    });

  try {
    await client.subscribe({ type: 'allMids' }, (update) => {
      console.log('BTC midpoint:', update.mids.BTC);
    });
  } catch (error) {
    console.error('Midpoint subscription failed:', error);
  }

  try {
    await client.subscribe({ type: 'l2Book', coin: 'BTC' }, (book) => {
      console.log('Best bid:', book.levels[0][0]);
      console.log('Best ask:', book.levels[1][0]);
    });
  } catch (error) {
    console.error('Order-book subscription failed:', error);
  }

  try {
    await client.subscribe({ type: 'trades', coin: 'BTC' }, (trades) => {
      console.log('Trades:', trades);
    });
  } catch (error) {
    console.error('Trade subscription failed:', error);
  }

  try {
    await client.subscribe(
      { type: 'candle', coin: 'BTC', interval: '1m' },
      (candle) => {
        console.log('One-minute candle:', candle);
      },
    );
  } catch (error) {
    console.error('Candle subscription failed:', error);
  }
}

main();
```

[View the source example](https://github.com/sieblyio/hyperliquid-api/blob/main/examples/websocket-subscriptions.ts)

### WebSocket API

```typescript
import { randomBytes } from 'node:crypto';
import { WebsocketAPIClient } from '@siebly/hyperliquid-api';

const privateKey = process.env.HYPERLIQUID_TESTNET_API_WALLET_KEY;
const accountAddress = process.env.HYPERLIQUID_TESTNET_ACCOUNT_ADDRESS;

if (!privateKey || !accountAddress) {
  throw new Error(
    'Set HYPERLIQUID_TESTNET_API_WALLET_KEY and HYPERLIQUID_TESTNET_ACCOUNT_ADDRESS before starting.',
  );
}

const client = new WebsocketAPIClient({
  privateKey,
  accountAddress,
  testnet: true,
});

function trimDecimal(value) {
  if (!value.includes('.')) {
    return value;
  }
  return value.replace(/0+$/, '').replace(/\.$/, '');
}

function sizeForNotional(price, szDecimals, targetNotional) {
  const factor = 10 ** szDecimals;
  const size = Math.ceil((targetNotional / Number(price)) * factor) / factor;
  return trimDecimal(size.toFixed(szDecimals));
}

async function main() {
  client
    .on('open', ({ wsKey }) => {
      console.log('WebSocket API opened:', wsKey);
    })
    .on('reconnected', ({ wsKey }) => {
      console.log('WebSocket API reconnected:', wsKey);
    })
    .on('exception', ({ wsKey, event }) => {
      console.error('WebSocket API exception:', wsKey, event);
    });

  let btc;
  let orderBook;

  try {
    const metadata = await client.getPerpMetadata();
    btc = metadata.universe.find((asset) => asset.name === 'BTC');
    console.log('BTC metadata:', btc);
  } catch (error) {
    console.error('WebSocket metadata request failed:', error);
    client.closeAll();
    return;
  }

  if (!btc) {
    console.error('BTC was not returned by the Testnet perpetual metadata.');
    client.closeAll();
    return;
  }

  try {
    orderBook = await client.getOrderBook({ coin: 'BTC' });
    console.log('BTC order book received at:', orderBook?.time);
  } catch (error) {
    console.error('WebSocket order-book request failed:', error);
    client.closeAll();
    return;
  }

  const bid = orderBook?.levels[0][4] ?? orderBook?.levels[0][0];

  if (!bid) {
    console.error('The BTC order book did not contain a bid.');
    client.closeAll();
    return;
  }

  const clientOrderId = `0x${randomBytes(16).toString('hex')}`;
  const size = sizeForNotional(bid.px, btc.szDecimals, 12);
  let orderId;

  try {
    const result = await client.submitLimitOrder({
      symbol: 'BTC',
      side: 'buy',
      price: bid.px,
      size,
      postOnly: true,
      clientOrderId,
    });
    console.log('WebSocket order response:', result);

    if (result.status !== 'ok') {
      console.error('Hyperliquid rejected the order request:', result.response);
      client.closeAll();
      return;
    }

    const orderStatus = result.response.data?.statuses[0];

    if (!orderStatus) {
      console.error('The order response did not contain an order status.');
      client.closeAll();
      return;
    }

    if ('error' in orderStatus) {
      console.error('The order was rejected:', orderStatus.error);
      client.closeAll();
      return;
    }

    if ('filled' in orderStatus) {
      console.log('The order filled immediately:', orderStatus.filled);
      client.closeAll();
      return;
    }

    orderId = orderStatus.resting.oid;
    console.log('Resting order ID:', orderId);
  } catch (error) {
    console.error('WebSocket order submission failed:', error);
    client.closeAll();
    return;
  }

  try {
    const currentOrder = await client.getOrderStatus({ oid: orderId });
    console.log('Order before cancellation:', currentOrder);
  } catch (error) {
    console.error('WebSocket order-status request failed:', error);
  }

  try {
    const cancellation = await client.cancelOrdersByClientOrderId({
      cancels: [{ asset: 'BTC', cloid: clientOrderId }],
    });
    console.log('WebSocket cancellation response:', cancellation);
  } catch (error) {
    console.error('WebSocket cancellation failed:', error);
  }

  try {
    const finalOrder = await client.getOrderStatus({ oid: clientOrderId });
    console.log('Final WebSocket order state:', finalOrder);
  } catch (error) {
    console.error('Final WebSocket order-status request failed:', error);
  }

  client.closeAll();
}

main();
```

[View the source example](https://github.com/sieblyio/hyperliquid-api/blob/main/examples/websocket-api.ts)

## Hyperliquid JavaScript FAQ

### What does the Hyperliquid JavaScript SDK cover?

Hyperliquid supports Perpetuals, Spot, Account State, WebSockets, WebSocket API, and Testnet workflows. The JavaScript guide covers the main REST and WebSocket integration patterns.

### How do I authenticate private Hyperliquid API calls in JavaScript?

Install @siebly/hyperliquid-api from npm & pass API credentials into the SDK client options, as shown in the Hyperliquid JavaScript examples above. The SDK handles the exchange-specific signing requirements for private requests.

### Does the Hyperliquid JavaScript SDK help with WebSocket connection management?

Yes. Use the SDK WebSocket client for subscriptions, reconnect handling, and stream lifecycle management instead of building raw socket flows yourself.

### When should I use the Hyperliquid WebSocket API instead of REST?

Use REST for standard request and response workflows such as account queries and order management. Use the WebSocket API flow when you want persistent low-latency interactions over a connected session.

## Machine Resources

- [AI prompt framework](/ai)
- [LLM discovery](/llms.txt)
- [SDK catalog](/.well-known/siebly-sdk-catalog.json)
- [Agent skill](/.well-known/agent-skills/siebly-crypto-exchange-api/SKILL.md)
