Skip to main content

Overview

The SDK provides methods to query market information, event metadata, and system configuration.

List Markets

Search and filter Kalshi markets based on various criteria.

getMarkets

async getMarkets(params?: {
  series_ticker?: string;
  event_ticker?: string;
  status?: 'active' | 'closed' | 'settled';
  limit?: string;
}): Promise<GetMarketsResponse>

Parameters

All parameters are optional. Omit all parameters to retrieve all markets.
series_ticker
string
Filter by Kalshi series ticker (e.g., "KXPREZ")
event_ticker
string
Filter by Kalshi event ticker (e.g., "KXFEDDECISION-26JAN")
status
string
Filter by market status: "active", "closed", or "settled"
limit
string
Maximum number of markets to return (max 200)

Returns

List of markets matching the filter criteria, including bid/ask prices, volume, and metadata.

Examples

Get all active markets:
import { createBisonClient } from 'bison-sdk-ts';

const client = createBisonClient({ 
  baseUrl: 'https://api.bison.markets' 
});

const response = await client.getMarkets({ status: 'active' });

console.log(`Found ${response.markets.length} active markets`);

response.markets.forEach(market => {
  console.log(`${market.ticker}: ${market.title}`);
  console.log(`  YES: ${market.yes_bid} / ${market.yes_ask}`);
  console.log(`  NO: ${market.no_bid} / ${market.no_ask}`);
  console.log(`  Volume: ${market.volume}`);
});
Filter by event ticker:
// Get all markets for a specific event
const response = await client.getMarkets({
  event_ticker: 'KXFEDDECISION-26JAN',
  status: 'active'
});

console.log(`Event has ${response.markets.length} active markets`);

// Find markets with high volume
const popularMarkets = response.markets
  .filter(m => m.volume && m.volume > 1000)
  .sort((a, b) => (b.volume || 0) - (a.volume || 0));

console.log('Most popular markets:');
popularMarkets.slice(0, 5).forEach(m => {
  console.log(`  ${m.ticker}: ${m.volume} volume`);
});
Filter by series:
// Get all presidential election markets
const response = await client.getMarkets({
  series_ticker: 'KXPREZ',
  limit: '50'
});

console.log(`Found ${response.markets.length} presidential markets`);

// Group by status
const byStatus = response.markets.reduce((acc, market) => {
  acc[market.status || 'unknown'] = (acc[market.status || 'unknown'] || 0) + 1;
  return acc;
}, {} as Record<string, number>);

console.log('Markets by status:', byStatus);
Find trading opportunities:
// Find markets with tight spreads
const response = await client.getMarkets({ status: 'active' });

const tightSpreads = response.markets
  .filter(m => {
    if (!m.yes_bid || !m.yes_ask) return false;
    const spread = m.yes_ask - m.yes_bid;
    return spread <= 0.02; // 2 cent spread or less
  })
  .map(m => ({
    ticker: m.ticker,
    title: m.title,
    spread: m.yes_ask! - m.yes_bid!,
    volume: m.volume || 0
  }))
  .sort((a, b) => a.spread - b.spread);

console.log('Markets with tight spreads:');
tightSpreads.slice(0, 10).forEach(m => {
  console.log(`  ${m.ticker}: ${(m.spread * 100).toFixed(1)}¢ spread, ${m.volume} volume`);
});

Get Event Information

Retrieve detailed information about a Kalshi event and its markets.

getEvent

async getEvent(eventTicker: string): Promise<GetEventResponse>

Parameters

eventTicker
string
required
Kalshi event ticker (e.g., "KXFEDDECISION-26JAN")

Returns

Event information including all associated markets, their metadata, and current state.

Example

import { createBisonClient } from 'bison-sdk-ts';

const client = createBisonClient({ 
  baseUrl: 'https://api.bison.markets' 
});

const event = await client.getEvent('KXFEDDECISION-26JAN');

console.log('Event:', event.event_ticker);
console.log('Title:', event.title);
console.log('Category:', event.category);
console.log('Status:', event.status);

