---
title: "Submit a signed Hyperliquid withdrawal (step 2 of 2)"
method: POST
path: "/exchanges/hyperliquid/withdraw"
tags: ["Hyperliquid"]
---

# Submit a signed Hyperliquid withdrawal (step 2 of 2)

`POST /exchanges/hyperliquid/withdraw`

## Request

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

Forwards your main wallet's signed `withdraw3` action to Hyperliquid. Kairos verifies the signature parses and then passes it through; the venue re-verifies it covers `destination`, `amount` and `time`, so a field altered after signing is rejected upstream.
**Irreversible.** A withdrawal that Hyperliquid accepts cannot be recalled. Kairos does not validate the destination address.
**No Kairos-side idempotency.** There is no in-flight tracking and no dedupe: calling this twice with the same `time` sends the same signed action twice, and the ONLY protection against a double withdrawal is Hyperliquid rejecting the replayed nonce. Do not build a blind retry loop on this endpoint.
**A `400` conflates two very different outcomes.** `Hyperliquid rejected withdrawal: …` is returned both for a genuine venue rejection AND for an HTTP/network failure reaching the venue — the underlying error type collapses them. On that error you cannot tell whether the withdrawal landed; query Hyperliquid directly before retrying.
Hyperliquid's own withdrawal minimum and flat fee are enforced venue-side and surface through that same `400`.
**Auth & scope.** Requires `trade:execute` for `hyperliquid`, wallet ownership, and the mutation gate. Not rate limited.

## Request body

- OrderHyperliquidWithdrawRequest
  - `wallet_address` string, required
  - `amount` string, required
  - `time` integer, required: The `time` from prepare. Doubles as the nonce — Hyperliquid's replay protection is the only thing preventing a duplicate withdrawal.
  - `signature` string, required: 0x-prefixed 65-byte signature over the prepared typed data, produced by the main wallet. Kairos never signs a withdrawal.
  - `destination` string, nullable: Defaults to `wallet_address`. Must match what you signed, or Hyperliquid rejects it.

## Response `200`

The withdrawal was submitted to Hyperliquid. Submission only — not a settlement confirmation.

- OrderHyperliquidActionResponse: Response for `POST /exchanges/hyperliquid/withdraw` and `POST /exchanges/hyperliquid/transfer`.
  - `success` boolean, required
  - `message` string, required: `Withdrawal submitted` or `Transfer submitted`. Submission only — not a confirmation of settlement.

## Other responses

- `400`: `ValidationInvalidOrder` — invalid user id, `Invalid withdraw amount: …`, or `Invalid withdrawal signature: …`. **Also** `InternalError` with message `Hyperliquid rejected withdrawal: …`, which covers venue rejection and network failure indistinguishably.
- `401`: No valid credential presented — missing/invalid API-key headers or an invalid/expired session token.
- `403`: Missing scope, provider access disabled, or wallet not owned by the caller.
- `500`: `DatabaseError`.
- `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)
