oddsockets-nodejs
v1.0.2
Published
Official Node.js SDK for OddSockets real-time messaging platform
Maintainers
Readme
OddSockets Node.js SDK
Real-time messaging for AI agents — as simple as git.
Your agents connect in real-time. Autonomously. OddSockets is the agent-first real-time platform: publish, subscribe, and coordinate across services with <30ms global latency and a 99.99% uptime SLA. This is the official Node.js SDK — automatic manager discovery, worker load balancing, auto-reconnect, and a drop-in PubNub compatibility layer.
npm install oddsockets-nodejsBuilding an agent? OddSockets also ships a zero-boilerplate CLI —
npm install -g oddsockets, thenoddsockets signup my-app --localandoddsockets publish alerts "Deploy complete". No API calls, no SDK wiring, just commands. Drop one line in yourCLAUDE.mdor.cursorrulesand your agent has real-time messaging.
Why OddSockets
- Agent-first — Built for autonomous workflows. Agents publish, subscribe, and coordinate without a human in the loop.
- Blazing fast —
<30msglobal latency on a multi-worker cluster with automatic failover and cross-worker fan-out. - PubNub alternative — up to 50% cheaper — Drop-in
PubNubCompatlayer means you migrate in minutes, not weeks. - 19 SDKs, one platform — JavaScript, Node.js, Python, Go, Java, Rust, C#, Kotlin, Swift, Flutter, PHP, React Native, Ruby, Elixir, Svelte, C, C++, Unity, and Unreal Engine.
- Presence & history built in — Real-time user presence, state, and message history out of the box.
- Free to start — 100 MAU, 10,000 messages/day, no credit card. Get a key.
Migrating from PubNub or Pusher?
| | OddSockets | PubNub | Pusher |
|---|---|---|---|
| Free tier | 100 MAU, 10k msgs/day | Limited | Limited |
| Global latency | <30ms | ~50-100ms | ~50ms |
| Drop-in compat layer | Yes (PubNubCompat) | — | — |
| Presence tracking | Included | Add-on | Included |
| Agent-native CLI | Yes | No | No |
| SDK languages | 19 | ~10 | ~7 |
Already on PubNub? Skip to the PubNub Compatibility section — most apps swap the import and keep going.
Features
- Simple API - Easy-to-use interface for real-time messaging
- Auto-reconnection - Automatic reconnection with exponential backoff
- Message Size Validation - Industry-standard 32KB message size limits
- Session Stickiness - Consistent worker assignment for optimal performance
- PubNub Compatibility - Drop-in replacement for PubNub applications
- Bulk Operations - Publish multiple messages efficiently
- Presence Tracking - Real-time user presence and state management
Quick Start
const OddSockets = require('oddsockets-nodejs');
// Initialize the client
const client = new OddSockets({
apiKey: 'your-api-key-here',
userId: 'user-123'
});
// Listen for connection events
client.on('connected', () => {
console.log('Connected to OddSockets');
});
// Get a channel and subscribe
const channel = client.channel('my-channel');
await channel.subscribe((message) => {
console.log('Received:', message);
});
// Publish a message
await channel.publish({
text: 'Hello World!',
timestamp: new Date().toISOString()
});Configuration Options
const client = new OddSockets({
apiKey: 'your-api-key-here', // Required: Your OddSockets API key
userId: 'user-123', // Optional: User identifier
autoConnect: true, // Optional: Auto-connect on initialization (default: true)
options: { // Optional: Additional Socket.IO options
transports: ['websocket', 'polling'],
timeout: 10000
}
});Channel Operations
Subscribe to Messages
const channel = client.channel('my-channel');
// Basic subscription
await channel.subscribe((message) => {
console.log('Message:', message.message);
console.log('Publisher:', message.publisher);
console.log('Timestamp:', message.timestamp);
});
// Subscribe with options
await channel.subscribe((message) => {
console.log('Received:', message);
}, {
enablePresence: true, // Enable presence tracking
retainHistory: true, // Keep message history in memory
maxHistory: 100 // Maximum messages to retain
});Publish Messages
// Simple message
await channel.publish('Hello World!');
// Complex message with metadata
await channel.publish({
text: 'Hello World!',
user: 'john_doe',
timestamp: new Date().toISOString()
}, {
ttl: 3600, // Time to live in seconds
metadata: { // Additional metadata
priority: 'high'
}
});Bulk Publishing
// Publish multiple messages at once
const results = await client.publishBulk([
{ channel: 'channel-1', message: 'Message 1' },
{ channel: 'channel-2', message: 'Message 2' },
{ channel: 'channel-1', message: 'Message 3', options: { ttl: 3600 } }
]);
results.forEach((result, index) => {
if (result.success) {
console.log(`Message ${index + 1} published successfully`);
} else {
console.error(`Message ${index + 1} failed:`, result.error);
}
});Message History
// Get recent messages
const history = await channel.getHistory({
count: 50, // Number of messages (default: 50)
start: '2023-01-01T00:00:00Z', // Start time (ISO string)
end: '2023-12-31T23:59:59Z' // End time (ISO string)
});
console.log('History:', history);Presence Management
// Get current presence
const presence = await channel.getPresence();
console.log('Online users:', presence.occupancy);
console.log('User list:', presence.occupants);
// Update user state
await channel.updateState({
status: 'online',
mood: 'happy',
location: 'New York'
});
// Listen for presence changes
channel.on('presence_change', (event) => {
console.log(`User ${event.user.userId} ${event.action}`);
console.log('Current occupancy:', event.occupancy);
});PubNub Compatibility
Migrate from PubNub with minimal code changes:
const { PubNubCompat } = require('oddsockets-nodejs');
// Initialize with PubNub-style config
const pubnub = new PubNubCompat({
publishKey: 'your-api-key-here',
subscribeKey: 'your-api-key-here',
userId: 'user-123'
});
// Add listeners (PubNub style)
pubnub.addListener({
message: (messageEvent) => {
console.log('Message:', messageEvent.message);
console.log('Channel:', messageEvent.channel);
console.log('Publisher:', messageEvent.publisher);
},
presence: (presenceEvent) => {
console.log('Presence:', presenceEvent.action);
console.log('User:', presenceEvent.uuid);
},
status: (statusEvent) => {
console.log('Status:', statusEvent.category);
}
});
// Subscribe to channels
pubnub.subscribe({
channels: ['channel-1', 'channel-2'],
withPresence: true
});
// Publish messages
pubnub.publish({
channel: 'channel-1',
message: 'Hello from PubNub compatibility!'
}, (response) => {
if (response.error) {
console.error('Error:', response.error);
} else {
console.log('Published with timetoken:', response.timetoken);
}
});Event Handling
// Connection events
client.on('connected', () => {
console.log('Connected to OddSockets');
});
client.on('disconnected', (reason) => {
console.log('Disconnected:', reason);
});
client.on('reconnecting', (attempt) => {
console.log(`Reconnecting... attempt ${attempt.attempt}/${attempt.maxAttempts}`);
});
client.on('error', (error) => {
console.error('Connection error:', error);
});
client.on('worker_assigned', (info) => {
console.log('Assigned to worker:', info.workerId);
console.log('Worker URL:', info.workerUrl);
});
// Channel events
channel.on('subscribed', (data) => {
console.log('Subscribed to channel:', data.channel);
});
channel.on('unsubscribed', (data) => {
console.log('Unsubscribed from channel:', data.channel);
});
channel.on('published', (data) => {
console.log('Message published:', data);
});Error Handling
try {
await channel.publish('Hello World!');
} catch (error) {
if (error.message.includes('Message size')) {
console.error('Message too large (max 32KB)');
} else if (error.message.includes('Not connected')) {
console.error('Client not connected');
} else {
console.error('Publish failed:', error.message);
}
}Advanced Usage
Custom Connection Options
const client = new OddSockets({
apiKey: 'your-api-key-here',
userId: 'user-123',
options: {
transports: ['websocket'], // Force WebSocket only
timeout: 15000, // Connection timeout
forceNew: true, // Force new connection
reconnection: true, // Enable reconnection
reconnectionDelay: 1000, // Initial reconnection delay
reconnectionAttempts: 5, // Max reconnection attempts
maxReconnectionAttempts: 10 // Max total attempts
}
});Manual Connection Management
const client = new OddSockets({
apiKey: 'your-api-key-here',
autoConnect: false // Don't auto-connect
});
// Connect manually
await client.connect();
// Check connection state
console.log('State:', client.getState()); // 'connected', 'connecting', 'disconnected', 'reconnecting'
// Get worker info
const workerInfo = client.getWorkerInfo();
console.log('Worker ID:', workerInfo.workerId);
console.log('Worker URL:', workerInfo.workerUrl);
// Disconnect
client.disconnect();Session Information
// Get client identifier (used for session stickiness)
const clientId = client.getClientIdentifier();
console.log('Client ID:', clientId);
// Get session info
const session = client.getSessionInfo();
console.log('Session:', session);Message Size Limits
The SDK enforces industry-standard message size limits:
- Maximum message size: 32KB (32,768 bytes)
- Encoding: UTF-8
- Validation: Automatic before publishing
// This will throw an error if message exceeds 32KB
try {
await channel.publish({
data: 'x'.repeat(40000) // Too large!
});
} catch (error) {
console.error(error.message);
// "Message size (39KB) exceeds maximum allowed size of 32KB"
}Examples
Run the included examples:
# Basic usage example
node examples/basic-usage.js
# PubNub compatibility example
node examples/basic-usage.js pubnubAPI Reference
OddSockets Class
Constructor
new OddSockets(config)- Create a new client instance
Methods
connect()- Connect to OddSockets platformdisconnect()- Disconnect from platformchannel(name)- Get or create a channelpublishBulk(messages)- Publish multiple messagesgetState()- Get connection stategetWorkerInfo()- Get assigned worker informationgetClientIdentifier()- Get client identifiergetSessionInfo()- Get session information
Events
connected- Connected to platformdisconnected- Disconnected from platformreconnecting- Attempting to reconnecterror- Connection error occurredworker_assigned- Assigned to a worker
Channel Class
Methods
subscribe(callback, options)- Subscribe to messagesunsubscribe()- Unsubscribe from channelpublish(message, options)- Publish a messagegetHistory(options)- Get message historygetPresence()- Get presence informationupdateState(state)- Update user stateisSubscribed()- Check subscription statusgetName()- Get channel name
Events
message- New message receivedsubscribed- Successfully subscribedunsubscribed- Successfully unsubscribedpublished- Message publishedpresence- Presence informationpresence_change- Presence changed
Get a Free API Key
AI agents can sign up with a verified email in two steps — no dashboard, no human required.
Step 1: Request a verification code
curl -X POST https://oddsockets.com/api/agent-signup \
-H "Content-Type: application/json" \
-d '{"email": "[email protected]", "agentName": "my-agent", "platform": "claude"}'Step 2: Verify the 6-digit code from your email and get your API key
curl -X POST https://oddsockets.com/api/agent-signup/verify \
-H "Content-Type: application/json" \
-d '{"email": "[email protected]", "code": "123456", "agentName": "my-agent"}'Plans
| | Free | Starter | Pro | |---|---|---|---| | Price | $0/mo | $49.99/mo | $299/mo | | MAU | 100 | 1,000 | 50,000 | | Concurrent connections | 50 | 1,000 | Unlimited | | Messages/day | 10,000 | 4,320,000 | Unlimited | | Messages/minute | 100 | 3,000 | Unlimited | | Channels | 10 | Unlimited | Unlimited | | Storage | 100MB (24h) | 50GB (6 months) | Unlimited | | Webhooks | No | Yes | Yes | | Analytics | No | Yes | Yes | | Support | Community | 24/5 email & chat | Dedicated team |
All limits are enforced in real time. When a limit is reached, the SDK receives a RATE_LIMIT_EXCEEDED error with a retryAfter value.
See pricing for full details.
Requirements
- Node.js 14.0.0 or higher
- Active OddSockets API key (get one free)
Support
License
Proprietary - Copyright (c) 2026 Tyga.Cloud Ltd. Licensed for use with the OddSockets platform. See LICENSE for the full End User License Agreement.
