npm package: @limitless-exchange/sdk
Description: TypeScript SDK for Limitless Exchange CLOB and NegRisk trading
Latest version: 1.0.5

# Limitless Exchange TypeScript SDK

**v1.0.5** | Production-Ready | Type-Safe | Fully Documented

A TypeScript SDK for interacting with the Limitless Exchange platform, providing type-safe access to CLOB and NegRisk prediction markets.

> 🎉 **v1.0.5 Release**: Adds `FAK` limit-order support and `postOnly` for `GTC` orders, with updated docs and examples. See [Changelog](#changelog) for details.

## ⚠️ Disclaimer

**USE AT YOUR OWN RISK**

This SDK is provided "as-is" without any warranties or guarantees. Trading on prediction markets involves financial risk. By using this SDK, you acknowledge that:

- You are responsible for testing the SDK thoroughly before using it in production
- The SDK authors are not liable for any financial losses or damages
- You should review and understand the code before executing any trades
- It is recommended to test all functionality on testnet or with small amounts first
- The SDK may contain bugs or unexpected behavior despite best efforts

**ALWAYS TEST BEFORE USING IN PRODUCTION WITH REAL FUNDS**

For production use, we strongly recommend:

1. Running comprehensive tests with your specific use case
2. Starting with small transaction amounts
3. Monitoring all transactions carefully
4. Having proper error handling and recovery mechanisms

**Feedback Welcome**: We encourage you to report any bugs, suggest improvements, or contribute to the project. Please submit issues or pull requests on our GitHub repository.

## 🌍 Geographic Restrictions

**Important**: Limitless restricts order placement from US locations due to regulatory requirements and compliance with international sanctions. Before placing orders, builders should verify their location complies with applicable regulations.

## Features

- ✅ **Authentication**: API key authentication with X-API-Key header
- ✅ **Order Management**: Create, cancel, and manage orders on CLOB and NegRisk markets
- ✅ **Market Data**: Access real-time market data and orderbooks
- ✅ **NegRisk Markets**: Full support for group markets with multiple outcomes
- ✅ **Error Handling & Retry**: Automatic retry logic for rate limits and transient failures
- ✅ **Type Safety**: Full TypeScript support with comprehensive type definitions
- ✅ **IEEE-Safe Order Payload Parsing**: `createOrder()` handles `makerAmount`, `takerAmount`, `price`, and `salt` returned as JSON strings
- ✅ **TSDoc Documentation**: Complete API documentation with examples
- ✅ **WebSocket**: Real-time price and position updates with API key auth

## Installation

```bash
npm install @limitless-exchange/sdk
# or
yarn add @limitless-exchange/sdk
# or
pnpm add @limitless-exchange/sdk
```

## Quick Start

### Fetching Active Markets (No Authentication Required)

```typescript
import { HttpClient, MarketFetcher } from '@limitless-exchange/sdk';

// Create HTTP client (no authentication needed)
const httpClient = new HttpClient({
  baseURL: 'https://api.limitless.exchange',

  // Optional: Add custom headers to all requests
  additionalHeaders: {
    'X-Custom-Header': 'my-value',
  },
});

const marketFetcher = new MarketFetcher(httpClient);

// Get markets sorted by LP rewards
const markets = await marketFetcher.getActiveMarkets({
  limit: 8,
  sortBy: 'lp_rewards', // 'lp_rewards' | 'ending_soon' | 'newest' | 'high_value'
});

console.log(`Found ${markets.data.length} of ${markets.totalMarketsCount} markets`);

// Pagination (page-based)
const page2 = await marketFetcher.getActiveMarkets({
  limit: 8,
  page: 2,
  sortBy: 'ending_soon',
});
```

See [examples/project-integration/src/active-markets.ts](https://github.com/limitless-labs-group/limitless-exchange-ts-sdk/blob/main/examples/project-integration/src/active-markets.ts) for more examples.

### Market Pages & Navigation (No Authentication Required)

```typescript
import { HttpClient, MarketPageFetcher } from '@limitless-exchange/sdk';

const httpClient = new HttpClient({
  baseURL: 'https://api.limitless.exchange',
});

const pageFetcher = new MarketPageFetcher(httpClient);

// Resolve a page from URL path
const page = await pageFetcher.getMarketPageByPath('/crypto');

// Fetch page markets with dynamic filters
const markets = await pageFetcher.getMarkets(page.id, {
  limit: 20,
  sort: '-updatedAt',
  filters: {
    duration: 'hourly',
    ticker: ['btc', 'eth'],
  },
});

if ('pagination' in markets) {
  console.log(`Total markets: ${markets.pagination.total}`);
}
```

Detailed guide: [docs/market-pages/README.md](https://github.com/limitless-labs-group/limitless-exchange-ts-sdk/blob/main/limitless-exchange-sdk/docs/market-pages/README.md)

### Authentication

The SDK uses API keys for authentication. API keys can be obtained from your Limitless Exchange account settings(Click on User Profile).

```typescript
import { HttpClient } from '@limitless-exchange/sdk';

// Option 1: Automatic from environment variable (recommended)
// Set LIMITLESS_API_KEY in your .env file
const httpClient = new HttpClient({
  baseURL: 'https://api.limitless.exchange',
});

// Option 2: Explicit API key
const httpClient = new HttpClient({
  baseURL: 'https://api.limitless.exchange',
  apiKey: process.env.LIMITLESS_API_KEY,
});

// All requests automatically include X-API-Key header
// For authenticated endpoints like portfolio, orders, etc.
```

**Environment Variables:**

Create a `.env` file:

```bash
# Required for authenticated endpoints
LIMITLESS_API_KEY=sk_live_your_api_key_here

# REQUIRED: Private key for order signing (EIP-712)
PRIVATE_KEY=0x...
```

### Partner API Token v3 / HMAC Usage

The SDK also supports partner-scoped HMAC credentials for api-token v3 workflows such as token self-service, partner-account creation, and delegated trading.

Use HMAC credentials only in a backend or BFF service. Do not expose partner HMAC secrets in browser bundles, frontend environment variables, or client-side storage.

Recommended setup:

- Keep public market and market-page reads in the browser.
- Store the real HMAC `tokenId` / `secret` on your backend.
- Use this SDK server-side to sign partner-authenticated requests.
- Expose only your own app-specific endpoints to the frontend.

See [`docs/code-samples/api-key-v3/`](https://github.com/limitless-labs-group/limitless-exchange-ts-sdk/tree/main/limitless-exchange-sdk/docs/code-samples/api-key-v3) for the partner HMAC examples.

### Token Approvals

**Important**: Before placing orders, you must approve tokens for the exchange contracts. This is a **one-time setup** per wallet.

#### Required Approvals

**CLOB Markets:**

- **BUY orders**: Approve USDC → `market.venue.exchange`
- **SELL orders**: Approve Conditional Tokens → `market.venue.exchange`

**NegRisk Markets:**

- **BUY orders**: Approve USDC → `market.venue.exchange`
- **SELL orders**: Approve Conditional Tokens → **both** `market.venue.exchange` AND `market.venue.adapter`

#### Quick Setup

Run the approval setup script:

```bash
# Copy .env.example and configure your wallet
cp docs/code-samples/.env.example docs/code-samples/.env

# Edit .env and set your PRIVATE_KEY and market slug
# Then run the approval script
npx tsx docs/code-samples/setup-approvals.ts
```

#### Manual Approval Example

```typescript
import { ethers } from 'ethers';
import { MarketFetcher, getContractAddress } from '@limitless-exchange/sdk';

// 1. Fetch market to get venue addresses
const market = await marketFetcher.getMarket('market-slug');

// 2. Create contract instances
const usdc = new ethers.Contract(
  getContractAddress('USDC'),
  ['function approve(address spender, uint256 amount) returns (bool)'],
  wallet
);

const ctf = new ethers.Contract(
  getContractAddress('CTF'),
  ['function setApprovalForAll(address operator, bool approved)'],
  wallet
);

// 3. Approve USDC for BUY orders
await usdc.approve(market.venue.exchange, ethers.MaxUint256);

// 4. Approve CT for SELL orders
await ctf.setApprovalForAll(market.venue.exchange, true);

// 5. For NegRisk SELL orders, also approve adapter
if (market.negRiskRequestId) {
  await ctf.setApprovalForAll(market.venue.adapter, true);
}
```

For complete examples, see [docs/code-samples/setup-approvals.ts](https://github.com/limitless-labs-group/limitless-exchange-ts-sdk/blob/main/limitless-exchange-sdk/docs/code-samples/setup-approvals.ts).

### Trading on NegRisk Markets

NegRisk markets are group markets with multiple related outcomes. Here's a quick example:

```typescript
import { OrderClient, MarketFetcher, Side, OrderType } from '@limitless-exchange/sdk';

// 1. Fetch NegRisk group market
const marketFetcher = new MarketFetcher(httpClient);
const groupMarket = await marketFetcher.getMarket('largest-company-end-of-2025-1746118069282');

// 2. Select a submarket (e.g., Apple)
const appleMarket = groupMarket.markets[0];
const marketDetails = await marketFetcher.getMarket(appleMarket.slug);

// 3. Create order client (userData fetched automatically from profile)
const orderClient = new OrderClient({
  httpClient,
  wallet,
});

// 4. Place order on submarket (not group!)
const order = await orderClient.createOrder({
  tokenId: marketDetails.tokens.yes,
  price: 0.5,
  size: 10,
  side: Side.BUY,
  orderType: OrderType.GTC,
  marketSlug: appleMarket.slug, // Use submarket slug
});
```

**Important**: Always use the **submarket slug** for NegRisk orders, not the group market slug!

For more details, see the [NegRisk Trading Guide](https://github.com/limitless-labs-group/limitless-exchange-ts-sdk/blob/main/limitless-exchange-sdk/docs/orders/README.md#negrisk-markets).

### GTC Orders (Limit Orders)

GTC orders use `price` + `size` and can optionally set `postOnly` to reject an order that would immediately match.

```typescript
import { OrderClient, Side, OrderType } from '@limitless-exchange/sdk';

const gtcOrder = await orderClient.createOrder({
  tokenId: marketDetails.tokens.yes,
  price: 0.42,
  size: 10,
  side: Side.BUY,
  orderType: OrderType.GTC,
  marketSlug: 'market-slug',
  postOnly: true, // Supported only for GTC
});

console.log(gtcOrder.order.id);
```

For complete examples, see [docs/code-samples/clob-gtc-order.ts](https://github.com/limitless-labs-group/limitless-exchange-ts-sdk/blob/main/limitless-exchange-sdk/docs/code-samples/clob-gtc-order.ts).

### FAK Orders (Fill-and-Kill Limit Orders)

FAK orders use the same `price` + `size` construction as `GTC`, but they only consume immediately available liquidity and cancel any remainder.

```typescript
import { OrderClient, Side, OrderType } from '@limitless-exchange/sdk';

const fakOrder = await orderClient.createOrder({
  tokenId: marketDetails.tokens.yes,
  price: 0.45,
  size: 10,
  side: Side.BUY,
  orderType: OrderType.FAK,
  marketSlug: 'market-slug',
});

if (fakOrder.makerMatches && fakOrder.makerMatches.length > 0) {
  console.log(`FAK matched immediately with ${fakOrder.makerMatches.length} fill(s)`);
} else {
  console.log('FAK remainder was cancelled.');
}
```

**Key Differences from GTC**:

- FAK uses `price` + `size` like GTC
- Executes immediately up to the available size
- Any unfilled remainder is cancelled
- `postOnly` is not supported for FAK

For complete examples, see [docs/code-samples/clob-fak-order.ts](https://github.com/limitless-labs-group/limitless-exchange-ts-sdk/blob/main/limitless-exchange-sdk/docs/code-samples/clob-fak-order.ts).

### FOK Orders (Fill-or-Kill Market Orders)

FOK orders execute immediately at the best available price or cancel entirely. Unlike GTC orders that use `price` + `size`, FOK orders use `makerAmount`.

**Parameter Semantics**:

- **BUY**: `makerAmount` = total USDC to spend
- **SELL**: `makerAmount` = number of shares to sell

```typescript
import { OrderClient, Side, OrderType } from '@limitless-exchange/sdk';

// BUY FOK - spend 50 USDC at market price
const buyOrder = await orderClient.createOrder({
  tokenId: marketDetails.tokens.yes,
  makerAmount: 50, // 50 USDC to spend
  side: Side.BUY,
  orderType: OrderType.FOK,
  marketSlug: 'market-slug',
});

// SELL FOK - sell 120 shares at market price
const sellOrder = await orderClient.createOrder({
  tokenId: marketDetails.tokens.no,
  makerAmount: 120, // 120 shares to sell
  side: Side.SELL,
  orderType: OrderType.FOK,
  marketSlug: 'market-slug',
});

// Check execution
if (buyOrder.makerMatches && buyOrder.makerMatches.length > 0) {
  console.log(`Order filled: ${buyOrder.makerMatches.length} matches`);
} else {
  console.log('Order cancelled (no liquidity)');
}
```

**Key Differences from GTC**:

- FOK uses `makerAmount` (not `price` + `size`)
- Executes immediately or cancels (no orderbook placement)
- All-or-nothing execution (no partial fills)
- Best for immediate execution at market price

For complete examples, see [docs/code-samples/clob-fok-order.ts](https://github.com/limitless-labs-group/limitless-exchange-ts-sdk/blob/main/limitless-exchange-sdk/docs/code-samples/clob-fok-order.ts).

### Error Handling & Retry

The SDK provides automatic retry logic for handling transient failures like rate limits and server errors:

```typescript
import { withRetry, retryOnErrors } from '@limitless-exchange/sdk';

// Option 1: Wrapper function approach
const result = await withRetry(async () => await orderClient.createOrder(orderData), {
  statusCodes: [429, 500, 503], // Retry on rate limits and server errors
  maxRetries: 3,
  delays: [2, 5, 10], // Wait 2s, then 5s, then 10s
  onRetry: (attempt, error, delay) => {
    console.log(`Retry ${attempt + 1} after ${delay}s: ${error.message}`);
  },
});

// Option 2: Decorator approach (requires experimentalDecorators: true)
class TradingService {
  @retryOnErrors({
    statusCodes: [429, 500, 503],
    maxRetries: 3,
    exponentialBase: 2, // Exponential backoff: 1s, 2s, 4s
    maxDelay: 30,
  })
  async placeOrder(orderData: any) {
    return await this.orderClient.createOrder(orderData);
  }
}
```

**Key Features**:

- Automatic retry on configurable status codes (429, 500, 502, 503, 504)
- Fixed delays or exponential backoff strategies
- Callback hooks for monitoring retry attempts
- Three approaches: decorator, wrapper function, or global client wrapper

For detailed documentation, see the [Error Handling & Retry Guide](https://github.com/limitless-labs-group/limitless-exchange-ts-sdk/blob/main/limitless-exchange-sdk/docs/api/README.md).

## API Documentation

### Authentication

#### `HttpClient`

HTTP client with API key authentication.

```typescript
const httpClient = new HttpClient({
  baseURL: 'https://api.limitless.exchange',
  apiKey: process.env.LIMITLESS_API_KEY, // you are allowed to pass it that way, otherwise will be loaded from .env
  timeout: 30000,
});

// Set or update API key
httpClient.setApiKey('sk_live_...');

// Make requests - X-API-Key header automatically included
const data = await httpClient.get('/endpoint');
await httpClient.post('/endpoint', { data });
```

## Documentation

For detailed documentation, see the [docs](https://github.com/limitless-labs-group/limitless-exchange-ts-sdk/tree/main/limitless-exchange-sdk/docs) directory:

- **[Complete Documentation](https://github.com/limitless-labs-group/limitless-exchange-ts-sdk/blob/main/limitless-exchange-sdk/docs/README.md)** - Full SDK documentation
- **[Authentication Guide](https://github.com/limitless-labs-group/limitless-exchange-ts-sdk/blob/main/limitless-exchange-sdk/docs/api/README.md)** - API key authentication and HTTP client
- **[Trading & Orders](https://github.com/limitless-labs-group/limitless-exchange-ts-sdk/blob/main/limitless-exchange-sdk/docs/orders/README.md)** - Order creation, management, and NegRisk markets
- **[Market Data](https://github.com/limitless-labs-group/limitless-exchange-ts-sdk/blob/main/limitless-exchange-sdk/docs/markets/README.md)** - Market discovery and orderbook access
- **[Portfolio & Positions](https://github.com/limitless-labs-group/limitless-exchange-ts-sdk/blob/main/limitless-exchange-sdk/docs/portfolio/README.md)** - Position tracking and user history
- **[WebSocket Streaming](https://github.com/limitless-labs-group/limitless-exchange-ts-sdk/blob/main/limitless-exchange-sdk/docs/websocket/README.md)** - Real-time data updates
- **[Error Handling & Retry](https://github.com/limitless-labs-group/limitless-exchange-ts-sdk/blob/main/limitless-exchange-sdk/docs/api/README.md)** - API error handling and retry mechanisms
- **[Logging](https://github.com/limitless-labs-group/limitless-exchange-ts-sdk/blob/main/limitless-exchange-sdk/docs/logging/LOGGING.md)** - Logging configuration

## Code Examples

Production-ready code samples are available in [docs/code-samples](https://github.com/limitless-labs-group/limitless-exchange-ts-sdk/tree/main/limitless-exchange-sdk/docs/code-samples):

### Authentication Examples

- `basic-auth.ts` - API key authentication setup
- `with-logging.ts` - Authentication with custom logging
- `auth-retry.ts` - Authentication with retry logic
- `error-handling.ts` - Comprehensive error handling

### Trading Examples

**CLOB Markets:**

- `clob-fok-order.ts` - Fill-or-Kill market orders
- `clob-gtc-order.ts` - Good-Til-Cancelled limit orders with `postOnly`
- `clob-fak-order.ts` - Fill-And-Kill limit orders

**NegRisk Markets:**

- `negrisk-fok-order.ts` - FOK orders on group markets
- `negrisk-gtc-order.ts` - GTC orders on NegRisk submarkets

### Market Data Examples

- `get-active-markets.ts` - Fetching active markets with sorting and pagination
- `orderbook.ts` - Fetching and analyzing orderbooks
- `positions.ts` - Portfolio and position tracking
- `fluent-api-trading-workflow.ts` - Complete trading workflow

### Real-Time Examples

- `websocket-events.ts` - Real-time trading events and subscriptions

## Development

### Build

```bash
pnpm install
pnpm build
```

### Test

```bash
pnpm test
pnpm test:coverage
```

### Lint

```bash
pnpm lint
pnpm format
```

## Project Structure

```
src/
├── types/          # TypeScript type definitions
│   ├── markets.ts  # Market and active markets types
│   ├── orders.ts   # Order types
│   ├── auth.ts     # User profile types
│   └── ...
├── api/            # HTTP client and API utilities
│   ├── http.ts     # HTTP client with API key auth
│   ├── errors.ts   # Error handling
│   └── retry.ts    # Retry logic
├── markets/        # Market data modules
│   ├── fetcher.ts  # Market and orderbook fetching
│   └── index.ts
├── orders/         # Order management
│   └── client.ts   # Order creation and management
├── portfolio/      # Portfolio and positions
│   └── fetcher.ts
├── websocket/      # Real-time data streaming
│   └── client.ts
├── api/            # HTTP client and API utilities
│   ├── http.ts     # HTTP client
│   └── errors.ts   # API error handling
└── utils/          # Shared utilities and constants

tests/
├── auth/           # Authentication tests
└── markets/        # Market fetcher tests
    └── fetcher.test.ts //etc.

docs/
├── code-samples/   # Production-ready examples
│   ├── get-active-markets.ts
│   ├── clob-fok-order.ts
│   └── ...
└── */              # Documentation guides

```

## Changelog

### v1.0.5

**Release Date**: April 2026

Latest release with `FAK` limit-order support and `postOnly` for `GTC` orders.

#### Highlights

- ✅ **Production-Ready**: Thoroughly tested and validated against Base mainnet
- 🔒 **Type-Safe**: Full TypeScript support with comprehensive type definitions
- 📚 **Well-Documented**: 18 production-ready code samples + comprehensive guides
- ⚡ **Performance Optimized**: Venue caching system and connection pooling
- 🔄 **Robust Error Handling**: Automatic retry logic with multiple strategies
- 🌐 **Real-Time Updates**: WebSocket support for orderbook and position streaming
- 🎯 **NegRisk Support**: Full support for group markets with multiple outcomes
- 🧭 **Market Pages API**: Navigation tree, by-path resolver with 301 handling, page-scoped markets, property keys
- 🧾 **More Trading Semantics**: `FAK` limit orders plus `postOnly` on `GTC`

#### Core Features

- **Authentication**: API key authentication, EIP-712 signing, EOA support
- **Market Data**: Active markets with sorting, orderbook access, venue caching
- **Market Pages & Navigation**: `/navigation`, `/market-pages/by-path`, `/market-pages/:id/markets`, `/property-keys`
- **Order Management**: GTC, FAK, and FOK orders, GTC `postOnly`, tick alignment, automatic signing, IEEE-safe create-order payload parsing
- **Portfolio**: Position tracking, user history
- **WebSocket**: Real-time orderbook, price updates, event streaming
- **Error Handling**: Decorator and wrapper retry patterns, configurable strategies
- **Token Approvals**: Complete setup script, CLOB and NegRisk workflows

#### Documentation Enhancements (v1.0.5)

- Added `FAK` order examples to README and code samples
- Added `postOnly` usage to `GTC` examples and delegated-order samples
- Created comprehensive CHANGELOG.md following Keep a Changelog format
- All 18 code samples include step-by-step comments and error handling
- Detailed guides for authentication, trading, markets, portfolio, and WebSocket
- Added market-pages guide and README quick-start for navigation-driven discovery

For complete release notes, see [CHANGELOG.md](https://github.com/limitless-labs-group/limitless-exchange-ts-sdk/blob/main/limitless-exchange-sdk/CHANGELOG.md).

---

### Pre-Release Versions

- **v0.0.3** - WebSocket streaming, enhanced code samples, NegRisk examples
- **v0.0.2** - Venue caching, retry mechanisms, portfolio fetcher
- **v0.0.1** - Initial release with core functionality

---

## License

MIT - See [LICENSE](https://github.com/limitless-labs-group/limitless-exchange-ts-sdk/blob/main/limitless-exchange-sdk/LICENSE) file for details