// List all markets in the event
event.markets.forEach(market => {
  console.log(`Market: ${market.ticker}`);
  console.log(`  Subtitle: ${market.subtitle}`);
  console.log(`  Floor: ${market.floor_strike}`);
  console.log(`  Cap: ${market.cap_strike}`);
  console.log(`  Status: ${market.status}`);
});

Get Event Metadata

Retrieve metadata for a Kalshi event, including human-readable information and timestamps.

getEventMetadata

async getEventMetadata(eventTicker: string): Promise<GetEventMetadataResponse>

Parameters

eventTicker
string
required
Kalshi event ticker (e.g., "KXFEDDECISION-26JAN")

Returns

Event metadata including title, description, category, and important dates.

Example

const metadata = await client.getEventMetadata('KXFEDDECISION-26JAN');

console.log('Title:', metadata.title);
console.log('Category:', metadata.category);
console.log('Series ticker:', metadata.series_ticker);
console.log('Mutually exclusive:', metadata.mutually_exclusive);

// Check event timing
console.log('Settlement date:', new Date(metadata.settlement_date));
console.log('Close date:', new Date(metadata.close_date));
console.log('Open date:', new Date(metadata.open_date));

Get Created Tokens

Retrieve information about position tokens that have been created on-chain.

getCreatedTokens

async getCreatedTokens(chain?: 'base'): Promise<GetCreatedTokensResponse>

Parameters

chain
string
Optional chain identifier. Currently only "base" is supported.

Returns

List of created position tokens with their contract addresses and market information.

Example

const tokens = await client.getCreatedTokens('base');

console.log('Created tokens:');
tokens.forEach(token => {
  console.log(`Market: ${token.marketId}`);
  console.log(`  YES token: ${token.yesTokenAddress}`);
  console.log(`  NO token: ${token.noTokenAddress}`);
  console.log(`  Created at: ${new Date(token.createdAt)}`);
});

Get System Information

Retrieve system configuration and contract addresses.

getInfo

async getInfo(): Promise<GetInfoResponse>

Returns

System information including vault addresses, USDC addresses, and supported chains.

Example

const info = await client.getInfo();

console.log('Bison API Version:', info.version);
console.log('Supported chains:', info.chains);

// Contract addresses are available if needed
const baseConfig = info.chains.base;
console.log('Base configuration:');
console.log('  Chain ID:', baseConfig.chainId);
console.log('  RPC URL:', baseConfig.rpcUrl);

// Note: The SDK automatically resolves vault and USDC addresses 
// for all trading/deposit functions, so you typically don't need to access them directly

Complete Market Workflow Example

Here’s a complete example showing how to discover and monitor a market:
import { createBisonClient } from 'bison-sdk-ts';

const client = createBisonClient({ 
  baseUrl: 'https://api.bison.markets' 
});

// 1. Get event information
const event = await client.getEvent('KXFEDDECISION-26JAN');
console.log(`Found ${event.markets.length} markets in event`);

// 3. Find a specific market
const market = event.markets.find(m => 
  m.floor_strike === 425 && m.cap_strike === 450
);

if (!market) {
  throw new Error('Market not found');
}

console.log('Trading market:', market.ticker);
console.log('Range:', market.floor_strike, '-', market.cap_strike);

// 4. Subscribe to real-time ticker updates
const disconnect = client.listenToKalshiEvent(
  event.event_ticker,
  (update) => {
    // Filter for our specific market
    if (update.market_ticker === market.ticker) {
      console.log(`${market.ticker} update:`);
      if (update.yes_bid_uusdc && update.yes_ask_uusdc) {
        console.log(`  YES: $${update.yes_bid_uusdc / 1_000_000} / $${update.yes_ask_uusdc / 1_000_000}`);
      }
      if (update.volume !== undefined) {
        console.log(`  Volume: ${update.volume}`);
      }
    }
  }
);

// Clean up when done
// disconnect();

Error Handling

