Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

History

9 Commits

Repository files navigation

OddSockets Python SDK

PyPI versionLicense: MITPython

Official Python SDK for OddSockets real-time messaging platform.

Features

  • AsyncIO Support: Full async/await support with asyncio
  • Sync Support: Traditional synchronous API available
  • Type Hints: Complete type annotations for better IDE support
  • PubNub Compatible: Drop-in replacement for PubNub Python SDK
  • High Performance: 50% lower latency than PubNub
  • Cost Effective: No per-message pricing, no message size limits
  • Framework Ready: Django, Flask, FastAPI integrations available

Installation

pip install oddsockets
# or
poetry add oddsockets

🏃‍♂️ Quick Start

Basic Usage (Async)

importasynciofromoddsocketsimportOddSocketsasyncdefmain():
client=OddSockets({
'api_key': 'ak_live_1234567890abcdef',
'user_id': 'server-user-123'
})
channel=client.channel('my-channel')
# Subscribe to messagesasyncdefon_message(message):
print(f'Received: {message}')
awaitchannel.subscribe(on_message)
# Publish a messageawaitchannel.publish('Hello from Python!')
# Keep the connection aliveawaitasyncio.sleep(10)
if__name__=='__main__':
asyncio.run(main())

Basic Usage (Sync)

fromoddsockets.syncimportOddSocketsclient=OddSockets(
api_key='ak_live_1234567890abcdef',
manager_url='https://connect.oddsockets.tyga.network'
)
channel=client.channel('my-channel')
# Subscribe to messagesdefon_message(message):
print(f'Received: {message}')
channel.subscribe(on_message)
# Publish a messagechannel.publish('Hello from Python!')
# Keep the connection aliveimporttimetime.sleep(10)

PubNub Migration

fromoddsockets.pubnub_compatimportPubNub# Drop-in replacement for PubNubpubnub=PubNub({
'publish_key': 'ak_live_1234567890abcdef',
'subscribe_key': 'ak_live_1234567890abcdef',
'user_id': 'user123'
})
defmessage_callback(message, envelope):
print(f'Message: {message}')
pubnub.add_listener({
'message': message_callback
})
pubnub.subscribe().channels(['my-channel']).execute()

Type Hints

fromtypingimportDict, AnyfromoddsocketsimportOddSockets, Channelfromoddsockets.typesimportMessageclient: OddSockets=OddSockets({
'api_key': 'ak_live_1234567890abcdef'
})
channel: Channel=client.channel('typed-channel')
asyncdeftyped_handler(message: Message) ->None:
data: Dict[str, Any] =message.dataprint(f'Typed message: {data}')

Documentation

Examples

Explore our comprehensive examples:

Configuration

Client Options

fromoddsocketsimportOddSocketsclient=OddSockets({
'api_key': 'your-api-key', # Required: Your OddSockets API key'user_id': 'user-id', # Optional: User identifier'options': { # Optional: connection options'auto_connect': True, # Auto-connect on creation'reconnect_attempts': 5, # Max reconnection attempts'heartbeat_interval': 30.0# Heartbeat interval (seconds)
}
})

Channel Options

# Subscribe with optionsawaitchannel.subscribe(
callback,
enable_presence=True, # Enable presence trackingretain_history=True, # Retain message historyfilter_expression='user.premium == True'# Message filter
)
# Publish with optionsawaitchannel.publish(
message,
ttl=3600, # Time to live (seconds)metadata={'priority': 'high'}, # Additional metadatastore_in_history=True# Store in message history
)

Enhanced Features

Beyond core pub/sub, OddSockets ships a Slack-like enhanced surface — reactions, typing indicators, threads, read receipts, presence/status, notifications, DMs, channel management, message editing and search. It lives on client.enhanced. The pattern is always the same:

  1. Send an action with an await client.enhanced.* coroutine (snake_case).
  2. Receive the paired broadcast with client.on('<event>', handler).
importasynciofromoddsocketsimportOddSocketsasyncdefmain():
client=OddSockets({'api_key': 'ak_live_1234567890abcdef', 'user_id': 'alice'})
channel=client.channel('room-42')
awaitchannel.subscribe()
# Receive-path: broadcasts from other users on the channelclient.on('user_typing', lambdae: print(f"{e['userId']} is typing"))
client.on('reaction_added', lambdae: print(f"{e['userId']} reacted {e['emoji']}"))
client.on('thread_reply', lambdae: print('New reply:', e))
# Send-path: enhanced actions over the live socketawaitclient.enhanced.start_typing('alice', 'room-42')
awaitclient.enhanced.add_reaction(
message_id='msg-1',
channel='room-42',
emoji=':thumbsup:',
user_id='alice',
user_name='Alice'
)
awaitclient.enhanced.thread_reply(
channel='room-42',
parent_message_id='msg-1',
message='Replying in the thread',
user_id='alice',
user_name='Alice'
)
awaitasyncio.sleep(2)
awaitclient.disconnect()
asyncio.run(main())

Each area exposes coroutine methods on client.enhanced; the worker broadcasts the paired events which you handle with client.on(...). Query methods (get_*, search_*) await and return the worker response.

