HyperVaults Docs
Gate API

Quickstart

From a bot key to your first order, end to end

This is the whole flow: get a key, resolve a market, place an order, read it back. Everything here is typed parameters over HTTP — the gate builds and signs the Hyperliquid action for you.

0. Where is the gate?

The order gate is platform-hosted infrastructure — it holds the signing credentials for every vault's agent, so you don't (and can't) run your own. Point your client at your gate endpoint:

export GATE="https://<your-gate-endpoint>"   # ask your onboarding contact
# local development against a self-run stack:
export GATE="http://localhost:8787"

A public production gate endpoint is being finalized. Until it is published, programmatic trading runs against a development gate — confirm your endpoint during manager onboarding.

1. Get a bot key

Mint one from Manage → Trading agent → Bot API keys (see authentication). Copy the secret — it is shown once.

export KEY="hvk_…"
export VAULT="0xYourVaultAddress"

2. Resolve the market

Order routing is by numeric asset id, which you resolve from Hyperliquid's meta for the network you trade (ids differ between mainnet and testnet — see assets & formatting and Hyperliquid's Asset IDs):

# Native perp: the index of the coin in the perp universe.
export HL="https://api.hyperliquid.xyz/info"   # testnet: api.hyperliquid-testnet.xyz
curl -s -XPOST $HL -d '{"type":"meta"}' \
  | jq '.universe | to_entries[] | select(.value.name=="BTC") | .key'
# → 0 on mainnet.  dex is 0 for native perps.

3. Place an order

curl -s -XPOST "$GATE/vaults/$VAULT/orders" \
  -H "Authorization: Bearer $KEY" -H "Content-Type: application/json" \
  -d '{"asset":0,"dex":0,"isBuy":true,"limitPx":"55000","sz":"0.001","reduceOnly":false,"tif":"Gtc"}'
# → {"status":"ok","response":{"type":"order","data":{"statuses":[{"resting":{"oid":...}}]}}}

Check response.data.statuses[] — a rejection can arrive inside a status:"ok" envelope ({"error":"..."}). See the error model.

4. Read it back

The gate is write-only; read state from Hyperliquid's info API, addressing the vault address:

curl -s -XPOST $HL -d "{\"type\":\"frontendOpenOrders\",\"user\":\"$VAULT\"}"

Builder-dex (HIP-3) orders need the dex param — see the per-dex trap.

A minimal client (Node)

const GATE = process.env.GATE, KEY = process.env.KEY, VAULT = process.env.VAULT;

async function place(order) {
  const res = await fetch(`${GATE}/vaults/${VAULT}/orders`, {
    method: 'POST',
    headers: { 'Content-Type': 'application/json', Authorization: `Bearer ${KEY}` },
    body: JSON.stringify(order),
  });
  const body = await res.json();
  if (res.status !== 200) throw new Error(body.error ?? `gate ${res.status}`);
  // HL can reject per-order inside an ok envelope.
  const err = body.response?.data?.statuses?.find((s) => s.error)?.error;
  if (err) throw new Error(err);
  return body.response.data.statuses[0];
}

console.log(await place({
  asset: 0, dex: 0, isBuy: true,
  limitPx: '55000', sz: '0.001', reduceOnly: false, tif: 'Gtc',
}));

That is the complete integration surface — every other action (full list) is the same POST with different typed params.

On this page