Skip to main content

Overview

The Osmium Chat Protocol invite system enables users to join communities, groups, and connect with other users through shareable invite codes.

Invite Types

Three types of invites are supported:
enum InviteType {
  UNKNOWN = 0;
  COMMUNITY = 1;
  GROUP = 2;
  USER = 3;
}
UNKNOWN
0
Unknown or invalid invite type
COMMUNITY
1
Invite to join a community (server)
GROUP
2
Invite to join a group chat
USER
3
Invite to connect with another user (friend request)

Lookup Invite

Preview invite details before accepting it. Method: auth.lookupInviteauth.InvitePreview

Request Message

message LookupInvite {
  string code = 1;
}

Parameters

code
string
required
The invite code to lookup

Response Message

message InvitePreview {
  string code = 1;
  // @snowflake<User>
  fixed64 creator_id = 2;
  // @snowflake<Keyable>
  fixed64 target_id = 3;
  InviteType target_type = 4;
  optional fixed64 expires_at = 5;

  optional tangle.client.types.User creator = 6;

  oneof target_info {
    tangle.client.types.Community community = 7;
    tangle.client.types.Group chat = 8;
    tangle.client.types.User user = 9;
  }
}

Response Fields

code
string
required
The invite code
creator_id
fixed64
required
Snowflake ID of the user who created the invite
target_id
fixed64
required
Snowflake ID of the target (community, group, or user)
target_type
InviteType
required
Type of invite: COMMUNITY, GROUP, or USER
expires_at
fixed64
Optional expiration timestamp (Unix timestamp in milliseconds). If not set, the invite never expires.
creator
User
Optional user object for the invite creator, including profile information
target_info
Community | Group | User
Detailed information about the invite target. Contains one of:
  • community: Community object if target_type is COMMUNITY
  • chat: Group object if target_type is GROUP
  • user: User object if target_type is USER

Example Usage

const inviteCode = "abc123xyz";
const preview = await client.auth.lookupInvite({ code: inviteCode });

console.log(`Invite Type: ${preview.target_type}`);
console.log(`Created by: ${preview.creator?.name || preview.creator_id}`);

if (preview.expires_at) {
  const expiresAt = new Date(Number(preview.expires_at));
  console.log(`Expires: ${expiresAt.toLocaleString()}`);
} else {
  console.log("Expires: Never");
}

// Check invite type and display appropriate information
switch (preview.target_type) {
  case InviteType.COMMUNITY:
    console.log(`Community: ${preview.community.name}`);
    console.log(`Members have ${preview.community.permissions} permissions`);
    break;
    
  case InviteType.GROUP:
    console.log(`Group: ${preview.chat.name}`);
    console.log(`Participants: ${preview.chat.participant_ids.length}`);
    break;
    
  case InviteType.USER:
    console.log(`User: ${preview.user.name}`);
    if (preview.user.username) {
      console.log(`Username: @${preview.user.username}`);
    }
    break;
}
Always lookup an invite before using it to show users what they’re about to join.

Use Invite

Accept an invite to join a community, group, or connect with a user. Method: auth.useInvite()

Request Message

message UseInvite {
  string code = 1;
}

Parameters

code
string
required
The invite code to accept

Response

Returns an empty response on success.

Example Usage

// Step 1: Lookup the invite
const inviteCode = "abc123xyz";
const preview = await client.auth.lookupInvite({ code: inviteCode });

// Step 2: Show preview to user
console.log(`You've been invited to join: ${preview.community?.name || preview.chat?.name || preview.user?.name}`);

// Step 3: User confirms, use the invite
await client.auth.useInvite({ code: inviteCode });

console.log("Successfully joined!");
Once an invite is used, the user immediately joins the target community/group or connects with the user. Ensure the user confirms before calling this method.

Created Invite

Response model returned when creating an invite (for communities, groups, or users).
message CreatedInvite {
  string code = 1;
}
code
string
required
The generated invite code that can be shared
Invite creation endpoints are defined in their respective service modules (communities, groups, users). This message is the standard response format for all invite creation operations.

Invite List

Container for multiple invite previews.
message InviteList {
  repeated InvitePreview invites = 1;
}
invites
InvitePreview[]
required
Array of invite preview objects
This message is used when retrieving multiple invites, such as getting all invites for a community or group.

Common Patterns

async function validateInviteLink(inviteCode) {
  try {
    const preview = await client.auth.lookupInvite({ code: inviteCode });
    
    // Check expiration
    if (preview.expires_at) {
      if (Number(preview.expires_at) < Date.now()) {
        return { valid: false, reason: "Invite has expired" };
      }
    }
    
    // Check invite type
    if (preview.target_type === InviteType.UNKNOWN) {
      return { valid: false, reason: "Invalid invite type" };
    }
    
    return { valid: true, preview };
    
  } catch (error) {
    return { valid: false, reason: "Invite not found" };
  }
}

const validation = await validateInviteLink("abc123");
if (validation.valid) {
  // Show invite preview to user
} else {
  console.error(validation.reason);
}

Display Invite Preview

function formatInvitePreview(preview) {
  const expiresText = preview.expires_at
    ? `Expires ${new Date(Number(preview.expires_at)).toLocaleDateString()}`
    : "Never expires";
  
  const creatorText = preview.creator
    ? `Invited by ${preview.creator.name}`
    : "";
  
  let targetInfo = {};
  
  switch (preview.target_type) {
    case InviteType.COMMUNITY:
      targetInfo = {
        type: "Community",
        name: preview.community.name,
        icon: preview.community.photo,
        subtitle: "Join this community"
      };
      break;
      
    case InviteType.GROUP:
      targetInfo = {
        type: "Group Chat",
        name: preview.chat.name,
        subtitle: `${preview.chat.participant_ids.length} members`
      };
      break;
      
    case InviteType.USER:
      targetInfo = {
        type: "User",
        name: preview.user.name,
        icon: preview.user.photo,
        subtitle: preview.user.username ? `@${preview.user.username}` : ""
      };
      break;
  }
  
  return {
    ...targetInfo,
    creator: creatorText,
    expiration: expiresText,
    code: preview.code
  };
}
// Handle invite deep links like: osmium://invite/abc123xyz
async function handleInviteDeepLink(url) {
  const inviteCode = url.split('/').pop();
  
  try {
    // Lookup first
    const preview = await client.auth.lookupInvite({ code: inviteCode });
    
    // Show confirmation dialog to user
    const confirmed = await showConfirmDialog(
      `Join ${preview.community?.name || preview.chat?.name || preview.user?.name}?`
    );
    
    if (confirmed) {
      await client.auth.useInvite({ code: inviteCode });
      
      // Navigate to the joined community/group/user
      navigateTo(preview.target_type, preview.target_id);
    }
    
  } catch (error) {
    showError("Invalid or expired invite link");
  }
}

Build docs developers (and LLMs) love