Chat Docs Introduction

Last Edit: Feb 02 2020

Before reviewing the Chat API docs, we recommend having a look at the tutorials and sample apps.

react chat

React

react native chat

React Native

iOS/Swift chat

iOS / Swift

Android chat

Java/Kotlin

The interactive API tour is the fastest way to learn how Stream’s Chat API works. Be sure to check that out if you haven’t done so already.

CHAT API TOUR

Getting Started

This guide quickly brings you up to speed on Stream’s Chat API. The API is flexible and allows you to build any type of chat or messaging.

You're currently not logged in. Create an account to automatically add your API key and secret to these code examples.

The Stream Chat API client is available as an npm package and also available via yarn.


# using npm
npm install stream-chat

# using yarn
yarn add stream-chat
                    

After installing the package, import the StreamChat module into your project, and you're ready to go:


import { StreamChat } from 'stream-chat';

// or

const StreamChat = require('stream-chat').StreamChat;
                    

The Stream Chat API client is available as a library using Jitpack package repository

Add repository into root build.gradle


allprojects {
  repositories {
    ...
    maven { url 'https://jitpack.io' }
  }
}
                    

Add library dependency into app build.gradle


android {
    ...
    dataBinding {
        enabled = true
    }
  
    compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_8
        targetCompatibility JavaVersion.VERSION_1_8
    }
}

dependencies {
    implementation 'com.github.getstream:stream-chat-android:3.4.1'
}
                    

The Stream Chat API client is available as a library using Jitpack package repository

Add repository into root build.gradle


allprojects {
  repositories {
    ...
    maven { url 'https://jitpack.io' }
  }
}
                    

Add library dependency into app build.gradle


android {
    ...
    dataBinding {
        enabled = true
    }
  
    compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_8
        targetCompatibility JavaVersion.VERSION_1_8
    }
}

