Skip to main content

API Key Authentication

All programmatic access to the Limitless Exchange API requires authentication. The simplest method is an API key.
Cookie-based session authentication has been removed. Use API keys or scoped API tokens for all programmatic access.

Getting an API Key

1

Log in to Limitless Exchange

Go to limitless.exchange and connect your wallet.
2

Open API key settings

Click your profile menu (top right) → select “Api keys”.
3

Generate a new key

Create a new key. It will start with lmts_....

Using Your API Key

Include the key in all requests via the X-API-Key header:
# REST API
curl -H "X-API-Key: lmts_your_key_here" https://api.limitless.exchange/markets

# WebSocket - pass as header during connection handshake

Authentication Methods

MethodHeadersUse Case
API KeyX-API-Key: lmts_...Individual traders, bots, data access
Scoped API Token (HMAC)lmts-api-key, lmts-timestamp, lmts-signaturePartners, delegated signing, sub-account management

Scoped API Tokens (HMAC)

For partners and advanced integrations, Limitless supports scoped API tokens with HMAC-SHA256 request signing. These tokens provide fine-grained access control through scopes.

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.

HMAC Request Signing

Every request is signed with HMAC-SHA256. The server verifies the signature using the token’s secret. 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
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

Scoped API tokens require a partner setup. Contact hey@limitless.network to get started. Once enabled, you can derive tokens via POST /auth/api-tokens/derive while authenticated with Privy.
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 API key or scoped token handles request authentication.