Official Elixir SDK for OddSockets real-time messaging platform. Provides a simple interface for pub/sub messaging with automatic manager discovery and worker load balancing.
Add oddsockets to your list of dependencies in mix.exs:
def deps do
[
{:oddsockets, "~> 1.0.0"}
]
end# Start a client
{:ok, client} = OddSockets.start_link(api_key: "your-api-key")
# Get a channel
channel = OddSockets.channel(client, "my-channel")
# Subscribe to messages
:ok = OddSockets.Channel.subscribe(channel, fn message ->
IO.inspect(message, label: "Received")
end)
# Publish a message
{:ok, result} = OddSockets.Channel.publish(channel, %{text: "Hello World!"})- Automatic Manager Discovery: Connects to the optimal manager endpoint
- Session Stickiness: Clients stick to assigned workers across reconnections
- Message Size Validation: Industry-standard 32KB message size limits
- Automatic Reconnection: Exponential backoff reconnection strategy
- Presence Tracking: Real-time user presence and state management
- Message History: Configurable message history retention
- Bulk Publishing: Publish multiple messages efficiently
- Event System: Subscribe to connection and channel events
Start an OddSockets client.
{:ok, client} = OddSockets.start_link(
api_key: "your-api-key",
user_id: "user123", # optional
auto_connect: true # optional, default: true
)Manually connect to the platform.
:ok = OddSockets.connect(client)Disconnect from the platform.
:ok = OddSockets.disconnect(client)Get current connection state.
state = OddSockets.get_state(client)
# Returns: :disconnected | :connecting | :connected | :reconnectingGet or create a channel.
channel = OddSockets.channel(client, "channel-name")Subscribe to channel messages.
:ok = OddSockets.Channel.subscribe(channel, fn message ->
IO.inspect(message)
end, %{
max_history: 100, # optional, default: 100
retain_history: true, # optional, default: true
enable_presence: false # optional, default: false
})Publish a message to the channel.
{:ok, result} = OddSockets.Channel.publish(channel, %{
text: "Hello World!",
user: "alice"
}, %{
ttl: 300, # optional, time to live in seconds
metadata: %{priority: "high"} # optional
})Get message history.
{:ok, messages} = OddSockets.Channel.get_history(channel, %{
count: 50, # optional, default: 50
start: "2023-01-01T00:00:00Z", # optional
end: "2023-01-02T00:00:00Z" # optional
})Get current presence information.
{:ok, presence} = OddSockets.Channel.get_presence(channel)Update user state.
{:ok, result} = OddSockets.Channel.update_state(channel, %{
status: "online",
location: "New York"
})Publish multiple messages at once.
messages = [
%{channel: "channel1", message: %{text: "Hello"}},
%{channel: "channel2", message: %{text: "World"}, options: %{ttl: 300}}
]
{:ok, results} = OddSockets.publish_bulk(client, messages)Subscribe to client events.
:ok = OddSockets.subscribe_events(client)
# Handle events in your process
receive do
{:oddsockets_event, :connected} ->
IO.puts("Connected to OddSockets!")
{:oddsockets_event, {:error, reason}} ->
IO.puts("Connection error: #{inspect(reason)}")
{:oddsockets_event, {:worker_assigned, info}} ->
IO.puts("Assigned to worker: #{info.worker_id}")
endAvailable events:
:connecting- Connection attempt started:connected- Successfully connected:disconnected- Disconnected from platform{:error, reason}- Connection error occurred{:reconnecting, info}- Reconnection attempt{:worker_assigned, info}- Worker assignment received:max_reconnect_attempts_reached- Reconnection failed
You can set default configuration using environment variables:
export ODDSOCKETS_API_KEY="your-api-key"
export ODDSOCKETS_MANAGER_URL="https://manager1.oddsockets.tyga.network"Configure in your config/config.exs:
config :oddsockets,
api_key: "your-api-key",
manager_url: "https://manager1.oddsockets.tyga.network"The SDK uses structured error handling:
case OddSockets.Channel.publish(channel, message) do
{:ok, result} ->
IO.puts("Message published: #{result.message_id}")
{:error, :client_not_connected} ->
IO.puts("Client is not connected")
{:error, reason} ->
IO.puts("Publish failed: #{inspect(reason)}")
endCommon error types:
:client_not_connected- Client is not connected to platform:manager_offline- Manager is not available:invalid_response- Invalid response from server{:http_error, status}- HTTP error with status code
Messages are limited to 32KB (industry standard) for reliable real-time messaging:
# This will raise an OddSockets.Error
large_message = String.duplicate("x", 40000)
OddSockets.Channel.publish(channel, large_message)defmodule ChatApp do
def start do
# Start client
{:ok, client} = OddSockets.start_link(api_key: "your-api-key")
# Get channel
channel = OddSockets.channel(client, "general")
# Subscribe to messages
:ok = OddSockets.Channel.subscribe(channel, &handle_message/1)
# Send a message
{:ok, _} = OddSockets.Channel.publish(channel, %{
text: "Hello everyone!",
user: "alice"
})
# Keep process alive
Process.sleep(:infinity)
end
defp handle_message(message) do
IO.puts("[#{message["user"]}]: #{message["text"]}")
end
enddefmodule PresenceApp do
def start do
{:ok, client} = OddSockets.start_link(api_key: "your-api-key")
channel = OddSockets.channel(client, "lobby")
# Subscribe with presence enabled
:ok = OddSockets.Channel.subscribe(channel, &handle_message/1, %{
enable_presence: true
})
# Update user state
{:ok, _} = OddSockets.Channel.update_state(channel, %{
status: "online",
location: "New York"
})
# Get current presence
{:ok, presence} = OddSockets.Channel.get_presence(channel)
IO.puts("Users online: #{presence.count}")
end
defp handle_message(%{"type" => "presence_change"} = message) do
IO.puts("User #{message["user"]["user_id"]} #{message["action"]}")
end
defp handle_message(message) do
IO.puts("Message: #{inspect(message)}")
end
endRun the test suite:
mix testGenerate documentation:
mix docs- Fork the repository
- Create your feature branch (
git checkout -b feature/amazing-feature) - Commit your changes (
git commit -m 'Add amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
This project is licensed under the MIT License - see the LICENSE file for details.
curl -X POST https://oddsockets.com/api/agent-signup \
-H "Content-Type: application/json" \
-d '{"email": "you@example.com", "agentName": "my-agent", "platform": "elixir"}'
# Then verify with the 6-digit code from your email:
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"}'| 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 |
| Channels | 10 | Unlimited | Unlimited |
| Storage | 100MB (24h) | 50GB (6 months) | Unlimited |
MIT License - Copyright (c) 2026 Joe Wee, Tyga.Cloud Ltd. See LICENSE for details.
- Initial release
- Full JavaScript SDK pattern compliance
- Manager discovery and session stickiness
- Message size validation
- Automatic reconnection
- Presence tracking
- Message history
- Bulk publishing
- Event system