Recover Pending Call Invites

When a user receives an inbound call invite and then refreshes the page (or restarts the app) before answering, the Client SDK can automatically re-deliver the invite — no extra API call required.

This works because the Conversation Service stores pending events for approximately 30 seconds. When you pass the previous session ID to createSession, the server replays those events into the new session and the callInvite event (or onCallInvite delegate) fires automatically.

How It Works

  1. Persist the session ID returned by createSession (e.g. in sessionStorage on web, or UserDefaults / SharedPreferences on mobile).
  2. On the next load, retrieve the saved session ID and pass it back to createSession.
  3. Register the invite listener before calling createSession so it is already in place when pending events are dispatched.

Warning: The Conversation Service retains pending events for approximately 30 seconds. If more time has passed since the original invite arrived, it will not be re-delivered.

Edge Cases

  • Window expired: If the 30-second retention window has passed, createSession still succeeds — you get a valid session, but the pending invite is not re-delivered. The caller will have timed out or cancelled by then.
  • Invalid session ID: If the stored session ID is invalid or belongs to a different user, the SDK ignores it and creates a fresh session. No pending events are replayed.
  • App killed vs page refresh: On web, sessionStorage is cleared when the tab closes, so this pattern works for in-tab refreshes. For mobile app restarts, persist the session ID in durable storage (UserDefaults / SharedPreferences).

Example

client.on('callInvite', (callId, from) => {
  console.log(`Received call invite ${callId} from ${from}`);
});

const previousSessionId = store.getSessionId();

try {
  const sessionId = previousSessionId
    ? await client.createSession(jwt, previousSessionId)
    : await client.createSession(jwt);

  store.saveSessionId(sessionId);
  console.log(`Session ready: ${sessionId}`);
} catch (error) {
  console.error('Failed to create/reconnect session', error);
}
 client.setCallInviteListener { callId, from, channelType ->
     println("Received call invite $callId from $from on $channelType")
 }

 val previousSessionId = store.getSessionId()
 if (previousSessionId != null) {
     client.createSession(jwt, previousSessionId) { error, sessionId ->
         if (error != null) {
             println("Failed to reconnect session: $error")
             return@createSession
         }

         sessionId?.let(store::saveSessionId)
         println("Reconnected session: $sessionId")
     }
 } else {
     client.createSession(jwt) { error, sessionId ->
         if (error != null) {
             println("Failed to create session: $error")
             return@createSession
         }

         sessionId?.let(store::saveSessionId)
         println("Session created: $sessionId")
     }
 }
 client.setCallInviteListener((callId, from, channelType) -> {
     System.out.println(
             "Received call invite " + callId + " from " + from + " on " + channelType
     );
     return null;
 });

 String previousSessionId = store.getSessionId();
 if (previousSessionId != null) {
     client.createSession(jwt, previousSessionId, (error, sessionId) -> {
         if (error != null) {
             System.out.println("Failed to reconnect session: " + error);
             return null;
         }

         if (sessionId != null) {
             store.saveSessionId(sessionId);
         }
         System.out.println("Reconnected session: " + sessionId);
         return null;
     });
 } else {
     client.createSession(jwt, null, (error, sessionId) -> {
         if (error != null) {
             System.out.println("Failed to create session: " + error);
             return null;
         }

         if (sessionId != null) {
             store.saveSessionId(sessionId);
         }
         System.out.println("Session created: " + sessionId);
         return null;
     });
 }
 class InviteDelegate: NSObject, VGVoiceClientDelegate {
     func voiceClient(_ client: VGVoiceClient, didReceiveInviteForCall callId: VGCallId, from caller: String, with type: VGVoiceChannelType) {
         print("Received call invite \(callId) from \(caller)")
     }

     func voiceClient(_ client: VGVoiceClient, didReceiveHangupForCall callId: VGCallId, withQuality callQuality: VGRTCQuality, reason: VGHangupReason) {}
     func voiceClient(_ client: VGVoiceClient, didReceiveInviteCancelForCall callId: VGCallId, with reason: VGVoiceInviteCancelReason) {}
     func client(_ client: VGBaseClient, didReceiveSessionErrorWith reason: VGSessionErrorReason) {}
 }

 let delegate = InviteDelegate()
 client.delegate = delegate

 if let previousSessionId = store.getSessionId() {
     client.createSession(jwt, sessionId: previousSessionId) { error, sessionId in
         guard error == nil, let sessionId = sessionId else {
             print("Failed to reconnect session: \(error?.localizedDescription ?? "unknown")")
             return
         }

         store.saveSessionId(sessionId)
         print("Reconnected session: \(sessionId)")
     }
 } else {
     client.createSession(jwt) { error, sessionId in
         guard error == nil, let sessionId = sessionId else {
             print("Failed to create session: \(error?.localizedDescription ?? "unknown")")
             return
         }

         store.saveSessionId(sessionId)
         print("Session created: \(sessionId)")
     }
 }
 self.store = store;
 client.delegate = self;

 NSString *previousSessionId = [store getSessionId];
 if (previousSessionId != nil) {
     [client createSession:jwt sessionId:previousSessionId callback:^(NSError * _Nullable error, NSString * _Nullable sessionId) {
         if (error != nil || sessionId == nil) {
             NSLog(@"Failed to reconnect session: %@", error);
             return;
         }

         [store saveSessionId:sessionId];
         NSLog(@"Reconnected session: %@", sessionId);
     }];
 } else {
     [client createSession:jwt callback:^(NSError * _Nullable error, NSString * _Nullable sessionId) {
         if (error != nil || sessionId == nil) {
             NSLog(@"Failed to create session: %@", error);
             return;
         }

         [store saveSessionId:sessionId];
         NSLog(@"Session created: %@", sessionId);
     }];
 }