All methods throw errors when the API request fails:
try {
  const event = await client.getEvent('INVALID-TICKER');
} catch (error) {
  if (error instanceof Error) {
    console.error('Failed to get event:', error.message);
    
    // Handle specific error cases
    if (error.message.includes('not found')) {
      console.log('Event does not exist');
    } else if (error.message.includes('network')) {
      console.log('Network error, retrying...');
    }
  }
}

Position Token Utilities

The SDK provides utility methods for working with position tokens on-chain.

getPositionTokenAddress

Get the on-chain token address for a specific market position.
async getPositionTokenAddress(params: {
  publicClient: PublicClient;
  chain: 'base';
  marketId: string;
  side: 'yes' | 'no';
}): Promise<`0x${string}` | null>

Parameters

publicClient
PublicClient
required
Viem public client for reading from the blockchain
chain
string
required
Chain identifier (currently only "base" is supported)
marketId
string
required
Market ticker
side
string
required
Position side: "yes" or "no"

Returns

Token address if the position has been minted, null otherwise.

Example

import { createPublicClient, http } from 'viem';
import { base } from 'viem/chains';

const publicClient = createPublicClient({
  chain: base,
  transport: http(),
});

const tokenAddress = await client.getPositionTokenAddress({
  publicClient,
  chain: 'base',
  marketId: 'KXBTC-100K-DEC31',
  side: 'yes',
});

if (tokenAddress) {
  console.log('YES token address:', tokenAddress);
} else {
  console.log('Position tokens not yet minted');
}

getTokenBalance

Get the balance of an ERC20 token for a specific address.
async getTokenBalance(params: {
  publicClient: PublicClient;
  tokenAddress: `0x${string}`;
  userAddress: `0x${string}`;
}): Promise<bigint>

Parameters

publicClient
PublicClient
required
Viem public client for reading from the blockchain
tokenAddress
string
required
ERC20 token contract address
userAddress
string
required
Wallet address to check balance for

Returns

Token balance as a bigint. Position tokens have 0 decimals.

Example

const tokenAddress = await client.getPositionTokenAddress({
  publicClient,
  chain: 'base',
  marketId: 'KXBTC-100K-DEC31',
  side: 'yes',
});

if (tokenAddress) {
  const balance = await client.getTokenBalance({
    publicClient,
    tokenAddress,
    userAddress: '0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266',
  });
  
  console.log(`Balance: ${balance} YES tokens`);
}

addTokenToWallet

Add a position token to the user’s wallet (e.g., MetaMask).
async addTokenToWallet(params: {
  tokenAddress: `0x${string}`;
  marketId: string;
  side: 'yes' | 'no';
}): Promise<boolean>

Parameters

tokenAddress
string
required
Position token contract address
marketId
string
required
Market ticker (used for token symbol)
side
string
required
Position side: "yes" or "no"

Returns

true if the user accepted the request, false otherwise.

Example

const tokenAddress = await client.getPositionTokenAddress({
  publicClient,
  chain: 'base',
  marketId: 'KXBTC-100K-DEC31',
  side: 'yes',
});

if (tokenAddress) {
  try {
    const added = await client.addTokenToWallet({
      tokenAddress,
      marketId: 'KXBTC-100K-DEC31',
      side: 'yes',
    });
    
    if (added) {
      console.log('Token added to wallet successfully');
    } else {
      console.log('User declined to add token');
    }
  } catch (error) {
    console.error('Failed to add token:', error);
  }
}
This method requires a browser environment with an injected Web3 wallet (like MetaMask). It will throw an error if called in a non-browser environment or if no wallet is detected.

Important Notes

  • Market status can be: unopened, open, closed, or settled
  • All dates are returned as ISO 8601 strings
  • Token addresses are only available after positions have been minted on-chain
  • The getInfo response is cached and safe to call frequently
  • Position tokens have 0 decimals - quantities represent whole tokens
  • Token symbols are automatically generated from the market ID (first 7 chars) and side