Error Response Format

All errors follow a consistent JSON structure:
{
  "error": {
    "code": "ERROR_CODE",
    "message": "Human-readable description of the error"
  }
}
The HTTP status code indicates the error category, while the code field provides a machine-readable identifier for programmatic handling.

Error Codes Reference

Authentication Errors

CodeHTTP StatusDescription
INVALID_API_KEY401Missing, invalid, or expired API key
SIGNATURE_ERROR401Invalid wallet signature for trading operations
SESSION_EXPIRED401Agent/signer session has expired; re-approve

Validation Errors

CodeHTTP StatusDescription
INVALID_PARAMS400Request parameters failed validation
MISSING_REQUIRED_FIELD400A required field was not provided

Provider Errors

CodeHTTP StatusDescription
UNSUPPORTED_PROVIDER400Provider does not exist or does not support this operation
UNSUPPORTED_NETWORK400Network (mainnet/testnet) not available for this provider
PROVIDER_ERROR502Upstream provider returned an unexpected error
PROVIDER_UNAVAILABLE503Upstream provider is temporarily unreachable

Trading Errors

CodeHTTP StatusDescription
INSUFFICIENT_MARGIN422Not enough margin/collateral for this order
ORDER_NOT_FOUND404Order ID does not exist or has already been filled/canceled
ORDER_REJECTED422Order was rejected by the exchange
INVALID_ORDER400Order parameters are invalid (e.g., bad side, type)
PRICE_TOO_FAR422Limit price is too far from mark price
SIZE_TOO_SMALL422Order size is below the minimum for this market
MAX_LEVERAGE_EXCEEDED422Requested leverage exceeds the maximum for this market
POSITION_NOT_FOUND404No open position found for the specified market
REDUCE_ONLY_REJECTED422Reduce-only order would increase position size
TOO_MANY_ORDERS422Maximum open orders limit reached

General Errors

CodeHTTP StatusDescription
RATE_LIMITED429Rate limit exceeded
NOT_FOUND404Requested resource does not exist
INTERNAL_ERROR500Unexpected server error

Handling Errors

async function placeOrder(params: OrderParams) {
  const response = await fetch("https://api.perps.studio/v1/perps/hyperliquid/orders", {
    method: "POST",
    headers: {
      "X-API-Key": API_KEY,
      "Content-Type": "application/json",
    },
    body: JSON.stringify(params),
  });

  if (!response.ok) {
    const { error } = await response.json();

    switch (error.code) {
      case "INSUFFICIENT_MARGIN":
        console.error("Not enough margin. Deposit more collateral.");
        break;
      case "RATE_LIMITED":
        const retryAfter = response.headers.get("Retry-After");
        console.error(`Rate limited. Retry in ${retryAfter}s`);
        break;
      case "PROVIDER_UNAVAILABLE":
        console.error("Exchange is temporarily down. Retry later.");
        break;
      default:
        console.error(`Error ${error.code}: ${error.message}`);
    }
    return null;
  }

  return response.json();
}

Provider-Specific Errors

When an upstream provider returns an error, the Provider API wraps it in a PROVIDER_ERROR or a more specific code when possible. The original provider error message is preserved in the message field.
{
  "error": {
    "code": "ORDER_REJECTED",
    "message": "Hyperliquid: Order would immediately cross. Use IOC or adjust price."
  }
}
Provider error messages are prefixed with the provider name so you can always tell which exchange generated the error.