# Access Token Lifecycle

> \[!CAUTION]
>
> Programmable Chat has been deprecated and is no longer supported. Instead, we'll be focusing on the next generation of chat: Twilio Conversations. Find out more about the [EOL process here](https://www.twilio.com/en-us/changelog/programmable-chat-end-of-life-notice).
>
> If you're starting a new project, please visit the [Conversations Docs](/docs/conversations) to begin. If you've already built on Programmable Chat, please visit our [Migration Guide](/docs/conversations/migrating-chat-conversations) to learn about how to switch.

Twilio access tokens have a lifetime determined by your server when you generate the token, with a minimum of 3 minutes and a maximum of 24 hours. When an access token in your application expires, you must update the token with your client(s) to continue using Twilio's services.

## Client Initialization \[#initialization]

After the initial start of your application on iOS, Android or in the browser, your access token needs to be passed to the instance of Programmable Chat SDK. You can then either register a lambda or implement a listener method to handle the token refresh events depending on your platform.

Initializing Programmable Chat SDK

```js
const Chat = require('twilio-chat');

// Make a secure request to your backend to retrieve an access token.
// Use an authentication mechanism to prevent token exposure to 3rd parties.

const accessToken = '<your accessToken>';

Chat.Client.create(accessToken)
  .then(client => {
    // Use Programmable Chat client
  });
```

```java
import com.twilio.chat.ChatClient;
import com.twilio.chat.ChatClientListener;

ChatClient.Properties.Builder builder = new ChatClient.Properties.Builder();
ChatClient.Properties properties = builder.createProperties();
// See below for client event listener implementation
ChatClientListener listener = new Listener();

// Make a secure request to your backend to retrieve an access token.
// Use an authentication mechanism to prevent token exposure to 3rd parties.

String accessToken = "<your token here>";

ChatClient.create(getApplicationContext(), accessToken, properties, listener);
```

```objective-c
#import <TwilioChatClient/TwilioChatClient.h>

// Make a secure request to your backend to retrieve an access token.
// Use an authentication mechanism to prevent token exposure to 3rd parties.

NSString *accessToken = @"<your token here>";

[TwilioChatClient chatClientWithToken:accessToken
  properties:properties delegate:delegate completion:(TCHResult *result, TwilioChatClient *client) {
    if (![result isSuccessful]) {
      // warn the user the initialization didn't succeed
    }
  }];
```

```swift
import TwilioChatClient

// Make a secure request to your backend to retrieve an access token.
// Use an authentication mechanism to prevent token exposure to 3rd parties.

let accessToken = "<your token here>"

TwilioChatClient.chatClient(withToken: accessToken,
  properties: nil, delegate: self) {
    (result, chatClient) in
    if (!result.isSuccessful()) {
      // warn the user the initialization didn't succeed
    }
  }
```

## Token Update \[#update]

Programmable Chat SDK also offers a method to provide updated tokens over the lifetime of the client. For uninterrupted access to Twilio's services, you should provide renewed tokens to your Twilio client SDKs before expiration with the client's `updateToken` method.

Updating Chat Access Token

```js
chatClient.updateToken(accessToken);
```

```java
chatClient.updateToken(accessToken, new StatusListener {
  @Override public void onSuccess() {
    System.out.println("Token updated successfully");
  }
});
```

```objective-c
[chatClient updateToken:accessToken completion:^(TCHResult *result) {
  if (![result isSuccessful]) {
    // warn the user the update didn't succeed
  }
}];
```

```swift
chatClient.updateToken(accessToken) { (result) in
  if (!result.isSuccessful()) {
    // warn the user the update didn't succeed
  }
}
```

> \[!NOTE]
>
> If you are using multiple Twilio client SDKs in your project at the same time, and share a common access token with multiple service grants (e.g. Chat, Sync, Voice, Video) you should instead implement external token lifecycle management using AccessManager component.

## Token Renewal Events \[#renewal]

Programmable Chat SDK has a built-in access token lifecycle management to support this renewal process.

When an access token is in its final three minutes, the `token about to expire` event is triggered. If the token was not updated before its expiry, a `token expired` event will trigger. You should use one of these methods to fetch a new access token and set it on the Chat SDK instance. The client will then validate the update you provided and refresh the token for all internal components to use it for subsequent operations. Additionally, a token error event may surface if there is a problem with the token provided to SDK.

The implementation of this mechanism varies by platform and is described in detail below.

Note: If the provided token is valid with less than three minutes remaining until expiry, the `token about to expire` event will trigger immediately. If the supplied token is already expired, the `error` event will trigger and the client will close connection.

Responding to Token Renewal Events

```js
chatClient.on('tokenAboutToExpire', function() {
  // Implement fetchToken() to make a secure request to your backend to retrieve a refreshed access token.
  // Use an authentication mechanism to prevent token exposure to 3rd parties.
  fetchToken(function(updatedToken) {
    chatClient.updateToken(updatedToken);
  });
});
```

```java
public class Listener implements ChatClientListener {
  @Override public void onTokenAboutToExpire()
  {
    // Implement fetchToken() to make a secure request to your backend to retrieve a refreshed access token.
    // Use an authentication mechanism to prevent token exposure to 3rd parties.
    fetchToken((String updatedToken) -> {
      chatClient.updateToken(updatedToken, new StatusListener {
        @Override public void onSuccess() {
          System.out.println("Token renewed successfully");
        }
      });
    });
  }
}
```

```objective-c
- (void)chatClientTokenWillExpire:(TwilioChatClient *)chatClient {
  // Implement fetchToken() to make a secure request to your backend to retrieve a refreshed access token.
  // Use an authentication mechanism to prevent token exposure to 3rd parties.
  [self fetchToken:completion:^(NSString *updatedToken) {
    [chatClient updateToken:updatedToken
      completion:^(TCHResult * _Nonnull result) {
        if (!result.isSuccessful) {
          NSLog(@"Error updating token: %@", result.error);
        }
      }];
  }]
}
```

```swift
func chatClientTokenWillExpire(_ chatClient: TwilioChatClient) {
  // Implement fetchToken() to make a secure request to your backend to retrieve a refreshed access token.
  // Use an authentication mechanism to prevent token exposure to 3rd parties.
  fetchToken(completion: { (updatedToken) -> (Void) in
    if let updatedToken = updatedToken {
      chatClient.updateToken(updatedToken, completion: { (result) in
        if !result.isSuccessful() {
          print("Error updating token: \(String(describing: result.error?.description))")
            return
          }
      })
    }
  })
}
```

Regardless of the way you choose to update your client's access token, renewing the token prior to expiry is important for ensuring that your chat application is a great user experience.

**Next:** [Best practices using Chat SDK](/docs/chat/best-practices-sdk-clients)
