Invitation System

Send real-time invitations to users and handle call requests with BaxCloud's invitation system

Overview

BaxCloud's Invitation System provides a seamless way to send real-time call invitations between users. Whether you're building a one-on-one calling app, a video conferencing platform, or a live streaming service with viewer-to-host calls, the invitation system handles the signaling, delivery, and response workflow for you.

The system works independently of the room connection, meaning you can send invitations before users join a room. This makes it perfect for implementing traditional "calling" experiences where one user initiates contact and the other accepts or declines.

Call Someone

Initiate 1-on-1 calls by sending invitations to specific users with custom messages

Invite to Meeting

Invite multiple participants to join an ongoing video conference or meeting room

Real-time Notifications

Recipients receive instant notifications with invitation details and can respond immediately

How It Works

The invitation system uses BaxCloud's real-time signaling infrastructure to deliver invitations instantly. Here's how the flow works:

Invitation Flow

  1. Sender calls sendCallInvitation() with recipient user ID and invitation details
  2. BaxCloud delivers the invitation to the recipient in real-time via their active connection
  3. Recipient's onInvitationReceived event handler is triggered with invitation data
  4. Recipient can call acceptCallInvitation() or declineCallInvitation()
  5. Sender receives callback with the response via onInvitationAccepted or onInvitationDeclined
  6. If accepted, both parties can join the specified room using the room URL or name
Prerequisites: To receive invitations, users must be connected to BaxCloud (authenticated) but don't need to be in a room. The system tracks online presence automatically.

Sending Invitations

Initiate a call by sending an invitation to another user

Use the sendCallInvitation() method to send an invitation. You can specify the call type, room details, and a custom message.

1import { BaxCloudClient } from '@baxcloud/react-sdk';
2
3const client = new BaxCloudClient({
4  projectId: 'your-project-id',
5  apiKey: 'your-api-key',
6});
7
8// Send a call invitation
9const invitation = await client.sendCallInvitation({
10  to: 'user-456', // Recipient's user ID
11  roomName: 'call-room-123',
12  callType: 'video_call', // 'video_call', 'audio_call', or 'live_streaming'
13  message: 'Hey! Want to hop on a quick video call?',
14  roomUrl: 'https://yourapp.com/room/call-room-123', // Optional deep link
15});
16
17console.log('Invitation sent:', invitation.invitationId);
18
19// Listen for responses
20client.onInvitationAccepted((data) => {
21  console.log('User accepted!', data);
22  // Join the room
23  client.connect({
24    roomName: data.roomName,
25    participant: { /* ... */ },
26    liveType: 'video_call',
27  });
28});
29
30client.onInvitationDeclined((data) => {
31  console.log('User declined:', data);
32});
Room URLs: The roomUrl parameter is useful for deep linking. When the recipient accepts on mobile, you can use this to navigate them directly to the call screen in your app.

Receiving Invitations

Handle incoming call invitations from other users

Register an event listener for onInvitationReceived to be notified when someone sends you a call invitation. The event provides all the invitation details including sender info, call type, and message.

1// Listen for incoming invitations
2client.onInvitationReceived((invitation) => {
3  console.log('Incoming call from:', invitation.from);
4  console.log('Call type:', invitation.callType);
5  console.log('Message:', invitation.message);
6  console.log('Room:', invitation.roomName);
7  
8  // Show UI notification to user
9  showCallNotification({
10    invitationId: invitation.invitationId,
11    callerName: invitation.fromUser.name,
12    callerAvatar: invitation.fromUser.avatarUrl,
13    callType: invitation.callType,
14    message: invitation.message,
15    onAccept: () => acceptInvitation(invitation.invitationId),
16    onDecline: () => declineInvitation(invitation.invitationId),
17  });
18});
19
20// Example: React component for incoming call UI
21function IncomingCallModal({ invitation, onAccept, onDecline }) {
22  return (
23    <div className="modal">
24      <img src={invitation.fromUser.avatarUrl} alt={invitation.fromUser.name} />
25      <h2>{invitation.fromUser.name} is calling...</h2>
26      <p>{invitation.message}</p>
27      <div className="buttons">
28        <button onClick={onAccept} className="accept">
29          <Check /> Accept
30        </button>
31        <button onClick={onDecline} className="decline">
32          <X /> Decline
33        </button>
34      </div>
35    </div>
36  );
37}
Foreground vs Background: On mobile platforms, you may need to use push notifications to alert users when they receive an invitation while your app is in the background. Integrate with Firebase Cloud Messaging (FCM) or Apple Push Notification Service (APNS) for full coverage.