dependencies {
    implementation 'com.github.getstream:stream-chat-android:3.4.1'
                    

You can add StreamChat to your Xcode project using CocoaPods or with Carthage.

CocoaPods

Add this entry in your Podfile and then run pod install


pod 'StreamChat'
                    

Carthage

To integrate Stream Chat into your Xcode project using Carthage, specify it in your Cartfile:


github "GetStream/stream-chat-swift"
                    

Then run carthage update --platform iOS --new-resolver and follow these steps:

  • Open your Xcode project

  • Select the project in the Navigator

  • Select your app target

  • Open General panel

  • Click the + button in the Linked Frameworks and Libraries section

  • Click the Add Other... and add StreamChatCore.framework in <Path to your Project>/Carthage/Build/iOS/

  • Add StreamChat.framework

  • Open Build Phases panel

  • Click the + button and select New Run Script Phase

  • Set the content to: /usr/local/bin/carthage copy-frameworks

  • Add to Input Files

    • $(SRCROOT)/Carthage/Build/iOS/StreamChatCore.framework

    • $(SRCROOT)/Carthage/Build/iOS/StreamChat.framework

  • Add to Output Files

    • $(BUILT_PRODUCTS_DIR)/$(FRAMEWORKS_FOLDER_PATH)/StreamChatCore.framework

    • $(BUILT_PRODUCTS_DIR)/$(FRAMEWORKS_FOLDER_PATH)/StreamChat.framework

Chat Client

Let's get started by initializing the client and setting the current user:


const client = new StreamChat("YOUR_API_KEY");
await client.setUser(
    {
        id: 'jlahey',
        name: 'Jim Lahey',
        image: 'https://i.imgur.com/fR9Jz14.png',
    },
    "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoiamxhaGV5In0.OkDbpbujWJ-XIVHaf00Dnqt3v8Yp_nQ6CGzm-Z4QUVc",
);
                    

// typically done in your BaseApplication class
StreamChat.init("qk4nn7rpcn75", new ApiClientOptions.Builder().Timeout(6666).build(), getApplicationContext());

// set the user to establish the websocket connection
// usually done when you open the chat interface
Client client = StreamChat.getInstance(getApplication());

// this hashmap allows you to add any custom fields you want to store about your user
// the UI components will pick up name and image by default
HashMap<string, object=""> extraData = new HashMap&lt;&gt;();
extraData.put("name", "Bender");
extraData.put("image", "https://bit.ly/321RmWb");
User user = new User(USER_ID, extraData);
client.setUser(user, "FEED_USER_TOKEN", new ClientConnectionCallback() {
    @Override
    public void onSuccess(User user) {
        Log.i(TAG, String.format("Connection established for user %s", user.getName()));
    }

    @Override
    public void onError(String errMsg, int errCode) {
        Log.e(TAG, String.format("Failed to establish websocket connection. Code %d message %s", errCode, errMsg));
    }
});</string,>
                    

// In your AppDelegate:
// Import Stream chat core framework.
import StreamChatCore

// Setup the Stream Chat Client with your API key 
// in func application(_ application:didFinishLaunchingWithOptions:).
Client.config = .init(apiKey: "&lt;#API_KEY#&gt;")

// Create a user, when he/she was logged in.
let user = User(id: "bender", name: "Bender", avatarURL: URL(string: "https://bit.ly/321RmWb")!)

// Setup the current user and token.
Client.shared.set(user: user, token: token)
                    

// typically done in your BaseApplication class
StreamChat.init(
    "qk4nn7rpcn75", ApiClientOptions.Builder().Timeout(6666).build(),
    applicationContext
)

// set the user to establish the websocket connection
// usually done when you open the chat interface
val client = StreamChat.getInstance(application)

// this hashmap allows you to add any custom fields you want to store about your user
// the UI components will pick up name and image by default
val extraData = HashMap<string, any="">()
extraData.put("name", "Bender")
extraData.put("image", "https://bit.ly/321RmWb")
val user = User("USER_ID", extraData)
client.setUser(user, "FEED_USER_TOKEN", object : ClientConnectionCallback {
    override fun onSuccess(user: User) {
        Log.i(TAG,String.format("Connection established for user %s", user.name) )
    }

    override fun onError(errMsg: String, errCode: Int) {
        Log.e(TAG,
            String.format("Failed to establish websocket connection. Code %d message %s",
                errCode,
                errMsg
            )
        )
    }
})</string,>
                    

The above snippet is for an in-browser or mobile integration. Server-side API calls are a little different, but this is covered in detail later in the documentation.

Channels

Let’s continue by initializing your first channel. A channel contains messages, a list of people that are watching the channel, and optionally a list of members (for private conversations). The example below shows how to set up a channel to support chat for a group conversation:


const channel = client.channel('messaging', 'travel', {
    name: 'Awesome channel about traveling',
});

// fetch the channel state, subscribe to future updates
const state = await channel.watch();
                    

// initialize a channel object with an extra data hashmap
HashMap<string, object=""> extraData = new HashMap&lt;&gt;();
extraData.put("name", "Talking about life");

Channel channel = client.channel(channelType, channelID, extraData);

// watching a channel's state
ChannelQueryRequest request = new ChannelQueryRequest().
          withMessages(Constant.DEFAULT_LIMIT).withWatch();

// note how the withWatch() argument ensures that we are watching the channel for any changes/new messages
channel.query(
  request,
  new QueryChannelCallback() {
      @Override
      public void onSuccess(ChannelState response) {          
      }

      @Override
      public void onError(String errMsg, int errCode) {          
      }
  }
);</string,>
                    

// Create an extra data for a channel.
struct ChannelInfo: Codable {
    let info: String
}

// Register once your extra data types for the decoding.
ExtraData.decodableTypes = [.channel(ChannelInfo.self)]

let info = ChannelInfo(info: "Awesome channel about traveling")
let channel = Channel(type: .messaging, id: "travel", name: "Travel", extraData: info)
                    

// initialize a channel object with an extra data hashmap
val extraData = HashMap<string, any="">()
extraData.put("name", "Talking about life")

val channel = client.channel(channelType, channelID, extraData)

// watching a channel's state
val request = ChannelQueryRequest().withMessages(Constant.DEFAULT_LIMIT).withWatch()

// note how the withWatch() argument ensures that we are watching the channel for any changes/new messages
channel.query(
    request,
    object : QueryChannelCallback {
        override fun onSuccess(response: ChannelState) {
        }

        override fun onError(errMsg: String, errCode: Int) {
        }
    }
)</string,>
                    

The first two arguments are the Channel Type and the Channel ID (messaging and travel in this case). The Channel ID is optional; if you leave it out, the ID is determined based on the list of members. The channel type controls the settings we’re using for this channel.

There are 5 default types of channels:

  • livestream
  • messaging
  • team
  • gaming
  • commerce

These five options above provide you with the most sensible defaults for those use cases. You can also define custom channel types if Stream Chat defaults don’t work for your use-case.

The third argument is an object containing the channel data. You can add as many custom fields as you would like as long as the total size of the object is less than 5KB.

Messages

Now that we have the channel set up, let's send our first chat message:


const text = 'I’m mowing the air Rand, I’m mowing the air.';

const response = await channel.sendMessage({
    text,
    customField: '123',
});
                    

// prepare the message
Message message = new Message();
message.setText("hello world");

// send the message to the channel
channel.sendMessage(message,
  new MessageCallback() {
      @Override
      public void onSuccess(MessageResponse response) {        
      }

      @Override
      public void onError(String errMsg, int errCode) {
      }
  });
                    

// The Stream Chat based on RxSwift framework.
import RxSwift

// Create an instance variable for the disposeBag in your view controller.
// It needs for the memory management of RxSwift subscriptions.
let disposeBag = DisposeBag()

// Create and send a message.
let message = Message(text: "Hello world!")

channel.send(message: message)
    .subscribe(onNext: { messageResponse in
        print(messageResponse)
    })
    .disposed(by: disposeBag)
                    

// prepare the message
val message = Message()
message.setText("hello world")

// send the message to the channel
channel.sendMessage(message, object : MessageCallback {
    override fun onSuccess(response: MessageResponse) {
        println(response)
    }

    override fun onError(errMsg: String, errCode: Int) {
        println("$errMsg: $errCode")
    }
}
                    

Similar to users and channels, the sendMessage method allows you to add custom fields. When you send a message to a channel, Stream Chat automatically broadcasts to all the people that are watching this channel and updates in real-time.

Events

This is how you can listen to events on the clients-side:


channel.on('message.new', event => {
    console.log('received a new message', event.message.text);
    console.log(`Now have ${channel.state.messages.length} stored in local state`);
});
                    

Integer channelSubscriptionId = channel.addEventHandler(new ChatChannelEventHandler() {
  @Override
  public void onMessageNew(Event event) {
      event.getMessage();
  }
}
// channel.removeEventHandler(channelSubscriptionId) to remove it
                    

channel.onEvent(.messageNew)
    .subscribe(onNext: { event in
        print(event)
    })
    .disposed(by: disposeBag)
                    

val channelSubscriptionId = client.addEventHandler(object : ChatChannelEventHandler() {
    override fun onMessageNew(event: Event) {
        println(event)
    }
})
// channel.removeEventHandler(channelSubscriptionId) to remove
                    
You can receive the event and access the full channel state via channel.state.

Conclusion

Now that you understand the building blocks of a fully functional chat integration, let’s move on to the next sections of the documentation, where we dive deeper into details on each API endpoint.