> ## Documentation Index
> Fetch the complete documentation index at: https://docs.uniblock.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# SDK Compatibility

> Reuse existing Hyperliquid SDKs against Uniblock's Info API by overriding the base URL and injecting your API key.

Because Uniblock forwards the native Hyperliquid `/info` contract verbatim, most existing Hyperliquid SDKs work against Uniblock unchanged — you only override the **base URL** and inject your **API key** header. The request bodies the SDK builds and the responses it parses stay identical.

<Info>
  Grab your API key from the
  [Uniblock dashboard](https://dashboard.uniblock.dev).
</Info>

## What to override

| Setting         | Value                                              |
| --------------- | -------------------------------------------------- |
| Base URL        | `https://api.uniblock.dev/uni/v1/hyperliquid/info` |
| Query parameter | `chainId=999` (mainnet) or `chainId=998` (testnet) |
| Auth header     | `x-api-key: YOUR_API_KEY`                          |

If your SDK exposes a configurable base URL and a way to attach default headers, that's all you need.

## Python (`hyperliquid-python-sdk`)

The official SDK takes a `base_url` and lets you pass a custom session. Point the base URL at Uniblock and attach your key as a default header:

```python theme={null}
import os
import requests
from hyperliquid.info import Info

session = requests.Session()
session.headers.update({"x-api-key": os.environ["UNIBLOCK_API_KEY"]})

# The SDK posts to `{base_url}/info`, so use the route prefix as the base.
info = Info(
    base_url="https://api.uniblock.dev/uni/v1/hyperliquid",
    skip_ws=True,
)
info.session = session  # reuse the authenticated session

state = info.user_state("0x0000000000000000000000000000000000000000")
print(state)
```

<Note>
  The SDK appends `/info` to the base URL. Set the base to the
  `.../uni/v1/hyperliquid` prefix so the final URL resolves to
  `.../uni/v1/hyperliquid/info`. If your SDK version doesn't send the `chainId`
  query parameter, Uniblock defaults to `999` (mainnet).
</Note>

## Raw / custom clients

If you built a thin client yourself, override the endpoint and header once and leave every call site unchanged:

```javascript theme={null}
const client = {
  baseUrl: "https://api.uniblock.dev/uni/v1/hyperliquid/info?chainId=999",
  headers: {
    "Content-Type": "application/json",
    "x-api-key": process.env.UNIBLOCK_API_KEY,
  },
  info(body) {
    return fetch(this.baseUrl, {
      method: "POST",
      headers: this.headers,
      body: JSON.stringify(body),
    }).then((r) => r.json());
  },
};

await client.info({ type: "metaAndAssetCtxs" });
```

## Notes & limits

* **Synthetic types are Uniblock-only.** `portfolioState`, `batchClearinghouseStates`, and `batchPortfolioStates` aren't part of the public contract, so SDKs won't have typed helpers for them — send them as raw bodies. See the [Info API overview](/guides/hyperliquid/info-api/overview).
* **WebSocket transports differ.** SDKs that open a WebSocket to Hyperliquid's public endpoint won't reach Uniblock's stream automatically — set `skip_ws=True` (or the equivalent) and use [Uniblock's WebSockets](/guides/hyperliquid/websockets/overview) for streaming.
* **Signing is unaffected.** Uniblock only changes transport and auth; any exchange/signing flow the SDK performs is untouched.