Accepting Invitations

Accept a call invitation and join the room

When a user wants to accept an invitation, call acceptCallInvitation() with the invitation ID. This notifies the sender and you can then proceed to join the room.

1// Accept the invitation
2await client.acceptCallInvitation(invitationId);
3
4// Then join the room
5await client.connect({
6  roomName: invitation.roomName,
7  participant: {
8    userId: 'user-123',
9    name: 'Jane Doe',
10    avatarUrl: 'https://example.com/avatar.jpg',
11    isHost: false,
12  },
13  liveType: invitation.callType, // 'video_call', 'audio_call', etc.
14});
15
16// Enable camera/microphone
17await client.enableCamera();
18await client.enableMicrophone();

Declining Invitations

Reject a call invitation

If the user doesn't want to accept the call, use declineCallInvitation() to notify the sender that the invitation was rejected.

1// Decline the invitation
2await client.declineCallInvitation(invitationId);
3
4// Optional: Provide a reason
5await client.declineCallInvitation(invitationId, {
6  reason: 'busy', // 'busy', 'declined', 'unavailable'
7  message: 'Sorry, I\'m in a meeting right now',
8});

Canceling Invitations

Cancel an invitation you sent before it's answered

If the sender wants to cancel an invitation (for example, if the recipient is taking too long to respond), use cancelCallInvitation().

1// Cancel the invitation
2await client.cancelCallInvitation(invitationId);
3
4// Example: Auto-cancel after 30 seconds
5const invitation = await client.sendCallInvitation({ /* ... */ });
6
7const timeoutId = setTimeout(async () => {
8  try {
9    await client.cancelCallInvitation(invitation.invitationId);
10    console.log('Invitation timed out');
11  } catch (error) {
12    // Already accepted/declined
13    console.log('Invitation already answered');
14  }
15}, 30000);
16
17// Clear timeout if user responds
18client.onInvitationAccepted((data) => {
19  clearTimeout(timeoutId);
20});
21
22client.onInvitationDeclined((data) => {
23  clearTimeout(timeoutId);
24});
The recipient will receive an onInvitationCanceled event when the sender cancels the invitation. You can use this to dismiss any UI notifications showing the incoming call.

Complete Invitation Flow Example

Full implementation showing both sender and receiver sides

