Session Setup

A session is an authenticated connection between your client app and the Vonage API. Your backend issues a JWT, and the Client SDK uses that JWT in createSession().

Session Model

  • Vonage API controls session lifecycle.
  • The Client SDK does not mint JWTs and does not manage token issuance.
  • Your backend remains the source of truth for identity and access policy.

Authentication Flow

Backend JWT Minting

The example below illustrates the required JWT structure. Your actual implementation will vary based on your backend language and framework.

JWTs must be generated on your server. The exact implementation is app-specific.

const privateKeyPem =
  '-----BEGIN PRIVATE KEY-----\n...\n-----END PRIVATE KEY-----';

const payload: GuideJwtPayload = {
  application_id: applicationId,
  sub: userName,
  acl: {
    paths: {
      '/*/users/**': {},
      '/*/conversations/**': {},
      '/*/sessions/**': {},
      '/*/devices/**': {},
      '/*/image/**': {},
      '/*/media/**': {},
      '/*/applications/**': {}
    }
  },
  exp: Math.floor(Date.now() / 1000) + 60 * 60
};

const jwt = signJwt(payload, privateKeyPem);
console.log(jwt);

Create a Session

client.setConfig({ region: ConfigRegion.EU });

try {
  const sessionId = await client.createSession(jwt);
  console.log(`Session created: ${sessionId}`);
} catch (error) {
  console.error('Failed to create session', error);
}
 val client = VoiceClient(ctx)

 val config = VGClientConfig(VGConfigRegion.EU)
 client.setConfig(config)

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

     println("Session created: $sessionId")
 }
 VoiceClient client = VoiceClient.createClient(ctx);

 VGClientConfig config = new VGClientConfig(ClientConfigRegion.EU);
 client.setConfig(config);

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

     System.out.println("Session created: " + sessionId);
     return null;
 });
 let config = VGClientConfig(region: .EU)
 client.setConfig(config)

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

     print("Session created: \(sessionId)")
 }
 VGClientConfig *config = [[VGClientConfig alloc] initWithRegion:VGConfigRegionEU];
 [client setConfig:config];

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

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

Session Lifetime

A session lives for as long as the JWT used in createSession() is valid. The session lifetime is set by the JWT's exp claim — your backend controls how long that is (minimum 30 seconds, maximum 24 hours, default 15 minutes if not set explicitly). The SDK does not impose any session TTL of its own.

To extend a session before its JWT expires, call refreshSession(jwt) with a fresh JWT. Many customers issue short-lived (15-minute) JWTs and refresh every ~10 minutes from their backend.

Reconnecting After a Transient Disconnect

If the WebSocket disconnects for any reason (network loss, app suspended, tab closed), the backend marks the session as disconnected but keeps it alive for approximately 15 minutes so the client can reattach. During that window:

  • Call refreshSession(jwt) if you still have the SDK state (SDK tracks the session ID internally).
  • Or call createSession(jwt, existingSessionId) if you've lost SDK state (e.g. app restart) but persisted the session ID yourself.

In both cases, the backend replays any events that arrived while you were disconnected (incoming call invites, etc.), so a customer can still answer a call that came in during the reconnection window.

After ~15 minutes without a reconnect, the session is deleted and you must call createSession(jwt) with a fresh JWT to start a new one.

See Vonage Client SDK Sessions for more details on session lifecycle.

Session TTL (15 minutes) and JWT expiry (exp claim) are independent. A JWT can be valid for longer than 15 minutes, but the session still expires after 15 minutes unless refreshed. Always refresh or recreate the session before the TTL elapses.

Handling Errors

createSession can fail for several reasons. Always handle the error callback:

try {
  const sessionId = await client.createSession(token);
  console.log("Session created:", sessionId);
} catch (error) {
  // error is a VonageError with type and message
  console.error("Session creation failed:", error.type, error.message);
}
client.createSession(token) { error, sessionId ->
    if (error != null) {
        when {
            error.message?.contains("token") == true ->
                // Invalid or expired JWT — request a new one from your backend
                println("Token error: $error")
            error.message?.contains("already active") == true ->
                // Session already exists — call deleteSession first if you need a fresh session
                println("Session already active")
            else ->
                println("Session creation failed: $error")
        }
    } else {
        println("Session created: $sessionId")
    }
}
client.createSession(token) { error, sessionId in
    if let error = error {
        print("Session creation failed: \(error.localizedDescription)")
        return
    }
    print("Session created: \(sessionId ?? "")")
}

For a full list of possible error types, see Errors.