---
title: "Build the typed data for a Hyperliquid withdrawal (step 1 of 2)"
method: POST
path: "/exchanges/hyperliquid/withdraw/prepare"
tags: ["Hyperliquid"]
---

# Build the typed data for a Hyperliquid withdrawal (step 1 of 2)

`POST /exchanges/hyperliquid/withdraw/prepare`

## Request

- Base URL: `https://execution.kairos.trade`
- URL: `https://execution.kairos.trade/exchanges/hyperliquid/withdraw/prepare`
- Auth: API key in header `X-Client-Id` and API key in header `X-Api-Key` and API key in header `X-Api-Secret`

Builds the EIP-712 `withdraw3` payload for a USDC withdrawal from Hyperliquid to an Arbitrum address. **Kairos never signs a withdrawal** — your main wallet does, and this endpoint only hands you the bytes.
**This call is pure.** It writes nothing, reserves nothing, and has no side effects. Never calling `POST /exchanges/hyperliquid/withdraw` afterwards has zero consequence.
**`destination` defaults to `wallet_address`.** Omit it and you withdraw to yourself. If you set it, be certain: Kairos validates only the *amount*, never the destination address, and a signed withdrawal to a wrong address is irreversible.
**No server-side binding between prepare and submit.** The submit endpoint accepts any well-formed `{amount, time, destination, signature}` — correctness rests entirely on Hyperliquid re-verifying your signature. Prepare is a convenience, not a control.
**Auth & scope.** Requires `trade:execute` for `hyperliquid`, wallet ownership, and the mutation gate. Not rate limited.

## Request body

- OrderHyperliquidWithdrawPrepareRequest: Body for `POST /exchanges/hyperliquid/withdraw/prepare`. This call is PURE — it writes nothing and has no side effects; it only builds the typed data for you to sign.
  - `wallet_address` string, required: The Hyperliquid main wallet. Must be owned by the authenticated caller.
  - `amount` string, required: USDC amount as a plain decimal string. Only ASCII digits and a single `.` not in first position are accepted, and it must parse to a finite value > 0 — `1e5`, `.5`, `-1`, `inf` and `NaN` are all rejected. Kairos enforces NO minimum and NO maximum; Hyperliquid's own withdrawal minimum and flat fee are applied venue-side.
  - `destination` string, nullable: Arbitrum destination address. **Defaults to `wallet_address`** (withdraw to self) when omitted. Kairos does NOT validate this address — see the endpoint description.

## Response `200`

Typed data to sign, plus the `time` nonce to echo back.

- OrderHyperliquidWithdrawPrepareResponse
  - `typed_data` object, required: The EIP-712 typed data for Hyperliquid's `withdraw3` action. Sign this with the main wallet.
  - `time` integer, required: Millisecond timestamp that is ALSO the action's nonce. Pass it back unchanged to `POST /exchanges/hyperliquid/withdraw`.
  - `destination` string, required
  - `amount` string, required

## Other responses

- `400`: `ValidationInvalidOrder` — invalid user id, or `Invalid withdraw amount: …` (not a plain positive decimal).
- `401`: No valid credential presented — missing/invalid API-key headers or an invalid/expired session token.
- `403`: "This API key lacks the trade:execute scope", API-key access to `hyperliquid` disabled, or "Wallet not found or does not belong to you".
- `500`: `DatabaseError`, or `InternalError` — "Hyperliquid signing misconfigured".
- `503`: API-key access to `hyperliquid` could not be checked (fails closed).

---

[API](https://skmtc.dev/kairos/apis/kairos-order-execution-api.md) - [All operations](https://skmtc.dev/kairos/apis/kairos-order-execution-api/llms.txt) - [OpenAPI document](https://skmtc.dev/kairos/apis/kairos-order-execution-api/revisions/9ba7d463d505?raw)
