Skip to main content

Overview

Osmium Chat Protocol uses a bidirectional message-based communication model with Protocol Buffers. All communication flows through two main message types: ClientMessage (client → server) and ServerMessage (server → client).

ClientMessage Structure

Every message sent from the client to the server follows this structure:
message ClientMessage {
  uint32 id = 1;
  oneof message {
    auth.SignIn auth_sign_in = 2;
    auth.SignUp auth_sign_up = 3;
    messages.SendMessage messages_send_message = 4;
    messages.GetHistory messages_get_history = 5;
    communities.CreateCommunity communities_create_community = 6;
    // ... and many more RPC methods
  }
}

Key Fields

id
uint32
required
Unique identifier for this request. Used to match server responses to client requests. Each request must have a unique ID within the session.
message
oneof
required
The actual RPC method being invoked. Only one field can be set at a time, representing the specific operation to perform.

Available RPC Methods

The protocol supports over 80 different RPC methods organized by domain:
  • auth_sign_in - Sign in to an existing account
  • auth_sign_up - Create a new account
  • auth_authorize - Authorize a session
  • auth_get_sessions - List active sessions
  • auth_revoke_sessions - Revoke specific sessions
  • auth_reset_password - Request password reset
  • auth_verify_email - Verify email address
  • messages_send_message - Send a new message
  • messages_get_history - Retrieve message history
  • messages_delete_message - Delete a message
  • messages_edit_message - Edit an existing message
  • messages_search - Search messages
  • messages_forward_message - Forward a message
  • communities_create_community - Create a new community
  • communities_get_communities - List communities
  • communities_create_channel - Create a channel
  • communities_get_channels - List channels
  • communities_get_channel_members - List channel members
  • communities_edit_channel - Edit channel settings
  • chats_get_chats - List all chats
  • chats_get_chat - Get specific chat details
  • chats_create_chat - Create a group chat
  • chats_mark_chat_read - Mark messages as read
  • chats_set_typing - Send typing indicator
  • friends_get_relationships - List all relationships
  • friends_sync_friends - Sync friend list
  • friends_change_relationship - Modify relationship status

ServerMessage Structure

Every message sent from the server to the client follows this structure:
message ServerMessage {
  uint32 id = 1;
  oneof message {
    tangle.client.updates.Update update = 2;
    RPCResult result = 3;
  }
}

Message Types

id
uint32
required
Sequential message ID assigned by the server. Used for ordering and tracking.
update
Update
Real-time update notification (e.g., new message, user status change). These are pushed to the client without a corresponding request.
result
RPCResult
Response to a client RPC request. Contains either successful result data or an error.

RPC Result System

RPCResult Message

When the server responds to a client request, it uses the RPCResult message:
message RPCResult {
  uint32 req_id = 1;
  oneof result {
    RPCError error = 2;
    messages.SentMessage sent_message = 3;
    auth.Authorization authorization = 4;
    communities.Communities communities = 5;
    communities.Channels channels = 6;
    messages.Messages messages = 7;
    // ... specific result types for each RPC method
  }
}
req_id
uint32
required
References the id field from the original ClientMessage. This allows clients to match responses to their requests.
result
oneof
required
Either an error or a success result. The specific success type depends on which RPC method was called.

RPCError Structure

When an RPC call fails, the server returns an error:
message RPCError {
  uint32 error_code = 1;
  string error_message = 2;
}
error_code
uint32
required
Numeric error code identifying the type of error. Clients can use this for programmatic error handling.
error_message
string
required
Human-readable error description. Useful for debugging and user-facing error messages.

How RPCs Work

The RPC flow follows this sequence:
1

Client sends request

Client creates a ClientMessage with a unique id and sets one of the RPC method fields.
// Example: Sending a message
{
  id: 42,
  messages_send_message: {
    chat_ref: { channel: { community_id: 123, channel_id: 456 } },
    message: "Hello, world!"
  }
}
2

Server processes request

Server receives the message, validates it, performs the requested operation, and prepares a response.
3

Server sends response

Server sends back a ServerMessage containing an RPCResult with req_id matching the original request’s id.
// Success response
{
  id: 1001,
  result: {
    req_id: 42,
    sent_message: {
      message: { /* full message object */ },
      temp_id: "client-temp-123"
    }
  }
}

// Error response
{
  id: 1001,
  result: {
    req_id: 42,
    error: {
      error_code: 403,
      error_message: "You do not have permission to send messages in this channel"
    }
  }
}
4

Client handles response

Client uses req_id to find the original request, then processes either the success result or error accordingly.

Example RPC Flows

Sending a Message

{
  id: 100,
  messages_send_message: {
    chat_ref: {
      channel: {
        community_id: 789,
        channel_id: 101
      }
    },
    message: "Hello everyone!",
    temp_id: "temp-msg-456"
  }
}

Fetching Message History

{
  id: 101,
  messages_get_history: {
    chat_ref: {
      channel: {
        community_id: 789,
        channel_id: 101
      }
    },
    limit: 50,
    before_id: 999888777
  }
}
The separation of RPC results and real-time updates allows clients to maintain a clear distinction between responses to their actions and asynchronous events from other users.

Best Practices

Use Unique Request IDs

Always increment or randomize request IDs to avoid collisions. Many clients use a simple counter starting from 1.

Handle Both Success and Error

Every RPC call can fail. Always implement error handling for graceful degradation.

Match Responses Correctly

Use req_id to associate responses with pending requests, especially important for async implementations.

Set Reasonable Timeouts

Implement request timeouts to detect network issues or server problems.

Message Flow

Learn about the complete request/response lifecycle

Real-time Updates

Understand how server-pushed updates work

Snowflake IDs

Learn about the ID system used throughout the protocol

Build docs developers (and LLMs) love