1import { useState, useEffect } from 'react';
2import { BaxCloudClient } from '@baxcloud/react-sdk';
3
4function CallApp() {
5  const [client] = useState(() => new BaxCloudClient({
6    projectId: 'your-project-id',
7    apiKey: 'your-api-key',
8  }));
9  const [incomingInvitation, setIncomingInvitation] = useState(null);
10  const [outgoingInvitation, setOutgoingInvitation] = useState(null);
11
12  useEffect(() => {
13    // Listen for incoming invitations
14    client.onInvitationReceived((invitation) => {
15      setIncomingInvitation(invitation);
16    });
17
18    // Listen for invitation responses
19    client.onInvitationAccepted((data) => {
20      console.log('User accepted! Joining room...');
21      setOutgoingInvitation(null);
22      joinRoom(data.roomName);
23    });
24
25    client.onInvitationDeclined((data) => {
26      alert('User declined the call');
27      setOutgoingInvitation(null);
28    });
29
30    client.onInvitationCanceled((data) => {
31      setIncomingInvitation(null);
32    });
33
34    return () => client.disconnect();
35  }, [client]);
36
37  const callUser = async (userId: string) => {
38    const invitation = await client.sendCallInvitation({
39      to: userId,
40      roomName: `call-${Date.now()}`,
41      callType: 'video_call',
42      message: 'Join me for a video call!',
43    });
44    setOutgoingInvitation(invitation);
45
46    // Auto-cancel after 30 seconds
47    setTimeout(() => {
48      if (outgoingInvitation?.invitationId === invitation.invitationId) {
49        client.cancelCallInvitation(invitation.invitationId);
50        setOutgoingInvitation(null);
51      }
52    }, 30000);
53  };
54
55  const acceptInvitation = async () => {
56    if (!incomingInvitation) return;
57    
58    await client.acceptCallInvitation(incomingInvitation.invitationId);
59    setIncomingInvitation(null);
60    joinRoom(incomingInvitation.roomName);
61  };
62
63  const declineInvitation = async () => {
64    if (!incomingInvitation) return;
65    
66    await client.declineCallInvitation(incomingInvitation.invitationId);
67    setIncomingInvitation(null);
68  };
69
70  const joinRoom = async (roomName: string) => {
71    await client.connect({
72      roomName,
73      participant: {
74        userId: 'current-user-id',
75        name: 'Current User',
76        isHost: false,
77      },
78      liveType: 'video_call',
79    });
80    await client.enableCamera();
81    await client.enableMicrophone();
82  };
83
84  return (
85    <div>
86      {/* Incoming call UI */}
87      {incomingInvitation && (
88        <div className="incoming-call-modal">
89          <img src={incomingInvitation.fromUser.avatarUrl} />
90          <h2>{incomingInvitation.fromUser.name} is calling...</h2>
91          <p>{incomingInvitation.message}</p>
92          <button onClick={acceptInvitation}>Accept</button>
93          <button onClick={declineInvitation}>Decline</button>
94        </div>
95      )}
96
97      {/* Outgoing call UI */}
98      {outgoingInvitation && (
99        <div className="outgoing-call-modal">
100          <p>Calling...</p>
101          <button onClick={() => {
102            client.cancelCallInvitation(outgoingInvitation.invitationId);
103            setOutgoingInvitation(null);
104          }}>
105            Cancel
106          </button>
107        </div>
108      )}
109
110      {/* Call button */}
111      <button onClick={() => callUser('target-user-id')}>
112        Call User
113      </button>
114    </div>
115  );
116}

Best Practices

1. Implement Timeouts

Always set a timeout for outgoing invitations (typically 30-60 seconds). If the recipient doesn't respond in time, automatically cancel the invitation to avoid hanging states.

2. Handle Offline Users

Check if the recipient is online before sending an invitation. BaxCloud provides presence APIs to query user online status. If a user is offline, show an appropriate message instead of sending an invitation that won't be delivered.

3. Provide Clear UI Feedback

Show clear visual and audio notifications for incoming invitations. Include the caller's name, avatar, and message. Use distinctive ringtones and vibrations on mobile to ensure users don't miss calls.

4. Support Background Notifications

Integrate push notifications (FCM for Android, APNS for iOS) to deliver invitations when your app is in the background or closed. BaxCloud can send webhook events to your backend to trigger push notifications.

5. Track Invitation State

Maintain invitation state in your UI to prevent duplicate invitations and handle edge cases like network disconnections. Use the invitation ID to track which invitation corresponds to which UI element.

6. Add Call History

Keep a record of sent and received invitations in your database. This allows users to see missed calls and call back later, similar to traditional phone apps.

Pro Tip: Combine the invitation system with BaxCloud's presence API to show real-time online status indicators next to contacts, making it clear when someone is available for a call.