Overview

Hyperliquid uses two distinct signing mechanisms with different chain IDs and purposes:
TypeChain IDDomainPurpose
L1 Actions1337”Exchange”Trading operations: order, cancel, cancelByCloid, modify, batchModify, scheduleCancel, updateLeverage, updateIsolatedMargin, vaultTransfer, subAccountTransfer
User-Signed0x66eee”HyperliquidSignTransaction”Administrative operations: approveAgent, usdSend, spotSend, usdClassTransfer, withdraw, approveBuilderFee, tokenDelegate
Unlike info endpoints that can be queried without authentication, exchange endpoints require cryptographic signatures to ensure security and prevent unauthorized access.
Exchange endpoints will not work without proper signatures. The Hyperliquid Python SDK v0.18.0+ handles signing complexity internally.

Types of signatures

1. L1 Action signatures (Trading operations)

L1 actions use a phantom agent construction - a temporary signing identity created from your action’s hash:
  • Chain ID: 1337 (NOT Arbitrum’s 42161)
  • Domain: “Exchange”
  • Serialization: Msgpack binary format
  • Implementation guide: L1 Action signing guide

2. User-Signed actions (Administrative operations)

User-signed actions use direct EIP-712 signing without phantom agent abstraction:
  • Chain ID: 0x66eee (421614 in decimal)
  • Domain: “HyperliquidSignTransaction”
  • Serialization: Direct JSON structure
  • Implementation guide: User-signed actions guide

Key concepts

Phantom Agent

A cryptographic construct (not a real wallet) used for L1 actions:
  1. Action serialized with msgpack
  2. Nonce and vault address appended
  3. Data hashed with keccak256
  4. Temporary “agent” object created with hash as connectionId
  5. This phantom agent is signed via EIP-712

Agent Wallet

A separate keypair authorized to sign L1 actions on behalf of your account:
  • Stateless: No funds or positions
  • Nonce isolation: Independent nonce tracking
  • Limited scope: Can only sign L1 actions, not transfers
  • Approved via: User-signed action (approveAgent)

Signature components

Every signature consists of three components:
{
  "r": "0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef",
  "s": "0xfedcba0987654321fedcba0987654321fedcba0987654321fedcba0987654321", 
  "v": 27
}
  • r — First 32 bytes of the ECDSA signature
  • s — Second 32 bytes of the ECDSA signature
  • v — Recovery ID (27 or 28) used to recover the public key

Architecture

L1 Actions → Phantom Agent → ChainId 1337

           Agent Wallet (approved via user-signed)

User-Signed → Direct EIP-712 → ChainId 0x66eee

Authentication flow

1

Choose signing mechanism

Determine if you need L1 actions (trading) or user-signed actions (admin/transfers)
2

Prepare the action

Create the action object with operation details
3

Add timestamp

Use current timestamp in milliseconds as nonce
4

Sign appropriately

L1 actions: Use phantom agent construction User-signed: Use direct EIP-712 signing
5

Send the request

Include signature, action, and nonce in request body

Complete list of supported actions

L1 Actions (Chain ID: 1337)

These actions use phantom agent construction with msgpack serialization.
ActionDescriptionCategory
orderPlace new ordersTrading
cancelCancel orders by order IDTrading
cancelByCloidCancel orders by client order IDTrading
modifyModify existing ordersTrading
batchModifyModify multiple orders at onceTrading
scheduleCancelSchedule order cancellationTrading
updateLeverageAdjust leverage for positionsPosition Management
updateIsolatedMarginManage isolated marginPosition Management
vaultTransferTransfer between vault accountsInternal Transfers
subAccountTransferTransfer between sub-accountsInternal Transfers
noopNo operation (for testing signatures)Utility
For implementation details and code examples, see the L1 Action signing guide.

User-Signed Actions (Chain ID: 0x66eee)

These actions use direct EIP-712 signing with JSON structure.
ActionDescriptionCategory
approveAgentAuthorize an agent wallet to trade on your behalfAgent Management
usdSendTransfer USDC between accountsFund Transfers
spotSendTransfer spot tokensFund Transfers
usdClassTransferTransfer between USD classesFund Transfers
withdrawWithdraw funds to Layer 1Withdrawals
approveBuilderFeeApprove builder fee structuresAdvanced
tokenDelegateDelegate token voting rightsAdvanced
For implementation details and code examples, see the User-signed actions guide.

Common issues and solutions

Wrong chain ID

Error: Signature verification failed
Cause: Using incorrect chain ID (especially using Arbitrum’s 42161)
Solution:
  • L1 actions: Use Chain ID 1337 (NOT 42161)
  • User-signed: Use Chain ID 0x66eee (421614 in decimal)

Invalid nonce

Error: Invalid or expired nonce
Cause: Nonce is too old, in the future, or not in milliseconds
Solution: Use current timestamp in milliseconds: get_timestamp_ms() or Date.now()

Signature type mismatch

Error: Unauthorized or invalid signature
Cause: Mixing up signing mechanisms or serialization
Solution:
  • L1 actions: Use phantom agent with msgpack serialization
  • User-signed: Use direct EIP-712 with JSON structure

Agent issues

Error: Agent not approved / Agent already exists
Cause: Using unapproved agent or duplicate agent name
Solution:
  • Approve agent first with exchange.approve_agent()
  • Use unique agent names for each bot/integration

Invalid action format

Error: Failed to deserialize / Invalid action
Cause: Missing required fields or wrong structure
Solution: Ensure action payloads include all required fields (e.g., grouping for orders)

Best practices

DO
  • Use the official SDK when possible for automatic signature handling
  • Keep your private keys secure and never expose them in code
  • Use environment variables or secure key management systems
  • Implement proper error handling for signature failures
  • Test with small amounts on mainnet or use testnet first
DON’T
  • Share your private keys or commit them to version control
  • Reuse nonces across different requests
  • Use placeholder signatures in production
  • Skip signature validation in your implementation

Official SDKs

The official SDKs handle all signing complexity internally, including phantom agent construction and EIP-712 formatting.

Python SDK

  • Repository: hyperliquid-python-sdk
  • Version: v0.18.0+ required
  • Features:
    • Automatic phantom agent construction for L1 actions
    • Built-in wrapper functions for all user-signed actions
    • Support for both mainnet and testnet

Rust SDK

  • Repository: hyperliquid-rust-sdk
  • Features:
    • Full L1 action support
    • User-signed action support
    • High-performance implementation

Installation

Python:
pip install hyperliquid-python-sdk
Rust:
[dependencies]
hyperliquid-rust-sdk = "0.3"

Testing your implementation

  1. Start with testnet: Use https://api.hyperliquid-testnet.xyz for testing
  2. Verify signatures locally: Ensure your signatures are properly formatted before sending
  3. Use small amounts: Test with minimal amounts when moving to mainnet
  4. Monitor rate limits: Respect API rate limits to avoid being blocked

Implementation guides

Key points to remember

  • Info endpoints don’t require signatures and can be accessed directly
  • Exchange endpoints require appropriate signing based on the action type
  • L1 actions use phantom agent construction with Chain ID 1337
  • User-signed actions use direct EIP-712 signing with Chain ID 0x66eee
  • Agent wallets can only perform L1 actions, not transfers or withdrawals