AreaRequests (await client.enhanced.*)Broadcast events (client.on)
Typingstart_typing, stop_typinguser_typing, user_stopped_typing
Reactionsadd_reaction, remove_reaction, get_reactionsreaction_added, reaction_removed
Threadsthread_reply, get_thread, subscribe_thread, follow_thread, mark_thread_readthread_reply, thread_subscribed, thread_followed, thread_read_updated
Read receiptsmark_read, mark_all_read, get_unread_countsuser_read, unread_count_updated, all_marked_read
Messagesedit_message, delete_message, pin_message, unpin_message, get_pinned_messages, search_messagesmessage_edited, message_deleted, message_pinned, message_unpinned
Presence & statusset_status, set_custom_status, set_dnd, get_user_presenceuser_status_changed, custom_status_updated, dnd_status_changed
Channelscreate_channel, update_channel, archive_channel, invite_to_channel, join_channel, leave_channelchannel_created, channel_updated, user_invited, user_joined_channel, user_left_channel
DMscreate_dm, send_dm, get_dm_conversationsdm_created, dm_received
Notificationssubscribe_notifications, get_notifications, mark_notification_read, clear_notificationsnotification, notification_read, notifications_cleared
File uploadsstart_file_upload, upload_progress, upload_completefile_upload_completed, file_upload_progress, file_upload_failed

For any worker event not wrapped above, subscribe with the raw client.on('<event>', handler) API — all enhanced broadcasts are forwarded onto the client surface.

🐍 Python Support

  • Python 3.8+
  • AsyncIO support
  • Type hints included
  • Both sync and async APIs

🧪 Testing

# Run tests
pytest
# Run tests with coverage
pytest --cov=oddsockets
# Run async tests
pytest -m asyncio
# Run integration tests
pytest tests/integration/

🔨 Building

# Install development dependencies
pip install -e ".[dev]"# Run linting
flake8 src/
black src/
mypy src/
# Build package
python -m build
# Install locally
pip install -e .

📈 Performance

OddSockets Python SDK delivers superior performance:

  • 50% lower latency compared to PubNub
  • 99.9% uptime with automatic failover
  • Unlimited message size - no artificial limits
  • High throughput - handle millions of messages

🔐 Security

  • End-to-end encryption available
  • API key authentication with fine-grained permissions
  • Rate limiting and abuse protection
  • GDPR compliant data handling

Framework Integrations

Django

# settings.pyODDSOCKETS= {
'API_KEY': 'ak_live_1234567890abcdef',
'MANAGER_URL': 'https://connect.oddsockets.tyga.network'
}
# views.pyfromdjango.httpimportJsonResponsefromoddsockets.djangoimportget_clientasyncdefsend_message(request):
client=get_client()
channel=client.channel('notifications')
awaitchannel.publish({
'user_id': request.user.id,
'message': 'Hello from Django!'
})
returnJsonResponse({'status': 'sent'})

FastAPI

fromfastapiimportFastAPIfromoddsocketsimportOddSocketsapp=FastAPI()
client=OddSockets(api_key='ak_live_1234567890abcdef')
@app.post("/send-message")asyncdefsend_message(message: str):
channel=client.channel('api-messages')
awaitchannel.publish({'text': message})
return {"status": "sent"}
@app.on_event("startup")asyncdefstartup():
awaitclient.connect()
@app.on_event("shutdown")asyncdefshutdown():
awaitclient.disconnect()

Flask

fromflaskimportFlask, request, jsonifyfromoddsockets.syncimportOddSocketsapp=Flask(__name__)
client=OddSockets(api_key='ak_live_1234567890abcdef')
@app.route('/send-message', methods=['POST'])defsend_message():
message=request.json.get('message')
channel=client.channel('flask-messages')
channel.publish({'text': message})
returnjsonify({'status': 'sent'})

🌍 Other SDKs

OddSockets is available in multiple languages:

  • JavaScript SDK - Browser + Node.js, TypeScript ready
  • Go SDK - High-performance, goroutines and channels
  • Java SDK - Enterprise-ready, Spring Boot integration
  • C# SDK - .NET Core/Framework, Azure integrations
  • Swift SDK - iOS native, Combine framework
  • Kotlin SDK - Android native, coroutines support

📞 Support

📄 License

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": "you@example.com", "agentName": "my-agent", "platform": "python"}'

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": "you@example.com", "code": "123456", "agentName": "my-agent"}'

Plans

FreeStarterPro
Price$0/mo$49.99/mo$299/mo
MAU1001,00050,000
Concurrent connections501,000Unlimited
Messages/day10,0004,320,000Unlimited
Messages/minute1003,000Unlimited
Channels10UnlimitedUnlimited
Storage100MB (24h)50GB (6 months)Unlimited
WebhooksNoYesYes
AnalyticsNoYesYes
SupportCommunity24/5 email & chatDedicated 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.

Get Accredited

tyga.games accreditation

Prove you can build and operate real-time features on OddSockets — channels, presence, pub/sub, delivery guarantees and production liveops — on the stack itself. Three tiers (TCU / TCA / TCP), certified through tyga.games and delivered on ClassaaS.

Get accredited on tyga.games →

Support

License

MIT License - Copyright (c) 2026 Joe Wee, Tyga.Cloud Ltd. See LICENSE for details.

About

Python SDK for OddSockets — real-time WebSocket channels, pub/sub, presence. AsyncIO.

Topics

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages