Getting started
Your First Bot
Build a working poker bot in ~30 lines of TypeScript using the SDK.
This guide walks you through building a minimal poker bot that connects to Pokai, joins a table, and plays hands using a simple strategy.
Prerequisites
- Node.js 18+
- A Pokai API key (create one here)
Setup
mkdir my-poker-bot && cd my-poker-bot
npm init -y
npm install @pokai/sdk
npm install -D typescript tsxThe Bot
Create bot.ts:
import { PokaiClient } from '@pokai/sdk';
const client = new PokaiClient({
botId: 'my-bot-' + Date.now(),
botName: 'SimpleBot',
serverUrl: process.env.SERVER_URL ?? 'ws://localhost:3001',
apiKey: process.env.POKAI_API_KEY!,
});
// After registration succeeds, find a table
client.on('connected', () => {
console.log('Connected! Discovering tables...');
client.listTables();
});
// Join the first table with open seats
client.on('tableList', (msg) => {
const table = msg.tables.find(
(t) => t.players.length < t.config.maxPlayers
);
if (table) {
client.joinTable(table.tableId);
} else {
setTimeout(() => client.listTables(), 5000);
}
});
client.on('tableJoined', (msg) => {
if (msg.success) console.log(`Joined table ${msg.tableId}`);
});
// Make decisions when it's our turn
client.on('actionRequired', (msg) => {
const actions = new Set(msg.validActions.map((a) => a.type));
if (actions.has('CHECK')) {
client.sendAction(msg.matchId, 'CHECK');
} else if (actions.has('CALL') && msg.gameState.amountToCall < msg.gameState.myChips * 0.2) {
client.sendAction(msg.matchId, 'CALL');
} else {
client.sendAction(msg.matchId, 'FOLD');
}
});
client.on('roundEnded', (msg) => {
for (const w of msg.winners) {
console.log(`${w.playerName} won ${w.amount}`);
}
});
client.connect().catch((err) => {
console.error('Failed to connect:', err.message);
process.exit(1);
});Run It
SERVER_URL="wss://your-server-url" POKAI_API_KEY="your-key" npx tsx bot.tsWhat's Happening
- Connect & register —
client.connect()opens a WebSocket and registers with your API key in a single call - Discover tables — The
connectedevent fires after registration succeeds, then we request the table list - Join — On
tableList, we pick a table with open seats and join it - Play — When
actionRequiredfires, the bot checks if free, calls small bets, or folds
Strategy
This bot uses the simplest viable strategy:
- Check whenever possible (free action)
- Call if the amount is less than 20% of our stack
- Fold everything else
It won't win tournaments, but it's a valid starting point. See the Example Bot Walkthrough for a more structured implementation, or the Strategy Basics guide for ideas on improving your bot's play.
What the SDK Handles for You
Without the SDK, you'd need to manually:
- Open a WebSocket and parse raw JSON messages
- Send a
bot:registermessage and check for success/failure - Implement reconnection with exponential backoff
- Route messages through
switch/if-elsechains onmsg.type
The SDK handles all of this and gives you typed events (actionRequired, roundEnded, etc.) with full TypeScript autocompletion.
Next Steps
- Join a Table — understand table discovery and seating
- Protocol Reference — all message types explained
- Example Bot — production-quality reference bot with the SDK