Skip to main content

Overview

All programmatic access to the Limitless Exchange API requires authentication via scoped API tokens with HMAC-SHA256 request signing.
API keys are deprecated and no longer available for new users. Existing API key users should migrate to scoped API tokens. See Legacy API Keys below.

Scoped API Tokens (HMAC)

Scoped API tokens are the authentication method for the Limitless Exchange API. Every request is authenticated by signing it with HMAC-SHA256 using your token’s secret. Tokens are scoped to control what actions they can perform.

Scopes

ScopeDescription
tradingPlace and cancel orders. Required base scope for delegated_signing.
account_creationCreate sub-account profiles under your partner account.
delegated_signingServer signs orders on behalf of sub-accounts (requires trading scope). Enables Web2 partners to submit orders without end users managing private keys.
withdrawalWithdraw ERC20 balances from managed server-wallet sub-accounts to partner-owned addresses.

HMAC Request Signing

Required headers:
HeaderDescription
lmts-api-keyYour token ID (received at token creation)
lmts-timestampISO-8601 timestamp (must be within 30 seconds of server time)
lmts-signatureBase64-encoded HMAC-SHA256 signature
SDK users should pass HMAC credentials to the SDK client (hmacCredentials / hmac_credentials / WithHMACCredentials) and let the SDK build these headers automatically. Manual header signing is only needed when you call the REST API directly.
Canonical message format:
{ISO-8601 timestamp}\n{HTTP METHOD}\n{request path with query string}\n{request body}
The path component must include the full request URL path and query string (e.g., /orders/all/btc-100k?onBehalfOf=42), not just the pathname. For requests without a query string, use the plain path (e.g., /orders). For GET requests, the body component is an empty string.
Example (TypeScript):
import { createHmac } from 'crypto';

function signRequest(
  tokenId: string,
  secret: string,     // base64-encoded, received at token creation
  method: string,
  path: string,
  body: string = '',
): Record<string, string> {
  const timestamp = new Date().toISOString();
  const message = `${timestamp}\n${method}\n${path}\n${body}`;

  const signature = createHmac('sha256', Buffer.from(secret, 'base64'))
    .update(message)
    .digest('base64');

  return {
    'lmts-api-key': tokenId,
    'lmts-timestamp': timestamp,
    'lmts-signature': signature,
  };
}

// Usage
const headers = signRequest(tokenId, secret, 'POST', '/orders', JSON.stringify(orderPayload));
const res = await fetch('https://api.limitless.exchange/orders', {
  method: 'POST',
  headers: { ...headers, 'Content-Type': 'application/json' },
  body: JSON.stringify(orderPayload),
});
Example (Python):
import hmac, hashlib, base64
from datetime import datetime, timezone

def sign_request(token_id: str, secret: str, method: str, path: str, body: str = "") -> dict:
    timestamp = datetime.now(timezone.utc).isoformat()
    message = f"{timestamp}\n{method}\n{path}\n{body}"

    signature = base64.b64encode(
        hmac.new(
            base64.b64decode(secret),
            message.encode("utf-8"),
            hashlib.sha256,
        ).digest()
    ).decode("utf-8")

    return {
        "lmts-api-key": token_id,
        "lmts-timestamp": timestamp,
        "lmts-signature": signature,
    }

Getting a Scoped API Token

1

Log in to Limitless Exchange

Go to limitless.exchange and connect your wallet.
2

Derive a token

Derive a scoped token via POST /auth/api-tokens/derive. Pass the token field from the Privy authenticate response (not privy_access_token) in the identity header as Bearer <token>. The response includes a tokenId and secret. This is a one-time setup — use the HMAC credentials for all subsequent requests.
The trading scope is available to all users — no application required. For partner-level scopes (account_creation, delegated_signing), apply for programmatic API access to get your account enabled.
The token secret is returned once at creation time. Store it securely — it cannot be retrieved again.

Delegated Signing

With the delegated_signing scope, partners can submit orders without providing signature and signatureType in the order payload. The server signs the order using a Privy server wallet linked to the target sub-account. Use the onBehalfOf field in the order payload to specify which sub-account the order is for. The target profile must be linked to your partner account.

Checksummed Addresses

All Ethereum addresses in API requests must use checksummed format (EIP-55 mixed-case):
  • x-account header
  • maker and signer fields in orders
Example: 0x5aAeb6053F3E94C9b9A09f33669435E7Ef1BeAed
Your private key is still required for EIP-712 order signing (unless using delegated signing), but the scoped token handles request authentication.

Legacy API Keys

API keys are deprecated and are no longer issued to new users. If you have an existing API key, it will continue to work, but we recommend migrating to scoped API tokens for improved security and access control.
Existing API key users authenticate via the X-API-Key header:
curl -H "X-API-Key: lmts_your_key_here" https://api.limitless.exchange/markets
MethodHeadersUse Case
Scoped API Token (HMAC)lmts-api-key, lmts-timestamp, lmts-signatureAll new integrations — traders, bots, partners, delegated signing
API Key (deprecated)X-API-Key: lmts_...Legacy users only — no longer issued