# Getstream > Build **low-latency** Vision AI applications using our new open-source --- # Stream.io Documentation # Source: https://getstream.io/activity-feeds/docs/ Build **low-latency** Vision AI applications using our new open-source **Vision AI SDK**. [⭐️ on GitHub ->](https://github.com/GetStream/vision- agents) [![Stream logo](/stream-dark.png)](/) * Products * Solutions * Developers * Company * Pricing * Contact * [Log in](https://beta.dashboard.getstream.io/login/) Back * * Products * [Chat MessagingBuild real-time chat messaging in less time](/chat/) * [Video & AudioReliable in-app video calling and livestreaming](/video/) * [Activity FeedsGrow engagement with enterprise-ready feeds](/activity-feeds/) * [AI ModerationFind, monitor, and resolve harmful content easily](/moderation/) * Advanced Add-Ons and Integrations * [AI ChatBot IntegrationIntegrate AI into your chat messaging app](/chat/solutions/ai-integration/) * [![/vision-agents.svg](/vision-agents.svg)Video AI AgentsBuild real-time low-latency voice and video AI applications with Vision Agents](https://github.com/GetStream/vision-agents) * [Voice AgentsDeploy voice agents with OpenAI](/video/voice-agents/) * * [Solutions ->](/chat/solutions/) * [Collaboration](/chat/solutions/collaboration/) * [Dating](/chat/solutions/dating/) * [Education](/chat/solutions/ed-tech/) * [Financial](/chat/solutions/fintech/) * [Gaming](/chat/solutions/gaming/) * [Healthcare](/chat/solutions/healthcare/) * [Live Shopping](/video/live-shopping/) * [Marketplace](/chat/solutions/marketplaces/) * [On-Demand](/chat/solutions/delivery/) * [Social](/chat/solutions/social/) * [Sports](/chat/solutions/sports/) * [Virtual Events](/chat/solutions/live-events/) * Resources * [Case StudiesWhy Stream is loved by its customers](/blog/topic/case-studies-2/) * [EnterpriseStream's industry-leading 99.999% uptime SLA](/enterprise/) * * Documentation * [Chat MessagingEverything developers need to build with Stream](/chat/docs/) * [Video & AudioYour guide to a seamless integration](/video/docs/) * [Activity FeedsStep by step guidance to streamline development](/activity-feeds/docs/) * [ModerationFind, monitor, and resolve harmful content easily](/moderation/docs) * Resources * [Stack OverflowFollow us on Stack Overflow](https://stackoverflow.com/questions/tagged/getstream-io) * [YoutubeFollow us on YouTube](https://www.youtube.com/channel/UC2xOn0xQj1HIpHJpOy5tvpA/featured) * [GitHubFollow us on GitHub](https://github.com/GetStream/) * * Company * [About UsLearn more about our mission and team](/team/) * [CareersExplore open opportunities](/team/#jobs) * [BlogRead tutorials, announcements, and more](/blog/) * [Case StudiesWhy Stream is loved by its customers](/blog/topic/case-studies-2/) * [EnterpriseStream's industry-leading 99.999% uptime SLA](/enterprise/) * [Press & AwardsStay Updated on Stream News](/press/) * * Pricing * [Chat Messaging](/chat/pricing/) * [Video & Audio](/video/pricing/) * [Activity Feeds](/activity-feeds/pricing/) * [Moderation](/moderation/pricing/) * * * [Contact Sales](/contact/) * [Contact Support](/contact/support/) * [Submit Bug Report](/contact/bug-report/) [Start Coding Free](/try-for-free/) * [Activity Feeds](/activity-feeds/) * [Docs](/activity-feeds/docs/) * [Docs](/activity-feeds/docs/) * Solutions * SDKs * [UI Kits](/activity-feeds/ui-kit/) * [Try The API](/activity-feeds/tour/) Back * * * * [Notification Feeds](/activity-feeds/notification-feeds/) * [Personalization](/activity-feeds/personalization/) * * [SDKs ->](/activity-feeds/sdk/) * [![The logo of React](https://getstream.cdn.prismic.io/getstream/Ze7pQEmNsf2sHfou_react-original.svg?auto=compress,format)React](/activity-feeds/sdk/react/) * [![The logo of Swift](https://getstream.cdn.prismic.io/getstream/Ze7qA0mNsf2sHfpX_swift-original.svg?auto=compress,format)iOS](/activity-feeds/sdk/ios/) * [![The logo of Android](https://getstream.cdn.prismic.io/getstream/Ze7m8kmNsf2sHfnz_android-plain.svg?auto=compress,format)Android](/activity-feeds/sdk/android/) * [![The logo of Flutter](https://getstream.cdn.prismic.io/getstream/Ze7nxEmNsf2sHfoE_flutter-original.svg?auto=compress,format)Flutter](/activity-feeds/sdk/flutter/) * [![The logo of React Native](https://getstream.cdn.prismic.io/getstream/Ze7pQEmNsf2sHfou_react-original.svg?auto=compress,format)React Native](/activity-feeds/sdk/react-native/) Documentation # Activity Feeds Docs Welcome to the docs for Stream's activity feed API. Note that most of the feed integration is typically done using backend SDKs. If you have questions, or you see something that can be improved, every section of the docs includes a “!?” icon to get in touch. ![example of feeds sdk](https://images.prismic.io/getstream/Zlfj7qWtHYXtT6w5_hero-feeds- docs.png?auto=format,compress) Client Side (v3) ![The logo of JavaScript](https://getstream.cdn.prismic.io/getstream/Ze7olUmNsf2sHfoT_javascript- original.svg?auto=compress,format) Javascript * [Documentation ->](https://getstream.io/activity-feeds/docs/javascript/) ![The logo of Swift](https://getstream.cdn.prismic.io/getstream/Ze7qA0mNsf2sHfpX_swift- original.svg?auto=compress,format) iOS * [Documentation ->](https://getstream.io/activity-feeds/docs/ios/) ![The logo of Android](https://getstream.cdn.prismic.io/getstream/Ze7m8kmNsf2sHfnz_android- plain.svg?auto=compress,format) Android * [Documentation ->](https://getstream.io/activity-feeds/docs/android/) ![The logo of React](https://getstream.cdn.prismic.io/getstream/Ze7pQEmNsf2sHfou_react- original.svg?auto=compress,format) React * [Documentation ->](https://getstream.io/activity-feeds/docs/react/) ![The logo of React Native](https://getstream.cdn.prismic.io/getstream/Ze7pQEmNsf2sHfou_react- original.svg?auto=compress,format) React Native * [Documentation ->](https://getstream.io/activity-feeds/docs/react-native/) ![The logo of Flutter](https://getstream.cdn.prismic.io/getstream/Ze7nxEmNsf2sHfoE_flutter- original.svg?auto=compress,format) Flutter * [Documentation ->](https://getstream.io/activity-feeds/docs/flutter/) Server Side (v3) ![The logo of Node](https://getstream.cdn.prismic.io/getstream/Ze7o90mNsf2sHfoa_nodejs- original.svg?auto=compress,format) Node * [Documentation ->](https://getstream.io/activity-feeds/docs/node/) ![The logo of Go](https://getstream.cdn.prismic.io/getstream/Ze7n_EmNsf2sHfoJ_go-original- wordmark.svg?auto=compress,format) Go * [Documentation ->](https://getstream.io/activity-feeds/docs/go-golang/) ![The logo of .NET](https://getstream.cdn.prismic.io/getstream/Ze7nnEmNsf2sHfn__dot-net- original.svg?auto=compress,format) .NET [Documentation ->](https://getstream.io/activity-feeds/docs/dotnet-csharp/) ! PHP [Documentation ->](https://getstream.io/activity-feeds/docs/php/) ![The logo of Java](https://getstream.cdn.prismic.io/getstream/Ze7oJkmNsf2sHfoP_java- original.svg?auto=compress,format) Java [Documentation ->](https://getstream.io/activity-feeds/docs/java/) ![The logo of Python](https://getstream.cdn.prismic.io/getstream/Ze7pHkmNsf2sHfol_python- original.svg?auto=compress,format) Python [Documentation ->](https://getstream.io/activity-feeds/docs/python/) Client Side (v2) ![The logo of JavaScript](https://getstream.cdn.prismic.io/getstream/Ze7olUmNsf2sHfoT_javascript- original.svg?auto=compress,format) Javascript * [Documentation ->](https://getstream.io/activity-feeds/docs/javascript/v2/) Server Side (v2) ![The logo of Node](https://getstream.cdn.prismic.io/getstream/Ze7o90mNsf2sHfoa_nodejs- original.svg?auto=compress,format) NodeJS * [Documentation ->](https://getstream.io/activity-feeds/docs/node/v2/) ![The logo of Python](https://getstream.cdn.prismic.io/getstream/Ze7pHkmNsf2sHfol_python- original.svg?auto=compress,format) Python * [Documentation ->](https://getstream.io/activity-feeds/docs/python/v2/) ![The logo of Ruby](https://getstream.cdn.prismic.io/getstream/Ze7pxUmNsf2sHfpM_ruby- original.svg?auto=compress,format) Ruby * [Documentation ->](https://getstream.io/activity-feeds/docs/ruby/v2/) ! PHP * [Documentation ->](https://getstream.io/activity-feeds/docs/php/v2/) ![The logo of Java](https://getstream.cdn.prismic.io/getstream/Ze7oJkmNsf2sHfoP_java- original.svg?auto=compress,format) Java * [Documentation ->](https://getstream.io/activity-feeds/docs/java/v2/) ![The logo of .NET](https://getstream.cdn.prismic.io/getstream/Ze7nnEmNsf2sHfn__dot-net- original.svg?auto=compress,format) .NET * [Documentation ->](https://getstream.io/activity-feeds/docs/dotnet-csharp/v2/) ![The logo of Go](https://getstream.cdn.prismic.io/getstream/Ze7n_EmNsf2sHfoJ_go-original- wordmark.svg?auto=compress,format) Go * [Documentation ->](https://getstream.io/activity-feeds/docs/go-golang/v2/) ! REST API * [Documentation ->](/docs_rest/) ## Start coding If you're interested in a custom plan or have any questions, please contact us. [Start Coding >_](/try-for-free/)[Contact Sales ->](/contact/) Products * [Chat Messaging](/chat/) * [Video & Audio](/video/) * [Activity Feeds](/activity-feeds/) * [AI Moderation](/moderation/) * Comparison * [Stream vs Sendbird](https://getstream.io/chat/stream-vs-sendbird/) * [Sendbird Alternatives](/blog/sendbird-competitor-alternatives/) * [Pricing Breakdown](/blog/what-i-learned-researching-chat-api-pricing/) * [Stream vs Vonage](/blog/vonage-comparison/) * [Twilio Alternatives](/blog/twilio-video-alternatives/) * [Twilio migration](/blog/migrate-twilio-programmable-video/) Developers * [Chat Messaging Docs](/chat/docs/) * [Video & Audio Docs](/video/docs/) * [Activity Feeds Docs](/activity-feeds/docs/?language=javascript) * [AI Moderation Docs](/moderation/docs/) * Resources * [Stack Overflow](https://stackoverflow.com/questions/tagged/getstream-io) * [YouTube](https://www.youtube.com/channel/UC2xOn0xQj1HIpHJpOy5tvpA/featured) * [GitHub](https://github.com/GetStream/) * Featured tutorials * [Build a Twitter Clone](/resources/projects/twitter-clone/) * [WebRTC Tutorial Series](/resources/projects/webrtc/) Company[Hiring](/team/#jobs) * [About Us](/team/) * [Careers](/team/#jobs) * [Blog](/blog/) * [Case Studies](/blog/topic/case-studies-2/) * [Enterprise](/enterprise/) * [Press & Awards](/press/) * [Glossary](/glossary/) * [Partners](/partners/) * [Trust Center](https://trust.getstream.io/) Contact Us * [Sales](/contact/) * [Support](/contact/support/) * [Bug Report](/contact/bug-report/) [![Stream logo](/stream-light.png)](/) Stream is proudly designed, built and continually enhanced in [Boulder, CO](/team/), and [Amsterdam, NL](/team/); with a global remote team. [System Status](https://status.getstream.io/) © Stream.io, Inc. All Rights Reserved. * [Terms](/legal/) * [Privacy](/legal/privacy/) * [Security](/security/) * * * * --- # Stream.io Documentation # Source: https://getstream.io/chat/docs/file_uploads/ * [Chat Messaging](/chat/) / * [Docs](/chat/docs/) / * [React](/chat/docs/react/) / * [Image and File Uploads](/chat/docs/react/file_uploads/) # Image and File Uploads Stream Chat allows you to upload images, videos, and other files to the Stream CDN or your own CDN. Uploaded files can be used as message attachments, user avatars, or channel images. Stream’s UI SDKs (React, React Native, Flutter, SwiftUI, Jetpack Compose, etc.) handle file uploads automatically through their message composer components. The upload process, progress tracking, and attachment handling are built into these components. Use the methods described on this page only if you need custom upload behavior or are building a custom UI. ## Uploading Files to a Channel Files uploaded to a channel can be attached to messages. You can either upload a file first and then attach it to a message, or let the SDK handle the upload when sending a message with attachments. JavaScriptKotlinSwiftDartJavaNode.jsPythonPHPRubyC#Unity // Upload an image to the channel const response = await channel.sendImage(file); const imageUrl = response.file; // Send a message with the uploaded image await channel.sendMessage({ text: "Check out this image", attachments: [ { type: "image", asset_url: imageUrl, thumb_url: imageUrl, }, ], }); val channelClient = client.channel("messaging", "general") // Upload an image channelClient.sendImage(imageFile).enqueue { result -> if (result is Result.Success) { val imageUrl = result.value.file val attachment = Attachment( type = "image", imageUrl = imageUrl, ) val message = Message(attachments = mutableListOf(attachment)) channelClient.sendMessage(message).enqueue { /* ... */ } } } // Upload a file with progress tracking channelClient.sendFile( file, object : ProgressCallback { override fun onSuccess(url: String?) { // File uploaded successfully } override fun onError(error: Error) { // Handle error } override fun onProgress(bytesUploaded: Long, totalBytes: Long) { // Update progress UI } } ).enqueue() let channelId = ChannelId(type: .messaging, id: "general") let channelController = chatClient.channelController(for: channelId) // Option 1: Send message with local attachment (SDK handles upload) let imageAttachment = try AnyAttachmentPayload( localFileURL: localImageUrl, attachmentType: .image ) channelController.createNewMessage( text: "Hello", attachments: [imageAttachment] ) // Option 2: Upload first, then attach to message channelController.uploadAttachment( localFileURL: localFileUrl, type: .image, progress: { value in // Track upload progress (0.0 to 1.0) }, completion: { result in switch result { case .success(let uploadedFile): let payload = ImageAttachmentPayload( title: nil, imageRemoteURL: uploadedFile.url ) let attachment = AnyAttachmentPayload(payload: payload) channelController.createNewMessage( text: "Hello", attachments: [attachment] ) case .failure(let error): // Handle upload error } } ) // Option 1: Send message with local attachments (SDK handles upload) final message = Message(text: "Hello", attachments: [ Attachment( type: "image", file: AttachmentFile(path: "imagePath/imageName.png"), ), ]); await channel.sendMessage(message); // Option 2: Upload first, then attach to message await client.sendImage( image, channelId, channelType, onSendProgress: (sent, total) { // Update progress UI }, ).then((response) { final imageUrl = response.file; final message = Message(attachments: [ Attachment(type: "image", imageUrl: imageUrl), ]); client.sendMessage(message, channelId, channelType); }); ChannelClient channelClient = client.channel("messaging", "general"); // Upload an image channelClient.sendImage(imageFile).enqueue(result -> { if (result.isSuccess()) { String imageUrl = result.data().getFile(); Attachment attachment = new Attachment(); attachment.setType("image"); attachment.setImageUrl(imageUrl); Message message = new Message(); message.getAttachments().add(attachment); channelClient.sendMessage(message).enqueue(res -> { /* ... */ }); } }); // Upload a file with progress tracking channelClient.sendFile(file, new ProgressCallback() { @Override public void onSuccess(@NotNull String url) { // File uploaded successfully } @Override public void onError(@NotNull ChatError error) { // Handle error } @Override public void onProgress(long bytesUploaded, long totalBytes) { // Update progress UI } }).enqueue(); // Upload multiple images in parallel const promises = [ channel.sendImage( fs.createReadStream("./image1.jpg"), "image1.jpg", "image/jpeg", { id: "user-id" }, ), channel.sendImage( fs.createReadStream("./image2.jpg"), "image2.jpg", "image/jpeg", { id: "user-id" }, ), ]; const results = await Promise.all(promises); const attachments = results.map((response) => ({ type: "image", thumb_url: response.file, asset_url: response.file, })); await channel.sendMessage({ text: "Check out these images", attachments, }); channel.send_image( "http://example.com/image.jpg", "image.jpg", {"id": "user-id"}, "image/jpeg", ) $user = ["id" => "user-id"]; $response = $channel->sendImage("http://example.com/image.jpg", "image.jpg", $user); channel.send_image( "http://example.com/image.jpg", "image.jpg", { id: "user-id" }, "image/jpeg" ) var imageBytes = File.ReadAllBytes("image.jpg"); await messageClient.UploadImageAsync(channel.Type, channel.Id, user, imageBytes, "image.jpg"); var imageBytes = File.ReadAllBytes("path/to/image.jpg"); var imageUploadResponse = await channel.UploadImageAsync(imageBytes, "image.jpg"); var imageUrl = imageUploadResponse.FileUrl; var fileBytes = File.ReadAllBytes("path/to/document.pdf"); var fileUploadResponse = await channel.UploadFileAsync(fileBytes, "document.pdf"); var fileUrl = fileUploadResponse.FileUrl; ## Uploading Standalone Files Files not tied to a specific channel can be used for user avatars, channel images, or other application needs. KotlinSwiftDart val client = ChatClient.instance() // Upload an image val uploadResult = client.uploadImage( file = imageFile, progressCallback = progressCallback, ).await() when (uploadResult) { is Result.Success -> { val imageUrl = uploadResult.value.file // Use the URL (e.g., update user avatar) client.updateUser(user.copy(image = imageUrl)).await() } is Result.Failure -> { // Handle error } } let chatClient = ChatClient.shared chatClient.uploadAttachment( localUrl: imageLocalFileUrl, progress: { progressValue in // Track upload progress (0.0 to 1.0) }, completion: { result in switch result { case .success(let uploadedFile): // Use the URL (e.g., update user avatar) chatClient.currentUserController().updateUserData( imageURL: uploadedFile.url ) case .failure(let error): // Handle upload error } } ) final client = StreamChatClient("api-key"); // Upload an image final image = AttachmentFile(path: "imagePath/image.png"); final response = await client.uploadImage( image, onUploadProgress: (count, total) { // Update progress UI }, ); final imageUrl = response.file; // Use the URL (e.g., update user avatar) final user = User(id: "user-id", image: imageUrl); await client.updateUser(user); ## Deleting Files Delete uploaded files to free storage space. Deleting a file from the CDN does not remove it from message attachments that reference it. JavaScriptKotlinSwiftDartJavaNode.jsPythonPHPRubyGoC#Unity // Delete from channel await channel.deleteFile(fileURL); await channel.deleteImage(imageURL); // Delete from channel channelClient.deleteFile("file-url").enqueue() channelClient.deleteImage("image-url").enqueue() // Delete standalone file client.deleteFile("file-url").enqueue() client.deleteImage("image-url").enqueue() // Delete from channel channelController.deleteFile(url: "remote-url") channelController.deleteImage(url: "remote-url") // Delete standalone file ChatClient.shared.deleteAttachment(remoteUrl: "remote-url") { error in // Handle deletion error } // Delete from channel await channel.deleteFile("file-url"); await channel.deleteImage("image-url"); // Delete standalone file await client.removeFile("file-url"); await client.removeImage("image-url"); // Android SDK ChannelClient channelClient = client.channel("messaging", "general"); channelClient.deleteImage("image-url").enqueue(); channelClient.deleteFile("file-url").enqueue(); // Backend SDK Message.deleteImage(channelType, channelId, url).request(); Message.deleteFile(channelType, channelId, url).request(); await channel.deleteFile(fileURL); await channel.deleteImage(imageURL); channel.delete_file(url) channel.delete_image(url) $channel->deleteFile($url); $channel->deleteImage($url); channel.delete_file(url) channel.delete_image(url) channel.DeleteFile(ctx, url) channel.DeleteImage(ctx, url) await messageClient.DeleteFileAsync("", "", url); await messageClient.DeleteImageAsync("", "", url); await channel.DeleteFileOrImageAsync("file-url"); ## File Requirements ### Images Requirement| Value Supported formats| BMP, GIF, JPEG, PNG, WebP, HEIC, HEIC-sequence, HEIF, HEIF- sequence, SVG+XML Maximum file size| 100 MB ### Other Files Requirement| Value Supported formats| All file types are allowed by default. Different clients may handle certain types differently. Maximum file size| 100 MB You can configure a more restrictive list of allowed file types for your application. ## Configuring Allowed File Types Stream allows all file extensions by default. To restrict allowed file types: * **Dashboard** : Go to Chat Overview > Upload Configuration * **API** : Use the [App Settings](/chat/docs/react/app_setting_overview/#file-uploads/) endpoint ## Access Control and Link Expiration Stream CDN URLs include a signature that validates access to the file. Only channel members can access files uploaded to that channel. Behavior| Description Access control| URLs are signed and only accessible by channel members Link expiration| URLs expire after 14 days Automatic refresh| Links are refreshed automatically when messages are retrieved (e.g., when querying a channel) Manual refresh| Call `getMessage` to retrieve fresh URLs for expired attachments To check when a link expires, examine the `Expires` query parameter in the URL (Unix timestamp). ## Image Resizing Append query parameters to Stream CDN image URLs to resize images on the fly. Parameter| Type| Values| Description w| number| | Width in pixels h| number| | Height in pixels resize| string| clip, crop, scale, fill| Resizing mode crop| string| center, top, bottom, left, right| Crop anchor position Images can only be resized if the source image has 16,800,000 pixels or fewer. An image of 4000x4000 pixels (16,000,000) would be accepted, but 4100x4100 (16,810,000) would fail. Resized images count against your storage quota. ## Using Your Own CDN All SDKs support custom CDN implementations. Implement a custom file uploader to use your own storage solution. JavaScriptKotlinSwiftDartJavaUnity messageComposer.attachmentManager.setCustomUploadFn(async (file) => { const result = await customCDN.upload(file); return { file: result.url }; }); val client = ChatClient.Builder("api-key", context) .fileUploader(MyCustomFileUploader()) .build() class CustomCDN: CDNClient { static var maxAttachmentSize: Int64 { 20 * 1024 * 1024 } func uploadAttachment( _ attachment: AnyChatMessageAttachment, progress: ((Double) -> Void)?, completion: @escaping (Result) -> Void ) { // Upload to your CDN // Call progress() to report upload progress // Call completion() with the result } } // Assign to ChatClientConfig config.customCDNClient = CustomCDN() final client = StreamChatClient( "api-key", attachmentFileUploader: MyCustomFileUploader(), ); // Android SDK ChatClient client = new ChatClient.Builder("api-key", context) .fileUploader(new MyCustomFileUploader()) .build(); // Backend SDK Message.uploadFile(channelType, channelId, userId, "text/plain") .file(new File("path/to/file")) .withFileHandler(customFileHandler) .request(); // Upload to your CDN and use the returned URL var fileUrl = await MyCustomCDN.Upload(fileBytes); await channel.SendNewMessageAsync(new StreamSendMessageRequest { Text = "Message with file attachment", Attachments = new List { new StreamAttachmentRequest { AssetUrl = fileUrl, } } }); Did you find this page helpful? It was helpful It was not helpful I have feedback Submit Thank you for the feedback. An error has occurred. Please refresh the page and try again. [PreviousMessages Overview](/chat/docs/react/send_message/)[NextThreads & Replies](/chat/docs/react/threads/) © Stream.io, Inc. All Rights Reserved. [Chat Messaging](https://getstream.io/chat/)[Video & Audio](https://getstream.io/video/)[Activity Feeds](https://getstream.io/activity- feeds/)[Moderation](https://getstream.io/moderation/) * Copy LLM prompt * [ View as markdown](https://getstream.io/chat/docs/react/file_uploads.md) * * [ Open in ChatGPT](https://chatgpt.com/?q=I'm working with the Stream Chat React SDK and would like to ask questions about this documentation page: https://getstream.io/chat/docs/react/file_uploads.md) * [ Open in Claude](https://claude.ai/new?q=I'm working with the Stream Chat React SDK and would like to ask questions about this documentation page: https://getstream.io/chat/docs/react/file_uploads.md) * [ Open in Gemini](https://gemini.google.com/app?query=I'm working with the Stream Chat React SDK and would like to ask questions about this documentation page: https://getstream.io/chat/docs/react/file_uploads.md) * [ Open in Grok](https://x.com/i/grok?text=I'm working with the Stream Chat React SDK and would like to ask questions about this documentation page: https://getstream.io/chat/docs/react/file_uploads.md) * [ Open in Perplexity](https://www.perplexity.ai/search/new?q=I'm working with the Stream Chat React SDK and would like to ask questions about this documentation page: https://getstream.io/chat/docs/react/file_uploads.md) On this page: * Uploading Files to a Channel * Uploading Standalone Files * Deleting Files * File Requirements * Images * Other Files * Configuring Allowed File Types * Access Control and Link Expiration * Image Resizing * Using Your Own CDN Is this helpful? Thank you . An error has occurred. --- # Stream.io Documentation # Source: https://getstream.io/chat/docs/ Learn how to quickly integrate rich Generative AI experiences directly into Stream Chat. [Learn More ->](/chat/solutions/ai-integration/) [![Stream logo](/stream-dark.png)](/) * Products * Solutions * Developers * Company * Pricing * Contact * [Log in](https://beta.dashboard.getstream.io/login/) Back * * Products * [Chat MessagingBuild real-time chat messaging in less time](/chat/) * [Video & AudioReliable in-app video calling and livestreaming](/video/) * [Activity FeedsGrow engagement with enterprise-ready feeds](/activity-feeds/) * [AI ModerationFind, monitor, and resolve harmful content easily](/moderation/) * Advanced Add-Ons and Integrations * [AI ChatBot IntegrationIntegrate AI into your chat messaging app](/chat/solutions/ai-integration/) * [![/vision-agents.svg](/vision-agents.svg)Video AI AgentsBuild real-time low-latency voice and video AI applications with Vision Agents](https://github.com/GetStream/vision-agents) * [Voice AgentsDeploy voice agents with OpenAI](/video/voice-agents/) * * [Solutions ->](/chat/solutions/) * [Collaboration](/chat/solutions/collaboration/) * [Dating](/chat/solutions/dating/) * [Education](/chat/solutions/ed-tech/) * [Financial](/chat/solutions/fintech/) * [Gaming](/chat/solutions/gaming/) * [Healthcare](/chat/solutions/healthcare/) * [Live Shopping](/video/live-shopping/) * [Marketplace](/chat/solutions/marketplaces/) * [On-Demand](/chat/solutions/delivery/) * [Social](/chat/solutions/social/) * [Sports](/chat/solutions/sports/) * [Virtual Events](/chat/solutions/live-events/) * Resources * [Case StudiesWhy Stream is loved by its customers](/blog/topic/case-studies-2/) * [EnterpriseStream's industry-leading 99.999% uptime SLA](/enterprise/) * * Documentation * [Chat MessagingEverything developers need to build with Stream](/chat/docs/) * [Video & AudioYour guide to a seamless integration](/video/docs/) * [Activity FeedsStep by step guidance to streamline development](/activity-feeds/docs/) * [ModerationFind, monitor, and resolve harmful content easily](/moderation/docs) * Resources * [Stack OverflowFollow us on Stack Overflow](https://stackoverflow.com/questions/tagged/getstream-io) * [YoutubeFollow us on YouTube](https://www.youtube.com/channel/UC2xOn0xQj1HIpHJpOy5tvpA/featured) * [GitHubFollow us on GitHub](https://github.com/GetStream/) * * Company * [About UsLearn more about our mission and team](/team/) * [CareersExplore open opportunities](/team/#jobs) * [BlogRead tutorials, announcements, and more](/blog/) * [Case StudiesWhy Stream is loved by its customers](/blog/topic/case-studies-2/) * [EnterpriseStream's industry-leading 99.999% uptime SLA](/enterprise/) * [Press & AwardsStay Updated on Stream News](/press/) * * Pricing * [Chat Messaging](/chat/pricing/) * [Video & Audio](/video/pricing/) * [Activity Feeds](/activity-feeds/pricing/) * [Moderation](/moderation/pricing/) * * * [Contact Sales](/contact/) * [Contact Support](/contact/support/) * [Submit Bug Report](/contact/bug-report/) [Start Coding Free](/try-for-free/) * [Chat Messaging](/chat/) * [Docs](/chat/docs/) * [Docs](/chat/docs/) * SDKs * [UI Kits](/chat/ui-kit/) * [API Tour](/chat/tour/) Back * * * [SDKs ->](/chat/sdk/) * [![The logo of React](https://getstream.cdn.prismic.io/getstream/Ze7pQEmNsf2sHfou_react-original.svg?auto=compress,format)React](/chat/sdk/react/) * [![The logo of Swift](https://getstream.cdn.prismic.io/getstream/Ze7qA0mNsf2sHfpX_swift-original.svg?auto=compress,format)iOS](/chat/sdk/ios/) * [![The logo of Android](https://getstream.cdn.prismic.io/getstream/Ze7m8kmNsf2sHfnz_android-plain.svg?auto=compress,format)Android](/chat/sdk/android/) * [![The logo of Flutter](https://getstream.cdn.prismic.io/getstream/Ze7nxEmNsf2sHfoE_flutter-original.svg?auto=compress,format)Flutter](/chat/sdk/flutter/) * [![The logo of React Native](https://getstream.cdn.prismic.io/getstream/Ze7pQEmNsf2sHfou_react-original.svg?auto=compress,format)React Native](/chat/sdk/react-native/) * [![The logo of Angular](https://getstream.cdn.prismic.io/getstream/Ze7uVEmNsf2sHfsk_angular-original.svg?auto=compress,format)Angular](/chat/sdk/angular/) * [![The logo of Unity](https://getstream.cdn.prismic.io/getstream/Ze7qNEmNsf2sHfpa_unity-original.svg?auto=compress,format)Unity](/chat/sdk/unity/) * [![The logo of Unreal](https://getstream.cdn.prismic.io/getstream/Ze7qZ0mNsf2sHfpd_unrealengine-original.svg?auto=compress,format)Unreal](/chat/sdk/unreal/) Documentation # Chat Messaging Docs Streamline app development with our feature-rich SDKs for real-time chat experiences. Easily tailor the user experience to fit your business needs — our kits offer customizable high-end UI components right out of the box! ! Select your SDK platform to get started: ![The logo of React](https://getstream.cdn.prismic.io/getstream/Ze7pQEmNsf2sHfou_react- original.svg?auto=compress,format) React * [UI Components ->](https://getstream.io/chat/docs/sdk/react/) * [Client ->](https://getstream.io/chat/docs/react/?language=javascript) ![The logo of Swift](https://getstream.cdn.prismic.io/getstream/Ze7qA0mNsf2sHfpX_swift- original.svg?auto=compress,format) iOS / Swift * [UI Components ->](https://getstream.io/chat/docs/sdk/ios/) * [Client ->](https://getstream.io/chat/docs/ios-swift/?language=swift) ![The logo of Android](https://getstream.cdn.prismic.io/getstream/Ze7m8kmNsf2sHfnz_android- plain.svg?auto=compress,format) Android * [UI Components ->](https://getstream.io/chat/docs/sdk/android/) * [Client ->](https://getstream.io/chat/docs/android/?language=kotlin) ![The logo of React Native](https://getstream.cdn.prismic.io/getstream/Ze7pQEmNsf2sHfou_react- original.svg?auto=compress,format) React Native * [UI Components ->](https://getstream.io/chat/docs/sdk/reactnative/) * [Client ->](https://getstream.io/chat/docs/react-native/?language=javascript) ![The logo of Flutter](https://getstream.cdn.prismic.io/getstream/Ze7nxEmNsf2sHfoE_flutter- original.svg?auto=compress,format) Flutter * [UI Components ->](https://getstream.io/chat/docs/sdk/flutter/) * [Client ->](https://getstream.io/chat/docs/flutter-dart/?language=dart) ![The logo of Unreal](https://getstream.cdn.prismic.io/getstream/Ze7qZ0mNsf2sHfpd_unrealengine- original.svg?auto=compress,format) Unreal * [Client ->](https://getstream.io/chat/docs/unreal/?language=unreal) ![The logo of Unity](https://getstream.cdn.prismic.io/getstream/Ze7qNEmNsf2sHfpa_unity- original.svg?auto=compress,format) Unity * [Client ->](https://getstream.io/chat/docs/unity/?language=unity) ![The logo of Angular](https://getstream.cdn.prismic.io/getstream/Ze7uVEmNsf2sHfsk_angular- original.svg?auto=compress,format) Angular * [UI Components ->](https://getstream.io/chat/docs/sdk/angular/) * [Client ->](https://getstream.io/chat/docs/javascript/?language=javascript) ![The logo of JavaScript](https://getstream.cdn.prismic.io/getstream/Ze7olUmNsf2sHfoT_javascript- original.svg?auto=compress,format) Javascript * [Client ->](https://getstream.io/chat/docs/javascript/?language=javascript) Backend Clients ![The logo of Node](https://getstream.cdn.prismic.io/getstream/Ze7o90mNsf2sHfoa_nodejs- original.svg?auto=compress,format) NodeJS v8.29.0 * [View ->](https://getstream.io/chat/docs/node/?language=javascript) ![The logo of Python](https://getstream.cdn.prismic.io/getstream/Ze7pHkmNsf2sHfol_python- original.svg?auto=compress,format) Python v4.15.0 * [View ->](https://getstream.io/chat/docs/python/?language=python) ![The logo of Ruby](https://getstream.cdn.prismic.io/getstream/Ze7pxUmNsf2sHfpM_ruby- original.svg?auto=compress,format) Ruby v3.5.1 * [View ->](https://getstream.io/chat/docs/ruby/?language=ruby) ! PHP 3.4.1 * [View ->](https://getstream.io/chat/docs/php/?language=php) ![The logo of Java](https://getstream.cdn.prismic.io/getstream/Ze7oJkmNsf2sHfoP_java- original.svg?auto=compress,format) Java 1.22.2 * [View ->](https://getstream.io/chat/docs/java/?language=java) ![The logo of .NET](https://getstream.cdn.prismic.io/getstream/Ze7nnEmNsf2sHfn__dot-net- original.svg?auto=compress,format) .NET 2.5.0 * [View ->](https://getstream.io/chat/docs/dotnet-csharp/?language=csharp) ![The logo of Go](https://getstream.cdn.prismic.io/getstream/Ze7n_EmNsf2sHfoJ_go-original- wordmark.svg?auto=compress,format) Go v6.10.0 * [View ->](https://getstream.io/chat/docs/go-golang/?language=go) ! REST API * [View ->](https://getstream.github.io/protocol/?urls.primaryName=Chat) Tutorials ![The logo of Swift](https://getstream.cdn.prismic.io/getstream/Ze7qA0mNsf2sHfpX_swift- original.svg?auto=compress,format) iOS Kit [4.53.0](https://github.com/GetStream/stream-chat-swift/) This tutorial will teach you how to build chat for your iOS app with offline support, optimistic UI updates, reactions, threads, URL previews, typing indicators, and image sharing. * [View Tutorial ->](/chat/sdk/ios/tutorial/swiftui/) ![The logo of Android](https://getstream.cdn.prismic.io/getstream/Ze7m8kmNsf2sHfnz_android- plain.svg?auto=compress,format) Android Kit [v6.3.1](https://github.com/GetStream/stream-chat-android/) This tutorial will teach you how to build in-app chat or messaging with Jetpack Compose & Stream's edge network. * [View Tutorial ->](/chat/sdk/android/tutorial/compose/) ![The logo of React Native](https://getstream.cdn.prismic.io/getstream/Ze7pQEmNsf2sHfou_react- original.svg?auto=compress,format) React Native Kit [v5.28.1](https://github.com/GetStream/stream-chat-react-native/) This tutorial will teach you how to build a mobile chat application similar to Facebook Messenger or Telegram. * [View Tutorial ->](/chat/sdk/react-native/tutorial/cli/) ![The logo of Flutter](https://getstream.cdn.prismic.io/getstream/Ze7nxEmNsf2sHfoE_flutter- original.svg?auto=compress,format) Flutter Kit [7.2.0-hotfix.1](https://github.com/GetStream/stream-chat-flutter/) This tutorial will teach you how to build a functioning mobile app with support for rich messages, reactions, threads, image uploads, and videos. * [View Tutorial ->](/chat/sdk/flutter/tutorial/) ## Start coding for free **No credit card required.** If you're interested in a custom plan or have any questions, please contact us. [Start Coding Free >_](/chat/trial/)[Contact Sales ->](/contact/) Products * [Chat Messaging](/chat/) * [Video & Audio](/video/) * [Activity Feeds](/activity-feeds/) * [AI Moderation](/moderation/) * Comparison * [Stream vs Sendbird](https://getstream.io/chat/stream-vs-sendbird/) * [Sendbird Alternatives](/blog/sendbird-competitor-alternatives/) * [Pricing Breakdown](/blog/what-i-learned-researching-chat-api-pricing/) * [Stream vs Vonage](/blog/vonage-comparison/) * [Twilio Alternatives](/blog/twilio-video-alternatives/) * [Twilio migration](/blog/migrate-twilio-programmable-video/) Developers * [Chat Messaging Docs](/chat/docs/) * [Video & Audio Docs](/video/docs/) * [Activity Feeds Docs](/activity-feeds/docs/?language=javascript) * [AI Moderation Docs](/moderation/docs/) * Resources * [Stack Overflow](https://stackoverflow.com/questions/tagged/getstream-io) * [YouTube](https://www.youtube.com/channel/UC2xOn0xQj1HIpHJpOy5tvpA/featured) * [GitHub](https://github.com/GetStream/) * Featured tutorials * [Build a Twitter Clone](/resources/projects/twitter-clone/) * [WebRTC Tutorial Series](/resources/projects/webrtc/) Company[Hiring](/team/#jobs) * [About Us](/team/) * [Careers](/team/#jobs) * [Blog](/blog/) * [Case Studies](/blog/topic/case-studies-2/) * [Enterprise](/enterprise/) * [Press & Awards](/press/) * [Glossary](/glossary/) * [Partners](/partners/) * [Trust Center](https://trust.getstream.io/) Contact Us * [Sales](/contact/) * [Support](/contact/support/) * [Bug Report](/contact/bug-report/) [![Stream logo](/stream-light.png)](/) Stream is proudly designed, built and continually enhanced in [Boulder, CO](/team/), and [Amsterdam, NL](/team/); with a global remote team. [System Status](https://status.getstream.io/) © Stream.io, Inc. All Rights Reserved. * [Terms](/legal/) * [Privacy](/legal/privacy/) * [Security](/security/) * * * * --- # Stream.io Documentation # Source: https://getstream.io/moderation/docs/engines/ai-llm-text/ * [Moderation](/moderation/) / * [Docs](/moderation/docs/) / * [AI Text Harm Detection (LLM)](/moderation/docs/engines/ai-llm-text/) # AI Text Harm Detection (LLM) This engine harnesses the power of LLMs to detect harmful content not just by scanning abusive words, but by understanding the context of the content and the intent of the user. ![AI LLM Text Moderation](/_astro/ai_llm_text_moderation.BqivmaH8_Z1apXki.webp) * Describe in plain language what you want the system to detect, and the engine will handle the rest. * Share context about your application so the LLM can better understand the context in which users are interacting. * Moderation considers both the message and its context, focusing on user intent rather than just keywords. * Detects and blocks attempts to bypass moderation by splitting harmful content across multiple messages. ## Language Support No language limits. ## How it works The LLM moderation engine classifies content based on your configuration and recent conversation history. To set it up, you’ll provide two key inputs: **App Context** : A short description of your application and how users interact. This helps the LLM understand your platform’s environment (e.g., casual chat, professional tone, teen audience). **LLM Rules** : Clear harm categories written in plain language. For example, you might define what counts as SCAM, HATE SPEECH, or SEXUAL HARASSMENT in your community. When a new message is sent, the engine considers: * Your defined app context * Your LLM rules * The last few messages in the conversation It then passes this information to the LLM, which classifies the message against your rule set and applies the configured moderation action (flag, block, review, etc.). ## Configuration You can set up the LLM moderation engine directly in the dashboard. 1. In the dashboard, navigate to **Moderation → Policies**. 2. Select the policy you want to update. 3. Navigate to **AI (LLM) Text**. 4. Add your app context and harm labels, then define prompts for each label. ![AI LLM Text Moderation Configuration](/_astro/ai_llm_text_configurations.BIo-i9PI_21euls.webp) We provide starter rules like SCAM, HATE SPEECH, SEXUAL HARASSMENT, PII, and PLATFORM BYPASS to help you get started. You can edit or remove these if they’re not needed. ## Moderation Prompt Guide When you set up a harm label in the dashboard, you’re talking directly to the LLM, telling it what to look for. You will need two things: **Harm Label** — a short, descriptive name you’ll use to track this category. **Prompt** — a clear instruction for the LLM to follow when deciding whether content matches that label. ### Writing with Clarity & Precision **Harm Label** * Keep it short and descriptive. * Examples: * Scam * Sexual Harassment * Bullying * Hate Speech **Prompt** * Write prompts like commands so the LLM knows exactly what to detect. * Examples of good prompts: * Messages where recruiters are trying to headhunt or share job descriptions. * Fraudulent content, phishing attempts, or deceptive practices. * Content that promotes hatred, discrimination, or violence against groups. ### Best Practices: Do’s and Don’ts **Do:** * Write in plain, directive language. * Specify exactly what behaviors or content to act on. * Keep each label focused on a single harm type. * Periodically review and refine prompts based on fundamental user interactions. **Don’t:** * Use vague, generalized terms like “bad,” “inappropriate,” or “offensive.” * Attempt to cover multiple harms in one label or prompt. * Overload the prompt with too much nuance, if it’s too long, break it into multiple labels. ### Prompt Debugging Checklist If something doesn’t seem to work or the LLM is flagging the wrong content run through this quick checklist: * **Clarity** – Is the prompt easy to understand and unambiguous? * **Scope** – Is the label targeting just one type of harm? * **Context** – Did you include platform-specific norms or boundaries (e.g., “casual chat”, “professional tone”, “teen audience”)? * **Human-level testability** – Would a person easily know what to flag based on your text? * **Avoid Over-censoring** – Am I flagging harmless content (like jokes or slang) mistakenly? * **One-change-at-a-time** – When testing, adjust only one variable so it’s easier to see what worked. * **Real-conversation testing** – Have you tested it on actual messages to balance what it catches vs. what it miss? ### Iterate & Improve Follow these steps to refine your prompts over time: 1. **Start Simple** : Begin with the most important harm types. 2. **Test Prompts** : Collect real examples and check what gets flagged or missed. 3. **Split When Needed** : If a prompt is too broad, break it into narrower labels. 4. **Review & Document**: Keep track of changes to know what’s working (or not). 5. **Share Learnings** : Document successful prompts in an internal library so your team can reuse proven approaches. ### Why It Matters By providing clear labels and prompts: * The LLM can operate consistently and accurately. * You build a safer and more trustworthy experience for your users. * You reduce false positives, missed issues, and make moderation more efficient for your team. ## Starter Prompt Library Use these pre-made harm labels and prompts as a baseline. You can copy them directly into your dashboard and adapt them to fit your community’s needs. **BULLYING** Insults, threats, or repeated targeting of another user intended to cause harm. **SELF_HARM** Messages where a user expresses intent to harm themselves, commit suicide, or encourages others to do so. **CHILD_SAFETY** Sexual content involving minors, attempts to exploit children, or discussions of child sexual abuse material (CSAM). **TERRORISM** Content that promotes or glorifies terrorism, violent extremism, or recruitment to extremist groups. **Tip** : Keep prompts about detection only. Let the moderation action (flag, block, review, etc.) be configured separately in the dashboard. Did you find this page helpful? It was helpful It was not helpful I have feedback Submit Thank you for the feedback. An error has occurred. Please refresh the page and try again. [PreviousLive Event Moderation](/moderation/docs/quick-start/live-event- moderation/)[NextAI Text Harm Detection (NLP)](/moderation/docs/engines/ai- text/) © Stream.io, Inc. All Rights Reserved. [Chat Messaging](https://getstream.io/chat/)[Video & Audio](https://getstream.io/video/)[Activity Feeds](https://getstream.io/activity- feeds/)[Moderation](https://getstream.io/moderation/) * Copy LLM prompt * [ View as markdown](https://getstream.io/moderation/docs/engines/ai-llm-text.md) * * [ Open in ChatGPT](https://chatgpt.com/?q=I'm working with the Stream Moderation SDK and would like to ask questions about this documentation page: https://getstream.io/moderation/docs/engines/ai-llm-text.md) * [ Open in Claude](https://claude.ai/new?q=I'm working with the Stream Moderation SDK and would like to ask questions about this documentation page: https://getstream.io/moderation/docs/engines/ai-llm-text.md) * [ Open in Gemini](https://gemini.google.com/app?query=I'm working with the Stream Moderation SDK and would like to ask questions about this documentation page: https://getstream.io/moderation/docs/engines/ai-llm-text.md) * [ Open in Grok](https://x.com/i/grok?text=I'm working with the Stream Moderation SDK and would like to ask questions about this documentation page: https://getstream.io/moderation/docs/engines/ai-llm-text.md) * [ Open in Perplexity](https://www.perplexity.ai/search/new?q=I'm working with the Stream Moderation SDK and would like to ask questions about this documentation page: https://getstream.io/moderation/docs/engines/ai-llm-text.md) On this page: * Language Support * How it works * Configuration * Moderation Prompt Guide * Writing with Clarity & Precision * Best Practices: Do’s and Don’ts * Prompt Debugging Checklist * Iterate & Improve * Why It Matters * Starter Prompt Library Is this helpful? Thank you . An error has occurred. --- # Stream.io Documentation # Source: https://getstream.io/moderation/docs/ * [Moderation](/moderation/) / * [Docs](/moderation/docs/) # Moderation Introduction Moderation is essential for maintaining a positive user experience on any digital platform. Unchecked problematic content can quickly drive away users and damage your brand’s reputation. Stream’s comprehensive moderation capabilities offer a robust solution that is easy to implement, cost- effective, and scalable for applications of all sizes. ## Key Features of Stream’s Moderation 1. **Extensive Harm Detection** : * Identifies approximately 40 different types of harmful content * Supports detection in 30 languages, ensuring global coverage 2. **AI-Powered Moderation** : * Utilizes advanced machine learning algorithms for accurate content analysis * Reduces the workload on human moderators by automatically flagging potential issues 3. **Human Moderation Dashboard** : * Provides an intuitive interface for your moderation team * Allows for easy review and decision-making on flagged content 4. **Seamless Integration** : * Automatically works with Stream’s chat and activity feed products * Can be easily integrated into existing workflows 5. **Multi-Media Moderation** : * Text moderation for chat messages, comments, and user-generated content * Image moderation to detect inappropriate visual content * Video moderation capabilities to ensure safe video sharing 6. **Flexible API-Driven Approach** : * Allows for moderation of various content types beyond chat and feeds * You can use Stream’s moderation APIs to integrate moderation into your own workflows by building your own moderation dashboard UI * You can integrate your own AI checks to further customize the moderation experience 7. **Cost-Effective Solution** : * Scales efficiently, making it suitable for startups and enterprise-level applications * Reduces the need for large in-house moderation teams By implementing Stream’s moderation tools, you can create a safer, more engaging environment for your users while protecting your platform from harmful content. In the following sections, we’ll dive deeper into each aspect of Stream’s moderation capabilities and guide you through the implementation process. Did you find this page helpful? It was helpful It was not helpful I have feedback Submit Thank you for the feedback. An error has occurred. Please refresh the page and try again. [NextRoadmap & Changelog](/moderation/docs/roadmap_and_changelog/) © Stream.io, Inc. All Rights Reserved. [Chat Messaging](https://getstream.io/chat/)[Video & Audio](https://getstream.io/video/)[Activity Feeds](https://getstream.io/activity- feeds/)[Moderation](https://getstream.io/moderation/) * Copy LLM prompt * [ View as markdown](https://getstream.io/moderation/docs.md) * * [ Open in ChatGPT](https://chatgpt.com/?q=I'm working with the Stream Moderation SDK and would like to ask questions about this documentation page: https://getstream.io/moderation/docs.md) * [ Open in Claude](https://claude.ai/new?q=I'm working with the Stream Moderation SDK and would like to ask questions about this documentation page: https://getstream.io/moderation/docs.md) * [ Open in Gemini](https://gemini.google.com/app?query=I'm working with the Stream Moderation SDK and would like to ask questions about this documentation page: https://getstream.io/moderation/docs.md) * [ Open in Grok](https://x.com/i/grok?text=I'm working with the Stream Moderation SDK and would like to ask questions about this documentation page: https://getstream.io/moderation/docs.md) * [ Open in Perplexity](https://www.perplexity.ai/search/new?q=I'm working with the Stream Moderation SDK and would like to ask questions about this documentation page: https://getstream.io/moderation/docs.md) On this page: * Key Features of Stream’s Moderation Is this helpful? Thank you . An error has occurred. --- # Stream.io Documentation # Source: https://getstream.io/chat/docs/moderation/ * [Chat Messaging](/chat/) / * [Docs](/chat/docs/) / * [React](/chat/docs/react/) / * [Moderation for Chat](/chat/docs/react/moderation/) # Moderation for Chat Moderation is essential for a good user experience on chat. There are also requirements from DSA and the app stores to take into account. Stream has advanced AI moderation capabilities for text, images, video and audio. Before we launched moderation, customers often struggled with the cost and difficulty of integrating external moderation APIs. You can now setup moderation in minutes at an affordable price point. There are 4 layers of moderation: * **Limits / chat features** : Restrict what’s allowed. Moderator permissions, disabling links or images, slow mode, enforce_unique_usernames, slash commands etc. * **Simple** : Blocklist, regex, domain allow/block, email allow/block * **User actions** : Flag, mute, ban etc. * **[AI moderation](/moderation/docs/)** : AI on text, images, video, audio Let’s go over each of these and show what’s supported. ## Limits & Chat features ### Disabling the permission to post links or add attachments You can control links and attachments by revoking the relevant permissions for a role. The permissions to manage are: * `add-links` \- ability to post messages containing URLs * `create-attachment` \- ability to add attachments to messages * `upload-attachment` \- ability to upload files/images Update the grants for a channel type to remove these permissions from a role: JavaScriptPythonPHPGo // Remove link and attachment permissions for channel_member role await client.updateChannelType("messaging", { grants: { channel_member: [ "read-channel", "create-message", "update-message-owner", "delete-message-owner", // "add-links" - removed to disable links // "create-attachment" - removed to disable attachments // "upload-attachment" - removed to disable uploads ], }, }); # Remove link and attachment permissions for channel_member role client.update_channel_type("messaging", grants={ "channel_member": [ "read-channel", "create-message", "update-message-owner", "delete-message-owner", # "add-links" - removed to disable links # "create-attachment" - removed to disable attachments # "upload-attachment" - removed to disable uploads ], }) // Remove link and attachment permissions for channel_member role $client->updateChannelType('messaging', [ 'grants' => [ 'channel_member' => [ 'read-channel', 'create-message', 'update-message-owner', 'delete-message-owner', // 'add-links' - removed to disable links // 'create-attachment' - removed to disable attachments // 'upload-attachment' - removed to disable uploads ], ], ]); // Remove link and attachment permissions for channel_member role client.UpdateChannelType(ctx, "messaging", map[string]interface{}{ "grants": map[string][]string{ "channel_member": { "read-channel", "create-message", "update-message-owner", "delete-message-owner", // "add-links" - removed to disable links // "create-attachment" - removed to disable attachments // "upload-attachment" - removed to disable uploads }, }, }) For more details on permissions, see [User Permissions](/chat/docs/react/chat_permission_policies/). ### Image & Video file types You can restrict which file types users can upload using `image_upload_config` and `file_upload_config`. This allows you to set allowed or blocked file extensions and MIME types, as well as size limits. Both configs accept the following fields: Field| Description `allowed_file_extensions`| Array of allowed file extensions (e.g., `[".jpg", ".png"]`) `blocked_file_extensions`| Array of blocked file extensions `allowed_mime_types`| Array of allowed MIME types (e.g., `["image/jpeg", "image/png"]`) `blocked_mime_types`| Array of blocked MIME types `size_limit`| Maximum file size in bytes (default allows up to 100MB) JavaScriptPythonGo // Restrict images to common formats only await client.updateAppSettings({ image_upload_config: { allowed_file_extensions: [".jpg", ".jpeg", ".png", ".gif", ".webp"], allowed_mime_types: ["image/jpeg", "image/png", "image/gif", "image/webp"], size_limit: 5 * 1024 * 1024, // 5MB }, // Restrict file uploads to documents only file_upload_config: { allowed_file_extensions: [".pdf", ".doc", ".docx"], allowed_mime_types: ["application/pdf", "application/msword"], size_limit: 10 * 1024 * 1024, // 10MB }, }); # Restrict images to common formats only client.update_app_settings({ "image_upload_config": { "allowed_file_extensions": [".jpg", ".jpeg", ".png", ".gif", ".webp"], "allowed_mime_types": ["image/jpeg", "image/png", "image/gif", "image/webp"], "size_limit": 5 * 1024 * 1024, # 5MB }, # Restrict file uploads to documents only "file_upload_config": { "allowed_file_extensions": [".pdf", ".doc", ".docx"], "allowed_mime_types": ["application/pdf", "application/msword"], "size_limit": 10 * 1024 * 1024, # 10MB }, }) // Restrict images to common formats only client.UpdateAppSettings(ctx, &UpdateAppSettingsRequest{ ImageUploadConfig: &FileUploadConfig{ AllowedFileExtensions: []string{".jpg", ".jpeg", ".png", ".gif", ".webp"}, AllowedMimeTypes: []string{"image/jpeg", "image/png", "image/gif", "image/webp"}, SizeLimit: 5 * 1024 * 1024, // 5MB }, FileUploadConfig: &FileUploadConfig{ AllowedFileExtensions: []string{".pdf", ".doc", ".docx"}, AllowedMimeTypes: []string{"application/pdf", "application/msword"}, SizeLimit: 10 * 1024 * 1024, // 10MB }, }) For more details, see [App Settings](/chat/docs/react/app_setting_overview/). ### Giving moderators more permissions Moderators have elevated permissions like the ability to ban users, delete messages, and more. You can assign moderator roles to users at the channel level or across all channels. **Add a Moderator to a Channel:** JavaScriptPythonRubyPHPGo // Add a member with moderator role await channel.addMembers([ { user_id: "james_bond", channel_role: "channel_moderator" }, ]); # Add a member with moderator role channel.add_members([{"user_id": "james_bond", "channel_role": "channel_moderator"}]) # Add a member with moderator role channel.add_members([{'user_id' => 'james_bond', 'channel_role' => 'channel_moderator'}]) // Add a member with moderator role $channel->addMembers([ ['user_id' => 'james_bond', 'channel_role' => 'channel_moderator'], ]); // Assign moderator role a := []*RoleAssignment{{ChannelRole: "channel_moderator", UserID: "james_bond"}} resp, err = ch.AssignRole(ctx, a, nil) **Make a User a Moderator Across All Channels:** To grant a user moderator permissions across all channels in your app, update their global role: JavaScriptPythonPHPGo await client.partialUpdateUser({ id: "james_bond", set: { role: "admin" }, }); client.update_user_partial( {"id": "james_bond", "set": {"role": "admin"}} ) $client->partialUpdateUsers([ 'id' => 'james_bond', 'set' => [ 'role' => 'admin', ], ]); client.PartialUpdateUser(ctx, &PartialUserUpdate{ ID: "james_bond", Set: map[string]interface{}{ "role": "admin", }, }) For more details on permissions, see [User Permissions](/chat/docs/react/chat_permission_policies/). ### Slow mode Slow mode helps reduce noise on a channel by limiting users to a maximum of 1 message per cooldown interval (1-120 seconds). Moderators, admins, and server- side API calls are not restricted. KotlinJavaScriptSwiftPHPPythonJavaGo val channelClient = client.channel("messaging", "general") // Enable slow mode and set cooldown to 1s channelClient.enableSlowMode(cooldownTimeInSeconds = 1).enqueue { /* Result handling */ } // Increase cooldown to 30s channelClient.enableSlowMode(cooldownTimeInSeconds = 30).enqueue { /* Result handling */ } // Disable slow mode channelClient.disableSlowMode().enqueue { /* Result handling */ } // enable slow mode and set cooldown to 1s await channel.enableSlowMode(1); // increase cooldown to 30s await channel.enableSlowMode(30); // disable slow mode await channel.disableSlowMode(); let channelController = client.channelController(for: .init(type: .messaging, id: "general")) channelController.enableSlowMode(cooldownDuration: 10) channelController.disableSlowMode() $update = $channel->update([ 'cooldown' => 30 ]); // 30 sec channel.update({ "cooldown": 30 }) # 30 sec // Enable slow mode and set cooldown to 1s channelClient.enableSlowMode(1).enqueue(result -> { /* Result handling */ }); // Disable slow mode channelClient.disableSlowMode().enqueue(result -> { /* Result handling */ }); channel.Update(ctx, map[string]interface{}{"cooldown": 30}, nil) // 30 sec For more details, see [Slow Mode & Throttling](/chat/docs/react/slow_mode/). ### Enforce unique usernames This setting prevents users from using duplicate usernames. When enabled with `app`, it enforces uniqueness across the entire app. With `team`, it only enforces within the same team. JavaScriptPythonRubyPHPJavaGo // Enable uniqueness constraints on App level await client.updateAppSettings({ enforce_unique_usernames: "app", }); // Enable uniqueness constraints on Team level await client.updateAppSettings({ enforce_unique_usernames: "team", }); # Enable uniqueness constraints on App level client.update_app_settings(enforce_unique_usernames="app") # Enable uniqueness constraints on Team level client.update_app_settings(enforce_unique_usernames="team") # Enable uniqueness constraints on App level client.update_app_settings(enforce_unique_usernames: 'app') # Enable uniqueness constraints on Team level client.update_app_settings(enforce_unique_usernames: 'team') // Enable uniqueness constraints on App level $client->updateAppSettings(["enforce_unique_usernames" => "app"]); // Enable uniqueness constraints on Team level $client->updateAppSettings(["enforce_unique_usernames" => "team"]); // Enable uniqueness constraints on App level App.update().enforceUniqueUsernames("app").request(); // Enable uniqueness constraints on Team level App.update().enforceUniqueUsernames("team").request(); // Enable uniqueness constraints on App level settings := &AppSettings{EnforceUniqueUsernames: "app"} resp, err = client.UpdateAppSettings(ctx, settings) // Enable uniqueness constraints on Team level settings := &AppSettings{EnforceUniqueUsernames: "team"} resp, err = client.UpdateAppSettings(ctx, settings) ### Slash commands for banning Stream Chat supports built-in slash commands like `/ban` and `/unban` for quick moderation actions. Enable these commands on your channel type: JavaScriptPythonRubyPHPJavaGo // Enable ban/unban commands for a channel type await client.updateChannelType("messaging", { commands: ["giphy", "ban", "unban", "mute", "unmute", "flag"], }); # Enable ban/unban commands for a channel type client.update_channel_type( "messaging", commands=["ban", "unban", "mute", "unmute", "flag"], ) # Enable ban/unban commands for a channel type client.update_channel_type( "messaging", commands: ["ban", "unban", "mute", "unmute", "flag"] ) // Enable ban/unban commands for a channel type $client->updateChannelType('messaging', [ 'commands' => ['giphy', 'ban', 'unban', 'mute', 'unmute', 'flag'] ]); // Enable ban/unban commands for a channel type ChannelType.update("messaging") .commands(List.of("ban", "unban", "mute", "unmute", "flag")) .request(); // Enable ban/unban commands for a channel type client.UpdateChannelType(ctx, "messaging", map[string]interface{}{ "commands": []interface{}{"ban", "unban", "mute", "unmute", "flag"}, }) ## Simple Moderation features ### Blocklist A Blocklist is a list of words that you can use to moderate chat messages. Stream Chat comes with a built-in Blocklist called `profanity_en_2020_v1` which contains over a thousand of the most common profane words. You can manage your own blocklists via the Stream dashboard or APIs to a manage blocklists and configure your channel types to use them. Channel types can be configured to block or flag messages from your users based on your blocklists. To do this you need to configure your channel type(s) with these two configurations: `blocklist` and `blocklist_behavior`. The first one refers to the name of the blocklist and the second must be set as `block` or `flag` . * Applications can have up to 15 blocklists in total alongside advanced filters * A Blocklist can contain up to 10,000 words, each word can be up to 40 characters * The blocklist words must be in lowercase * Text matching is done with case insensitive word match (no prefix, post-fix support) * Messages are split into words using white spaces and hyphens (cookie-monster matches both “cookie” and “monster”) So for instance, if you have a blocklist with the word “cream” these messages will be blocked or flagged: * She jabbed the spoon in the ice cream and sighed * Cream is the best and it will not affect any of these * Is creamcheese a word? * I did not enjoy watching Scream The default blocklist contains material that many will find offensive. #### Setup example Blocklists can be managed using the APIs like any other Chat feature. Here is a simple example on how to create a Blocklist and use it for a channel type. JavaScriptPHPPythonRubyJavaGoC# // add a new blocklist for this app await client.createBlockList({ name: "no-cakes", words: ["fudge", "cream", "sugar"], }); // use the blocklist for all channels of type messaging await client.updateChannelType("messaging", { blocklist: "no-cakes", blocklist_behavior: "block", }); // add a new blocklist for this app $client->createBlocklist(["no-cakes" => $name, "words" => ["fudge", "cream", "sugar"]]); # add a new blocklist for this app client.create_blocklist(name="no-cakes", words=["fudge", "cream", "sugar"]) # use the blocklist for all channels of type messaging client.update_channel_type("messaging", blocklist="no-cakes", blocklist_behavior="block") # require 'stream-chat' # add a new blocklist for this app client.create_blocklist("no-cakes", words: ["fudge", "cream", "sugar"]) # use the blocklist for all channels of type messaging client.update_channel_type("messaging", blocklist: "no-cakes", blocklist_behavior: "block") // add a new blocklist for this app Blocklist.create() .name("no-cakes") .words(List.of("fudge", "cream", "sugar")) .request(); // use the blocklist for all channels of type messaging ChannelType.update("messaging") .blocklist("no-cakes") .blocklistBehavior(ChannelType.BlocklistBehavior.BLOCK) .request(); // add a new blocklist for this app blocklistReq := &BlocklistCreateRequest{BlocklistBase{Name: "no-cakes", Words: []string{"fudge", "cream", "sugar"}}} client.CreateBlocklist(ctx, blocklistReq) // use the blocklist for all channels of type messaging client.UpdateChannelType(ctx, "messaging", map[string]interface{}{ "blocklist": "no-cakes", "blocklist_behavior": "block", }) // add a new blocklist for this app await blocklistClient.CreateAsync(new BlocklistCreateRequest { Name = "no-cakes", Words = new[] { "fudge", "cream", "sugar" }, }); // use the blocklist for all channels of type messaging #### List available blocklists All applications have the `profanity_en_2020_v1` blocklist available. This endpoint returns all blocklists available for this application. JavaScriptPHPPythonRubyJavaGoC# await client.listBlockLists(); $client->listBlocklists(); client.list_blocklists() client.list_blocklists() Blocklist.list().request(); client.ListBlocklists(ctx) await blocklistClient.ListAsync(); #### Describe a blocklist JavaScriptPHPPythonRubyJavaGoC# await client.getBlockList("no-cakes"); $client->getBlocklist("no-cakes"); client.get_blocklist("no-cakes") client.get_blocklist("no-cakes") Blocklist.get("no-cakes").request(); c.GetBlocklist(ctx, "no-cakes") await blocklistClient.GetAsync("no-cakes"); #### Create new blocklist JavaScriptPHPPythonRubyJavaGoC# const words = ["fudge", "cream", "sugar"]; await client.createBlockList({ name: "no-cakes", words, }); $client->createBlocklist(["no-cakes" => $name, "words" => ["fudge", "cream", "sugar"]]); client.create_blocklist(name="no-cakes", words=["fudge", "cream", "sugar"]) client.create_blocklist("no-cakes", words: ["fudge", "cream", "sugar"]) Blocklist.create() .name("no-cakes") .words(List.of("fudge", "cream", "sugar")) .request(); blocklistReq := &BlocklistCreateRequest{BlocklistBase{Name: "no-cakes", Words: []string{"fudge", "cream", "sugar"}}} client.CreateBlocklist(ctx, blocklistReq) await blocklistClient.CreateAsync(new BlocklistCreateRequest { Name = "no-cakes", Words = new[] { "fudge", "cream", "sugar" }, }); #### Update a blocklist JavaScriptPHPPythonRubyJavaGoC# await client.updateBlockList("no-cakes", { words: ["fudge", "cream", "sugar", "vanilla"], }); $client->updateBlocklist("no-cakes", ["words" => ["fudge", "cream", "sugar", "vanilla"]]); client.update_blocklist("no-cakes", words=["fudge", "cream", "sugar", "vanilla"]) client.update_blocklist("no-cakes", words: ["fudge", "cream", "sugar", "vanilla"]) Blocklist.update("no-cakes") .words(List.of("fudge", "cream", "sugar", "vanilla"])) .request(); client.UpdateBlocklist(ctx, "no-cakes", []string{"fudge", "cream", "sugar", "vanilla"}) await blocklistClient.UpdateAsync("no-cakes", new[] { "fudge", "cream", "sugar", "vanilla" }); #### Delete a blocklist When a blocklist is deleted, it will be automatically removed from all channel types that were using it. JavaScriptPHPPythonRubyJavaGoC# await client.deleteBlockList("no-cakes"); $client->deleteBlocklist("no-cakes"); client.delete_blocklist("no-cakes") client.delete_blocklist("no-cakes") Blocklist.delete("no-cakes").request(); client.DeleteBlocklist(ctx, "no-cakes") await _blocklistClient.DeleteAsync("no-cakes"); ### Regex Regex filters allow you to match and moderate messages using regular expressions. This is useful for filtering patterns like phone numbers, URLs, or complex word variations. Configure regex filters via the Stream dashboard under ‘Blocklist & Regex Filters’. For detailed configuration, see [Regex, Email, and Domain Filters](/moderation/docs/engines/blocklists-and-regex-filters/). ### Email/domain allow or block You can configure domain and email filters to control what URLs and email addresses can be shared in messages. Set up allowlists or blocklists for specific domains via the Stream dashboard. For detailed configuration, see [Regex, Email, and Domain Filters](/moderation/docs/engines/blocklists-and-regex-filters/). ## User Actions ### Flag Any user can flag a message or user. Flagged content is added to your moderation review queue on the Stream Dashboard. KotlinJavaScriptSwiftPythonRubyGoUnity client.flagMessage( messageId = "message-id", reason = "This message is inappropriate", customData = mapOf("extra_info" to "more details"), ).enqueue { result -> if (result.isSuccess) { val flag: Flag = result.data() } else { // Handle result.error() } } client.flagUser( userId = "user-id", reason = "This user is a spammer", customData = mapOf("extra_info" to "more details"), ).enqueue { result -> if (result.isSuccess) { val flag: Flag = result.data() } else { // Handle result.error() } } // Flag a message const flag = await client.flagMessage(messageId); // Flag with a reason and custom data const flag = await client.flagMessage(messageId, { reason: "spammy_user", custom: { user_comment: "This user is spamming.", }, }); import StreamChat let messageController = chatClient.messageController(cid: channelId, messageId: messageId) messageController.flag { error in print(error ?? "message flagged") } // Flag a user let userController = chatClient.userController(userId: "another_user") userController.flag { error in print(error ?? "user flagged") } client.flag_message(msg["id"], user_id=server_user["id"]) @client.flag_message(msg_id, user_id: server_user[:id]) client.FlagMessage(ctx, msg.ID, user.ID) // Flag a message await message.FlagAsync(); // Flag a user await channelMember.User.FlagAsync(); #### Reasons & custom data You can enhance flags by associating them with a specific reason and custom data. It is advisable to utilise a slug or keyword as a designated reason for easy translation or other forms of display customisation. The custom data can encompass any object, offering supplementary metadata to the flag. The Query Message Flags endpoint retrieves both reasons and custom data, and the reason can also be utilised for filtering these flags. JavaScriptSwift // flag with a reason let flag = await client.flagMessage(messageID, { reason: "spammy_user", }); // flag with a reason and additional custom data flag = await client.flagMessage(messageID, { reason: "spammy_user", custom: { user_comment: "This user is spamming the homepage.", page: "homepage", }, }); // flag with only custom data flag = await client.flagMessage(messageID, { custom: { page: "homepage", }, }); // flag with a reason messageController.flag(reason: "spammy_user") #### Query Flagged Messages If you prefer to build your own in-app moderation dashboard, rather than use the Stream dashboard, you can query flagged messages using the `QueryReviewQueue` API endpoint. Both server-authenticated and user-authenticated clients can use this method. For client-side requests, the user needs moderator or admin permissions. JavaScript const response = await client.moderation.queryReviewQueue( { entity_type: "stream:chat:v1:message" }, [{ field: "created_at", direction: -1 }], { next: null }, ); for (const item of response.items) { console.log(item.message.id); console.log(item.message.text); console.log(item.message.type); console.log(item.message.created_at); } console.log(next); // <-- next cursor for pagination Please refer to the [Moderation API](/moderation/docs/api/#query-review-queue) documentation for more details. ### Mute Users can mute other users. Mutes are stored at the user level and returned when `connectUser` is called. Messages from muted users are still delivered via websocket but not via push notifications. See [Mute in the Moderation API](/moderation/docs/api/flag-mute-ban/#mute) for full documentation and SDK examples. ### Block The user block feature allows users to control their 1-on-1 interactions within the chat application by blocking other users. await client.blockUser("user-to-block"); #### How blocking impacts chat When a user is blocked, several changes occur: * **Direct Communication Termination** : When a user blocks another user, communication in all 1-on-1 channels are hidden for the blocking user. * **Adding to Channels** : If a blocked user tries to add the blocking user to a channel as a member, the action is ignored. The channel will not include the blocking user but will have the remaining members. * **Push Notifications** : The blocking user will not receive push notifications from blocked users for 1-on-1 channels. * **Channel Events** : The blocking user will not receive any events from blocked users in 1-on-1 channels (e.g., message.new). * **Group Channels** : Group channels are unaffected by the block. Both the blocking and blocked users can participate, receive push notifications, and events in group channels. * **Query Channels** : When hidden channels are requested, 1-on-1 channels with blocked users will be returned with a `blocked:true` flag and all the messages. * **Active Chats and Unread Counts** : Blocked users will not appear in the blocking user’s list of active chats. Messages from blocked users will not contribute to unread counts. * **Unblocking Users** : After unblocking, all previous messages in 1-on-1 channels become visible again, including those sent during the block period. * **Hidden Channels** : Channels with only the blocked and blocking users are marked as hidden for the blocking user by default. If a blocked user sends a message in a hidden channel, the channel remains hidden for the blocking user. * **Group Channel Messages** : Messages from blocked users will still appear when retrieving messages from a group channel. * **WebSocket Connection** : When connecting to the WebSocket, the blocking user receives a list of users they have blocked (user.blocked_users). This is only available for the blocking user’s own account. * **Message Actions** : Actions such as sending, updating, reacting to, and deleting messages will still work in blocked channels. However, since the channels are hidden, these actions will not be visible to the blocking user. #### Block User Any user is allowed to block another user. Blocked users are stored at the user level and returned with the rest of the user information when connectUser is called. A user will be blocked until the user is unblocked. JavaScriptKotlinSwift await client.blockUser("user-to-block"); client.blockUser("user-to-block-id").enqueue { /* ... */ } chatClient.userController(userId: userToBlock.id).block { error in ... } #### Unblock user JavaScriptKotlinSwift await client.unBlockUser(blockedUser); client.unblockUser("user-to-unblock-id").enqueue { /* ... */ } chatClient.userController(userId: userToUnblock.id).unblock { error in ... } #### List of Blocked Users JavaScriptKotlinSwift const resp = await client.getBlockedUsers(); client.queryBlockedUsers().enqueue { result -> if (result is Result.Success) { val blockedUsers: List = result.value } else { // Handle Result.Failure } } chatClient.currentUserController().loadBlockedUsers { result in switch result { case .success(let blockedUsers): // Handle success case .failure(let error): // Handle error } } #### Server Side **Block User:** JavaScriptGoC#Java const blockingUser = "user1"; const blockedUser = "user2"; await ctx.createUsers([blockingUser, blockedUser]); const serverClient = await ctx.serverClient(); await serverClient.blockUser(blockedUser, blockingUser); const resp = await serverClient.getBlockedUsers(blockingUser); resp, err := client.BlockUser(ctx, blockedUserID, blockingUserID) await userClient.BlockUserAsync(user2.Id, user1.Id); BlockUser.BlockUserResponse blockResponse = BlockUser.blockUser() .blockedUserID(blockedUserId) .userID(blockingUserId) .request(); **Unblock user:** JavaScriptGoC#Java await serverClient.unBlockUser(blockedUser, blockingUser); resp, err := client.UnblockUser(ctx, blockedUserID, blockingUserID) await userClient.UnblockUserAsync(user2.Id, user1.Id); BlockUser.UnblockUserResponse unblockResponse = BlockUser.unblockUser() .blockedUserID(blockedUserId) .userID(blockingUserId) .request(); **Get List of Blocked Users:** JavaScriptGoC#Java const resp = await client.getBlockedUsers(blockingUser); getRes, err := client.GetBlockedUser(ctx, blockingUserID) for _, blockedUser := getRes.BlockedUsers{ fmt.Println(blockedUser.BlockedUserID) } await userClient.GetBlockedUsersAsync(user1.Id); BlockUser.GetBlockedUsersResponse getBlockedUsersResponse = BlockUser.getBlockedUsers(blockingUserId).request(); ## AI moderation AI moderation can detect over 40 harms in 50+ different languages. In addition to these classification models LLM based moderation is also supported. Moderation APIs are available at additional costs. It’s priced to be cost- effective and typically is a fraction of the cost of other moderation APIs. [Read the full AI moderation docs](/moderation/docs/). ## Ban Users can be banned from an app entirely or from a channel. When banned, they cannot post messages until the ban is removed or expires. You can also apply IP bans and optionally delete the user’s messages. See [Ban in the Moderation API](/moderation/docs/api/flag-mute-ban/#ban) for full documentation, including shadow bans, query endpoints, and SDK examples. Did you find this page helpful? It was helpful It was not helpful I have feedback Submit Thank you for the feedback. An error has occurred. Please refresh the page and try again. [PreviousOverview](/chat/docs/react/best_practices/)[NextMarketplace Apps](/chat/docs/react/marketplace_best_practices/) © Stream.io, Inc. All Rights Reserved. [Chat Messaging](https://getstream.io/chat/)[Video & Audio](https://getstream.io/video/)[Activity Feeds](https://getstream.io/activity- feeds/)[Moderation](https://getstream.io/moderation/) * Copy LLM prompt * [ View as markdown](https://getstream.io/chat/docs/react/moderation.md) * * [ Open in ChatGPT](https://chatgpt.com/?q=I'm working with the Stream Chat React SDK and would like to ask questions about this documentation page: https://getstream.io/chat/docs/react/moderation.md) * [ Open in Claude](https://claude.ai/new?q=I'm working with the Stream Chat React SDK and would like to ask questions about this documentation page: https://getstream.io/chat/docs/react/moderation.md) * [ Open in Gemini](https://gemini.google.com/app?query=I'm working with the Stream Chat React SDK and would like to ask questions about this documentation page: https://getstream.io/chat/docs/react/moderation.md) * [ Open in Grok](https://x.com/i/grok?text=I'm working with the Stream Chat React SDK and would like to ask questions about this documentation page: https://getstream.io/chat/docs/react/moderation.md) * [ Open in Perplexity](https://www.perplexity.ai/search/new?q=I'm working with the Stream Chat React SDK and would like to ask questions about this documentation page: https://getstream.io/chat/docs/react/moderation.md) On this page: * Limits & Chat features * Disabling the permission to post links or add attachments * Image & Video file types * Giving moderators more permissions * Slow mode * Enforce unique usernames * Slash commands for banning * Simple Moderation features * Blocklist * Regex * Email/domain allow or block * User Actions * Flag * Mute * Block * AI moderation * Ban Is this helpful? Thank you . An error has occurred. --- # Stream.io Documentation # Source: https://getstream.io/chat/docs/permissions/ * [Chat Messaging](/chat/) / * [Docs](/chat/docs/) / * [React](/chat/docs/react/) / * [Reference](/chat/docs/react/permissions_reference/) # Reference This reference contains some useful information about permission system, applicable to both versions. ## Actions In the table below you will find all available actions of Stream Chat permission system Action| Resource Type| Description AddLinks| Channel| Allows user to add URLs into messages AddOwnChannelMembership| Channel| Allows user to add own channel membership (join channel) BanChannelMember| Channel| Allows user to ban channel members CreateChannel| Channel| Allows user to create a new channel CreateDistinctChannelForOthers| Channel| Allows user to create new distinct channel for other users (e.g. user A creates channel for users B and C) CreateMessage| Channel| Allows user to send a new message CreateAttachment| Channel| Allows user to send a new message with attachments CreateMention| Channel| Allows user to send a new message with mentions CreateReaction| Channel| Allows user to add a reaction to a message CreateSystemMessage| Channel| Allows user to send a new system message DeleteChannel| Channel| Allows user to delete a channel DeleteReaction| Channel| Allows user to delete a reaction FlagMessage| Channel| Allows user to flag messages MuteChannel| Channel| Allows user to mute and unmute channel PinMessage| Channel| Allows user to pin a message ReadChannel| Channel| Allows user to read messages from the channel ReadChannelMembers| Channel| Allows user to read channel members ReadDisabledChannel| User| Allows user to read disabled channels (regardless of channel membership) ReadMessageFlags| Channel| Allows user to access messages that have been flagged RecreateChannel| Channel| Allows user to recreate a channel when it got deleted RemoveOwnChannelMembership| Channel| Allows user to leave the channel (remove own channel membership) SendCustomEvent| Channel| Allows user to send custom events to a channel SkipChannelCooldown| Channel| Allows user to bypass existing cooldown in a channel SkipMessageModeration| Channel| Allows user to bypass automatic message moderation TruncateChannel| Channel| Allows user to truncate a channel UpdateChannel| Channel| Allows user to update channel data UpdateChannelCooldown| Channel| Allows user to set and unset cooldown time for a channel (slow mode) UpdateChannelFrozen| Channel| Allows user to freeze and unfreeze a channel UpdateChannelMembers| Channel| Allows user to add, modify and remove channel members UploadAttachment| Channel| Allows user to upload files and images UseFrozenChannel| Channel| Allows user to send messages and reactions to a frozen channels DeleteMessage| Message| Allows user to delete a message RunMessageAction| Message| Allows user to run an action against a message UnblockMessage| Message| Allows user to unblock message blocked by automatic moderation UpdateMessage| Message| Allows user to update a message DeleteAttachment| Attachment| Allows user to delete uploaded files and images BanUser| User| Allows user to ban users FlagUser| User| Allows user to flag users MuteUser| User| Allows user to mute and unmute users SearchUser| User| Allows user to search for other users UpdateUser| User| Allows user to update users UpdateUserRole| User| Allows user to update user roles UpdateUserTeams| User| Allows user to update user teams CreateRestrictedVisibilityMessage| User| Allows user to create restricted visibility messages ReadRestrictedVisibilityMessage| User| Allows user to read restricted visibility messages BlockUser| Call| Allows user to Block and unblock users on calls CreateCall| Call| Allows user to creates a call CreateCallReaction| Call| Allows user to Add a reaction to a call DeleteRecording| Call| Allows user to Delete recording EndCall| Call| Allows user to terminates a call JoinBackstage| Call| Allows user to joins a call backstage JoinCall| Call| Allows user to joins a call JoinEndedCall| Call| Allows user to joins a call that was marked as ended ListRecordings| Call| Allows user to List recordings MuteUsers| Call| Allows user to MuteUsers PinCallTrack| Call| Allows user to Pin/Unpin a track for everyone in the call ReadCall| Call| Allows user to read a call ReadFlagReports| FlagReport| Allows user to read flag reports RemoveCallMember| Call| Allows user to Remove a participant Screenshare| Call| Allows user to Screenshare SendAudio| Call| Allows user to Send audio SendEvent| Call| Allows user to SendEvent SendVideo| Call| Allows user to Send video StartBroadcasting| Call| Allows user to Start broadcasting StartRecording| Call| Allows user to Start recording StartTranscription| Call| Allows user to Start transcription StopBroadcasting| Call| Allows user to Stop broadcasting StopRecording| Call| Allows user to Stop recording StopTranscription| Call| Allows user to Stop transcription UpdateCall| Call| Allows user to update the data for a call UpdateCallMember| Call| Allows user to Update a participant UpdateCallMemberRole| Call| Allows user to Update role for participants UpdateCallPermissions| Call| Allows user to UpdateCallPermissions UpdateCallSettings| Call| Allows user to updates settings of a call UpdateFlagReport| FlagReport| Allows user to update flag report ## Default Grants In tables below you will find default permission grants for each builtin channel type as well as `.app` permission scope. For each of of the above actions, there are different built in permissions depending on whether the object was created by the user or not. For example, users can be given permissions to `delete-attachment` which allows for deleting any message attachments, or they can be given permissions to `delete- attachment-owned` to restrict this to only attachments added by the current user. Every custom channel type that you create using CreateChannelType API endpoint, will have `messaging` scope grants by default. ### Scope `video:development` Permission ID| admin| user| guest| anonymous block-user| ✠| ✠| ✖️| ✖️ create-call| ✠| ✠| ✖️| ✖️ create-call-reaction| ✠| ✠| ✖️| ✖️ end-call| ✠| ✠| ✖️| ✖️ join-backstage| ✠| ✠| ✖️| ✖️ join-call| ✠| ✠| ✠| ✠join-ended-call| ✠| ✠| ✖️| ✖️ list-recordings| ✠| ✠| ✖️| ✖️ mute-users| ✠| ✠| ✖️| ✖️ pin-call-track| ✠| ✠| ✖️| ✖️ read-call| ✠| ✠| ✠| ✠remove-call-member| ✠| ✠| ✖️| ✖️ screenshare| ✠| ✠| ✖️| ✖️ send-audio| ✠| ✠| ✠| ✖️ send-event| ✠| ✠| ✠| ✖️ send-video| ✠| ✠| ✠| ✖️ start-broadcasting| ✠| ✠| ✖️| ✖️ start-recording| ✠| ✠| ✖️| ✖️ start-transcription| ✠| ✠| ✖️| ✖️ stop-broadcasting| ✠| ✠| ✖️| ✖️ stop-recording| ✠| ✠| ✖️| ✖️ stop-transcription| ✠| ✠| ✖️| ✖️ update-call| ✠| ✠| ✖️| ✖️ update-call-member| ✠| ✠| ✖️| ✖️ update-call-member-role| ✠| ✠| ✖️| ✖️ update-call-permissions| ✠| ✠| ✖️| ✖️ update-call-settings| ✠| ✠| ✖️| ✖️ ### Scope `video:livestream` Permission ID| admin| user| anonymous block-user| ✠| ✖️| ✖️ block-user-owner| ✖️| ✠| ✖️ create-call| ✠| ✠| ✖️ create-call-reaction| ✠| ✠| ✖️ end-call| ✠| ✖️| ✖️ end-call-owner| ✖️| ✠| ✖️ join-backstage| ✠| ✖️| ✖️ join-backstage-owner| ✖️| ✠| ✖️ join-call| ✠| ✠| ✠join-ended-call| ✠| ✖️| ✖️ join-ended-call-owner| ✖️| ✠| ✖️ mute-users| ✠| ✖️| ✖️ mute-users-owner| ✖️| ✠| ✖️ pin-call-track| ✠| ✖️| ✖️ pin-call-track-owner| ✖️| ✠| ✖️ read-call| ✠| ✠| ✠remove-call-member| ✠| ✖️| ✖️ remove-call-member-owner| ✖️| ✠| ✖️ screenshare| ✠| ✖️| ✖️ screenshare-owner| ✖️| ✠| ✖️ send-audio| ✠| ✖️| ✖️ send-audio-owner| ✖️| ✠| ✖️ send-event| ✠| ✠| ✖️ send-video| ✠| ✖️| ✖️ send-video-owner| ✖️| ✠| ✖️ start-broadcasting| ✠| ✖️| ✖️ start-broadcasting-owner| ✖️| ✠| ✖️ start-recording| ✠| ✖️| ✖️ start-recording-owner| ✖️| ✠| ✖️ stop-broadcasting| ✠| ✖️| ✖️ stop-broadcasting-owner| ✖️| ✠| ✖️ stop-recording| ✠| ✖️| ✖️ stop-recording-owner| ✖️| ✠| ✖️ update-call| ✠| ✖️| ✖️ update-call-member| ✠| ✖️| ✖️ update-call-member-owner| ✖️| ✠| ✖️ update-call-member-role| ✠| ✖️| ✖️ update-call-member-role-owner| ✖️| ✠| ✖️ update-call-owner| ✖️| ✠| ✖️ update-call-permissions| ✠| ✖️| ✖️ update-call-permissions-owner| ✖️| ✠| ✖️ update-call-settings| ✠| ✖️| ✖️ ### Scope `video:audio_room` Permission ID| admin| user| anonymous block-user| ✠| ✖️| ✖️ block-user-owner| ✖️| ✠| ✖️ create-call| ✠| ✠| ✖️ create-call-reaction| ✠| ✠| ✖️ end-call| ✠| ✖️| ✖️ end-call-owner| ✖️| ✠| ✖️ join-backstage| ✠| ✖️| ✖️ join-backstage-owner| ✖️| ✠| ✖️ join-call| ✠| ✠| ✠join-ended-call| ✠| ✖️| ✖️ join-ended-call-owner| ✖️| ✠| ✖️ mute-users| ✠| ✖️| ✖️ mute-users-owner| ✖️| ✠| ✖️ read-call| ✠| ✠| ✠remove-call-member| ✠| ✖️| ✖️ remove-call-member-owner| ✖️| ✠| ✖️ screenshare| ✠| ✖️| ✖️ send-audio| ✠| ✖️| ✖️ send-audio-owner| ✖️| ✠| ✖️ send-event| ✠| ✠| ✖️ start-broadcasting| ✠| ✖️| ✖️ start-broadcasting-owner| ✖️| ✠| ✖️ start-recording| ✠| ✖️| ✖️ start-recording-owner| ✖️| ✠| ✖️ start-transcription| ✠| ✖️| ✖️ start-transcription-owner| ✖️| ✠| ✖️ stop-broadcasting| ✠| ✖️| ✖️ stop-broadcasting-owner| ✖️| ✠| ✖️ stop-recording| ✠| ✖️| ✖️ stop-recording-owner| ✖️| ✠| ✖️ stop-transcription| ✠| ✖️| ✖️ stop-transcription-owner| ✖️| ✠| ✖️ update-call| ✠| ✖️| ✖️ update-call-member| ✠| ✖️| ✖️ update-call-member-owner| ✖️| ✠| ✖️ update-call-member-role| ✠| ✖️| ✖️ update-call-member-role-owner| ✖️| ✠| ✖️ update-call-owner| ✖️| ✠| ✖️ update-call-permissions| ✠| ✖️| ✖️ update-call-permissions-owner| ✖️| ✠| ✖️ update-call-settings| ✠| ✖️| ✖️ update-call-settings-owner| ✖️| ✠| ✖️ ### Scope `.app` Permission ID| admin| moderator| user| guest flag-user| ✠| ✠| ✠| ✠mute-user| ✠| ✠| ✠| ✠read-flag-reports| ✠| ✠| ✖️| ✖️ search-user| ✠| ✠| ✠| ✠update-flag-report| ✠| ✠| ✖️| ✖️ update-user-owner| ✠| ✠| ✠| ✠### Scope `video:default` Permission ID| admin| user| guest block-user| ✠| ✖️| ✖️ block-user-owner| ✖️| ✠| ✖️ create-call| ✠| ✠| ✖️ create-call-reaction| ✠| ✠| ✖️ delete-recording| ✠| ✖️| ✖️ end-call| ✠| ✠| ✖️ join-backstage| ✠| ✖️| ✖️ join-call| ✠| ✠| ✠join-ended-call| ✠| ✠| ✖️ list-recordings| ✠| ✠| ✖️ mute-users| ✠| ✖️| ✖️ mute-users-owner| ✖️| ✠| ✖️ pin-call-track| ✠| ✖️| ✖️ pin-call-track-owner| ✖️| ✠| ✖️ read-call| ✠| ✠| ✠remove-call-member| ✠| ✠| ✖️ screenshare| ✠| ✠| ✖️ send-audio| ✠| ✠| ✠send-event| ✠| ✠| ✠send-video| ✠| ✠| ✠start-broadcasting| ✠| ✠| ✖️ start-recording| ✠| ✠| ✖️ start-transcription| ✠| ✠| ✖️ stop-broadcasting| ✠| ✠| ✖️ stop-recording| ✠| ✠| ✖️ stop-transcription| ✠| ✠| ✖️ update-call| ✠| ✖️| ✖️ update-call-member| ✠| ✠| ✖️ update-call-member-role| ✠| ✖️| ✖️ update-call-owner| ✖️| ✠| ✖️ update-call-permissions| ✠| ✖️| ✖️ update-call-permissions-owner| ✖️| ✠| ✖️ update-call-settings| ✠| ✖️| ✖️ update-call-settings-owner| ✖️| ✠| ✖️ ### Scope `messaging` Permission ID| admin| moderator| user| channel_member| channel_moderator add-links| ✠| ✠| ✖️| ✠| ✠add-links-owner| ✖️| ✖️| ✠| ✖️| ✖️ ban-channel-member| ✠| ✠| ✖️| ✖️| ✠ban-user| ✠| ✠| ✖️| ✖️| ✖️ create-call| ✠| ✠| ✖️| ✠| ✠create-channel| ✠| ✠| ✠| ✖️| ✖️ create-message| ✠| ✠| ✖️| ✠| ✠create-message-owner| ✖️| ✖️| ✠| ✖️| ✖️ create-attachment| ✠| ✠| ✖️| ✠| ✠create-attachment-owner| ✖️| ✖️| ✠| ✖️| ✖️ create-mention| ✠| ✠| ✖️| ✠| ✠create-mention-owner| ✖️| ✖️| ✠| ✖️| ✖️ create-reaction| ✠| ✠| ✖️| ✠| ✠create-reaction-owner| ✖️| ✖️| ✠| ✖️| ✖️ create-system-message| ✠| ✠| ✖️| ✖️| ✠delete-attachment| ✠| ✠| ✖️| ✖️| ✠delete-attachment-owner| ✖️| ✖️| ✠| ✖️| ✖️ delete-channel| ✠| ✖️| ✖️| ✖️| ✖️ delete-channel-owner| ✖️| ✠| ✠| ✖️| ✖️ delete-message| ✠| ✠| ✖️| ✖️| ✠delete-message-owner| ✖️| ✖️| ✠| ✖️| ✖️ delete-reaction| ✠| ✠| ✖️| ✖️| ✠delete-reaction-owner| ✖️| ✖️| ✠| ✖️| ✖️ flag-message| ✠| ✠| ✖️| ✠| ✠flag-message-owner| ✖️| ✖️| ✠| ✖️| ✖️ join-call| ✠| ✠| ✖️| ✠| ✠mute-channel| ✠| ✠| ✖️| ✠| ✠mute-channel-owner| ✖️| ✖️| ✠| ✖️| ✖️ pin-message| ✠| ✠| ✖️| ✠| ✠pin-message-owner| ✖️| ✖️| ✠| ✖️| ✖️ read-channel| ✠| ✠| ✖️| ✠| ✠read-channel-members| ✠| ✠| ✖️| ✠| ✠read-channel-members-owner| ✖️| ✖️| ✠| ✖️| ✖️ read-channel-owner| ✖️| ✖️| ✠| ✖️| ✖️ read-message-flags| ✠| ✠| ✖️| ✖️| ✠recreate-channel| ✠| ✖️| ✖️| ✖️| ✖️ recreate-channel-owner| ✖️| ✠| ✠| ✖️| ✖️ remove-own-channel-membership| ✠| ✠| ✖️| ✠| ✠remove-own-channel-membership-owner| ✖️| ✖️| ✠| ✖️| ✖️ run-message-action| ✠| ✠| ✖️| ✠| ✠run-message-action-owner| ✖️| ✖️| ✠| ✖️| ✖️ send-custom-event| ✠| ✠| ✖️| ✠| ✠send-custom-event-owner| ✖️| ✖️| ✠| ✖️| ✖️ skip-channel-cooldown| ✠| ✠| ✖️| ✖️| ✠skip-message-moderation| ✠| ✠| ✖️| ✖️| ✠truncate-channel| ✠| ✖️| ✖️| ✖️| ✖️ truncate-channel-owner| ✖️| ✠| ✠| ✖️| ✖️ unblock-message| ✠| ✠| ✖️| ✖️| ✠update-channel| ✠| ✠| ✖️| ✖️| ✠update-channel-cooldown| ✠| ✠| ✖️| ✖️| ✠update-channel-frozen| ✠| ✠| ✖️| ✖️| ✠update-channel-members| ✠| ✠| ✖️| ✖️| ✠update-channel-members-owner| ✖️| ✖️| ✠| ✖️| ✖️ update-channel-owner| ✖️| ✖️| ✠| ✖️| ✖️ update-message| ✠| ✠| ✖️| ✖️| ✠update-message-owner| ✖️| ✖️| ✠| ✖️| ✖️ upload-attachment| ✠| ✠| ✖️| ✠| ✠upload-attachment-owner| ✖️| ✖️| ✠| ✖️| ✖️ ### Scope `livestream` Permission ID| admin| moderator| user| channel_moderator| guest| anonymous add-links| ✠| ✠| ✠| ✖️| ✖️| ✖️ ban-channel-member| ✠| ✠| ✖️| ✠| ✖️| ✖️ ban-user| ✠| ✠| ✖️| ✖️| ✖️| ✖️ create-call| ✠| ✠| ✖️| ✠| ✖️| ✖️ create-channel| ✠| ✠| ✠| ✖️| ✖️| ✖️ create-message| ✠| ✠| ✠| ✖️| ✖️| ✖️ create-attachment| ✠| ✠| ✠| ✖️| ✖️| ✖️ create-mention| ✠| ✠| ✠| ✖️| ✖️| ✖️ create-reaction| ✠| ✠| ✠| ✖️| ✖️| ✖️ create-system-message| ✠| ✠| ✖️| ✠| ✖️| ✖️ delete-attachment| ✠| ✠| ✖️| ✠| ✖️| ✖️ delete-attachment-owner| ✖️| ✖️| ✠| ✖️| ✖️| ✖️ delete-channel| ✠| ✖️| ✖️| ✖️| ✖️| ✖️ delete-message| ✠| ✠| ✖️| ✠| ✖️| ✖️ delete-message-owner| ✖️| ✖️| ✠| ✖️| ✖️| ✖️ delete-reaction| ✠| ✠| ✖️| ✠| ✖️| ✖️ delete-reaction-owner| ✖️| ✖️| ✠| ✖️| ✖️| ✖️ flag-message| ✠| ✠| ✠| ✖️| ✠| ✖️ join-call| ✠| ✠| ✠| ✖️| ✠| ✠mute-channel| ✠| ✠| ✠| ✖️| ✠| ✖️ pin-message| ✠| ✠| ✖️| ✠| ✖️| ✖️ pin-message-owner| ✖️| ✖️| ✠| ✖️| ✖️| ✖️ read-channel| ✠| ✠| ✠| ✖️| ✠| ✠read-channel-members| ✠| ✠| ✠| ✖️| ✠| ✠read-message-flags| ✠| ✠| ✖️| ✠| ✖️| ✖️ recreate-channel| ✠| ✖️| ✖️| ✖️| ✖️| ✖️ remove-own-channel-membership| ✠| ✖️| ✖️| ✖️| ✖️| ✖️ run-message-action| ✠| ✠| ✠| ✖️| ✖️| ✖️ send-custom-event| ✠| ✠| ✠| ✖️| ✖️| ✖️ skip-channel-cooldown| ✠| ✠| ✖️| ✠| ✖️| ✖️ skip-message-moderation| ✠| ✠| ✖️| ✠| ✖️| ✖️ truncate-channel| ✠| ✖️| ✖️| ✖️| ✖️| ✖️ unblock-message| ✠| ✠| ✖️| ✠| ✖️| ✖️ update-channel| ✠| ✖️| ✖️| ✖️| ✖️| ✖️ update-channel-cooldown| ✠| ✠| ✖️| ✠| ✖️| ✖️ update-channel-frozen| ✠| ✠| ✖️| ✠| ✖️| ✖️ update-channel-members| ✠| ✖️| ✖️| ✖️| ✖️| ✖️ update-message| ✠| ✠| ✖️| ✠| ✖️| ✖️ update-message-owner| ✖️| ✖️| ✠| ✖️| ✖️| ✖️ upload-attachment| ✠| ✠| ✠| ✖️| ✖️| ✖️ ### Scope `team` Permission ID| admin| moderator| user| channel_member| channel_moderator add-links| ✠| ✠| ✖️| ✠| ✠add-links-owner| ✖️| ✖️| ✠| ✖️| ✖️ ban-channel-member| ✠| ✠| ✖️| ✖️| ✠ban-user| ✠| ✠| ✖️| ✖️| ✖️ create-call| ✠| ✠| ✖️| ✠| ✠create-channel| ✠| ✠| ✠| ✖️| ✖️ create-message| ✠| ✠| ✖️| ✠| ✠create-message-owner| ✖️| ✖️| ✠| ✖️| ✖️ create-attachment| ✠| ✠| ✖️| ✠| ✠create-attachment-owner| ✖️| ✖️| ✠| ✖️| ✖️ create-mention| ✠| ✠| ✖️| ✠| ✠create-mention-owner| ✖️| ✖️| ✠| ✖️| ✖️ create-reaction| ✠| ✠| ✖️| ✠| ✠create-reaction-owner| ✖️| ✖️| ✠| ✖️| ✖️ create-system-message| ✠| ✠| ✖️| ✖️| ✠delete-attachment| ✠| ✠| ✖️| ✖️| ✠delete-attachment-owner| ✖️| ✖️| ✠| ✖️| ✖️ delete-channel| ✠| ✖️| ✖️| ✖️| ✖️ delete-channel-owner| ✖️| ✠| ✠| ✖️| ✖️ delete-message| ✠| ✠| ✖️| ✖️| ✠delete-message-owner| ✖️| ✖️| ✠| ✖️| ✖️ delete-reaction| ✠| ✠| ✖️| ✖️| ✠delete-reaction-owner| ✖️| ✖️| ✠| ✖️| ✖️ flag-message| ✠| ✠| ✖️| ✠| ✠flag-message-owner| ✖️| ✖️| ✠| ✖️| ✖️ join-call| ✠| ✠| ✖️| ✠| ✠mute-channel| ✠| ✠| ✖️| ✠| ✠mute-channel-owner| ✖️| ✖️| ✠| ✖️| ✖️ pin-message| ✠| ✠| ✖️| ✠| ✠pin-message-owner| ✖️| ✖️| ✠| ✖️| ✖️ read-channel| ✠| ✠| ✖️| ✠| ✠read-channel-members| ✠| ✠| ✖️| ✠| ✠read-channel-members-owner| ✖️| ✖️| ✠| ✖️| ✖️ read-channel-owner| ✖️| ✖️| ✠| ✖️| ✖️ read-message-flags| ✠| ✠| ✖️| ✖️| ✠recreate-channel| ✠| ✖️| ✖️| ✖️| ✖️ recreate-channel-owner| ✖️| ✠| ✠| ✖️| ✖️ remove-own-channel-membership| ✠| ✠| ✖️| ✠| ✠remove-own-channel-membership-owner| ✖️| ✖️| ✠| ✖️| ✖️ run-message-action| ✠| ✠| ✖️| ✠| ✠run-message-action-owner| ✖️| ✖️| ✠| ✖️| ✖️ send-custom-event| ✠| ✠| ✖️| ✠| ✠send-custom-event-owner| ✖️| ✖️| ✠| ✖️| ✖️ skip-channel-cooldown| ✠| ✠| ✖️| ✖️| ✠skip-message-moderation| ✠| ✠| ✖️| ✖️| ✠truncate-channel| ✠| ✖️| ✖️| ✖️| ✖️ truncate-channel-owner| ✖️| ✠| ✠| ✖️| ✖️ unblock-message| ✠| ✠| ✖️| ✖️| ✠update-channel| ✠| ✠| ✖️| ✖️| ✠update-channel-cooldown| ✠| ✠| ✖️| ✖️| ✠update-channel-frozen| ✠| ✠| ✖️| ✖️| ✠update-channel-members| ✠| ✠| ✖️| ✖️| ✠update-channel-members-owner| ✖️| ✖️| ✠| ✖️| ✖️ update-channel-owner| ✖️| ✖️| ✠| ✖️| ✖️ update-message| ✠| ✠| ✖️| ✖️| ✠update-message-owner| ✖️| ✖️| ✠| ✖️| ✖️ upload-attachment| ✠| ✠| ✖️| ✠| ✠upload-attachment-owner| ✖️| ✖️| ✠| ✖️| ✖️ ### Scope `commerce` Permission ID| admin| moderator| user| channel_member| channel_moderator| guest add-links| ✠| ✠| ✖️| ✠| ✠| ✠add-links-owner| ✖️| ✖️| ✠| ✖️| ✖️| ✖️ ban-channel-member| ✠| ✠| ✖️| ✖️| ✠| ✖️ ban-user| ✠| ✠| ✖️| ✖️| ✖️| ✖️ create-call| ✠| ✠| ✖️| ✖️| ✠| ✖️ create-channel| ✠| ✠| ✖️| ✖️| ✖️| ✠create-message| ✠| ✠| ✖️| ✠| ✠| ✖️ create-message-owner| ✖️| ✖️| ✠| ✖️| ✖️| ✖️ create-attachment| ✠| ✠| ✖️| ✠| ✠| ✖️ create-attachment-owner| ✖️| ✖️| ✠| ✖️| ✖️| ✖️ create-mention| ✠| ✠| ✖️| ✠| ✠| ✖️ create-mention-owner| ✖️| ✖️| ✠| ✖️| ✖️| ✖️ create-reaction| ✠| ✠| ✖️| ✠| ✠| ✖️ create-reaction-owner| ✖️| ✖️| ✠| ✖️| ✖️| ✖️ create-system-message| ✠| ✠| ✖️| ✖️| ✠| ✖️ delete-attachment| ✠| ✠| ✖️| ✖️| ✠| ✖️ delete-attachment-owner| ✖️| ✖️| ✠| ✖️| ✖️| ✠delete-channel| ✠| ✖️| ✖️| ✖️| ✖️| ✖️ delete-message| ✠| ✠| ✖️| ✖️| ✠| ✖️ delete-message-owner| ✖️| ✖️| ✠| ✖️| ✖️| ✠delete-reaction| ✠| ✠| ✖️| ✖️| ✠| ✖️ delete-reaction-owner| ✖️| ✖️| ✠| ✖️| ✖️| ✠flag-message| ✠| ✠| ✖️| ✠| ✠| ✖️ flag-message-owner| ✖️| ✖️| ✠| ✖️| ✖️| ✠join-call| ✠| ✠| ✖️| ✠| ✠| ✖️ mute-channel| ✠| ✠| ✖️| ✠| ✠| ✖️ mute-channel-owner| ✖️| ✖️| ✠| ✖️| ✖️| ✠pin-message| ✠| ✠| ✖️| ✖️| ✠| ✖️ pin-message-owner| ✖️| ✖️| ✠| ✖️| ✖️| ✠read-channel| ✠| ✠| ✖️| ✠| ✠| ✖️ read-channel-members| ✠| ✠| ✖️| ✠| ✠| ✖️ read-channel-members-owner| ✖️| ✖️| ✠| ✖️| ✖️| ✠read-channel-owner| ✖️| ✖️| ✠| ✖️| ✖️| ✠read-message-flags| ✠| ✠| ✖️| ✖️| ✠| ✖️ recreate-channel| ✠| ✖️| ✖️| ✖️| ✖️| ✖️ remove-own-channel-membership| ✠| ✠| ✖️| ✠| ✠| ✖️ remove-own-channel-membership-owner| ✖️| ✖️| ✠| ✖️| ✖️| ✖️ run-message-action| ✠| ✠| ✖️| ✠| ✠| ✖️ run-message-action-owner| ✖️| ✖️| ✠| ✖️| ✖️| ✖️ send-custom-event| ✠| ✠| ✖️| ✠| ✠| ✖️ send-custom-event-owner| ✖️| ✖️| ✠| ✖️| ✖️| ✖️ skip-channel-cooldown| ✠| ✠| ✖️| ✖️| ✠| ✖️ skip-message-moderation| ✠| ✠| ✖️| ✖️| ✠| ✖️ truncate-channel| ✠| ✖️| ✖️| ✖️| ✖️| ✖️ unblock-message| ✠| ✠| ✖️| ✖️| ✠| ✖️ update-channel| ✠| ✠| ✖️| ✖️| ✠| ✖️ update-channel-cooldown| ✠| ✠| ✖️| ✖️| ✠| ✖️ update-channel-frozen| ✠| ✠| ✖️| ✖️| ✠| ✖️ update-channel-members| ✠| ✠| ✖️| ✖️| ✠| ✖️ update-channel-members-owner| ✖️| ✖️| ✠| ✖️| ✖️| ✠update-message| ✠| ✠| ✖️| ✖️| ✠| ✖️ update-message-owner| ✖️| ✖️| ✠| ✖️| ✖️| ✠upload-attachment| ✠| ✠| ✖️| ✠| ✠| ✠upload-attachment-owner| ✖️| ✖️| ✠| ✖️| ✖️| ✖️ ### Scope `gaming` Permission ID| admin| moderator| user| channel_member| channel_moderator add-links| ✠| ✠| ✖️| ✠| ✠add-links-owner| ✖️| ✖️| ✠| ✖️| ✖️ ban-channel-member| ✠| ✠| ✖️| ✖️| ✠ban-user| ✠| ✠| ✖️| ✖️| ✖️ create-call| ✠| ✠| ✖️| ✠| ✠create-channel| ✠| ✖️| ✖️| ✖️| ✖️ create-message| ✠| ✠| ✖️| ✠| ✠create-message-owner| ✖️| ✖️| ✠| ✖️| ✖️ create-attachment| ✠| ✠| ✖️| ✠| ✠create-attachment-owner| ✖️| ✖️| ✠| ✖️| ✖️ create-mention| ✠| ✠| ✖️| ✠| ✠create-mention-owner| ✖️| ✖️| ✠| ✖️| ✖️ create-reaction| ✠| ✠| ✖️| ✠| ✠create-reaction-owner| ✖️| ✖️| ✠| ✖️| ✖️ create-system-message| ✠| ✠| ✖️| ✖️| ✠delete-attachment| ✠| ✠| ✖️| ✖️| ✠delete-attachment-owner| ✖️| ✖️| ✠| ✖️| ✖️ delete-channel| ✠| ✖️| ✖️| ✖️| ✖️ delete-message| ✠| ✠| ✖️| ✖️| ✠delete-message-owner| ✖️| ✖️| ✠| ✖️| ✖️ delete-reaction| ✠| ✠| ✖️| ✖️| ✠delete-reaction-owner| ✖️| ✖️| ✠| ✖️| ✖️ flag-message| ✠| ✠| ✖️| ✠| ✠flag-message-owner| ✖️| ✖️| ✠| ✖️| ✖️ join-call| ✠| ✠| ✖️| ✠| ✠mute-channel| ✠| ✠| ✖️| ✠| ✠mute-channel-owner| ✖️| ✖️| ✠| ✖️| ✖️ pin-message| ✠| ✠| ✖️| ✖️| ✠read-channel| ✠| ✠| ✖️| ✠| ✠read-channel-members| ✠| ✠| ✖️| ✠| ✠read-channel-members-owner| ✖️| ✖️| ✠| ✖️| ✖️ read-channel-owner| ✖️| ✖️| ✠| ✖️| ✖️ read-message-flags| ✠| ✠| ✖️| ✖️| ✠recreate-channel| ✠| ✖️| ✖️| ✖️| ✖️ remove-own-channel-membership| ✠| ✠| ✖️| ✠| ✠remove-own-channel-membership-owner| ✖️| ✖️| ✠| ✖️| ✖️ run-message-action| ✠| ✠| ✖️| ✠| ✠run-message-action-owner| ✖️| ✖️| ✠| ✖️| ✖️ send-custom-event| ✠| ✠| ✖️| ✠| ✠send-custom-event-owner| ✖️| ✖️| ✠| ✖️| ✖️ skip-channel-cooldown| ✠| ✠| ✖️| ✖️| ✠skip-message-moderation| ✠| ✠| ✖️| ✖️| ✠truncate-channel| ✠| ✖️| ✖️| ✖️| ✖️ unblock-message| ✠| ✠| ✖️| ✖️| ✠update-channel| ✠| ✖️| ✖️| ✖️| ✖️ update-channel-cooldown| ✠| ✠| ✖️| ✖️| ✠update-channel-frozen| ✠| ✠| ✖️| ✖️| ✠update-channel-members| ✠| ✖️| ✖️| ✖️| ✖️ update-message| ✠| ✠| ✖️| ✖️| ✠update-message-owner| ✖️| ✖️| ✠| ✖️| ✖️ upload-attachment| ✠| ✠| ✖️| ✠| ✠upload-attachment-owner| ✖️| ✖️| ✠| ✖️| ✖️ ## Multi-Tenant Default Grants In tables below you will find default permission grants for builtin roles that designed for multi-tenant applications. They are useful for [multi-tenant applications](/chat/docs/react/multi_tenant_chat/) only. By default, for multi-tenant applications, all objects (users, channels, and messages) must belong to the same team to be able to interact. These multi- tenant permissions enable overriding that behavior, so that certain users can have permissions to interact with objects on any team ### Scope `video:livestream` Permission ID ### Scope `video:development` Permission ID ### Scope `.app` Permission ID| global_moderator| global_admin flag-user-any-team| ✠| ✠mute-user-any-team| ✠| ✠read-flag-reports-any-team| ✠| ✠search-user-any-team| ✠| ✠update-flag-report-any-team| ✠| ✠update-user-owner| ✠| ✠### Scope `video:audio_room` Permission ID ### Scope `video:default` Permission ID ### Scope `messaging` Permission ID| global_moderator| global_admin add-links-any-team| ✠| ✠ban-channel-member-any-team| ✠| ✠ban-user-any-team| ✠| ✠create-call-any-team| ✠| ✠create-channel-any-team| ✠| ✠create-message-any-team| ✠| ✠create-attachment-any-team| ✠| ✠create-mention-any-team| ✠| ✠create-reaction-any-team| ✠| ✠create-system-message-any-team| ✠| ✠delete-attachment-any-team| ✠| ✠delete-channel-any-team| ✖️| ✠delete-channel-owner-any-team| ✠| ✖️ delete-message-any-team| ✠| ✠delete-reaction-any-team| ✠| ✠flag-message-any-team| ✠| ✠join-call-any-team| ✠| ✠mute-channel-any-team| ✠| ✠pin-message-any-team| ✠| ✠read-channel-any-team| ✠| ✠read-channel-members-any-team| ✠| ✠read-message-flags-any-team| ✠| ✠recreate-channel-any-team| ✖️| ✠recreate-channel-owner-any-team| ✠| ✖️ remove-own-channel-membership-any-team| ✠| ✠run-message-action-any-team| ✠| ✠send-custom-event-any-team| ✠| ✠skip-channel-cooldown-any-team| ✠| ✠skip-message-moderation-any-team| ✠| ✠truncate-channel-any-team| ✖️| ✠truncate-channel-owner-any-team| ✠| ✖️ unblock-message-any-team| ✠| ✠update-channel-any-team| ✠| ✠update-channel-cooldown-any-team| ✠| ✠update-channel-frozen-any-team| ✠| ✠update-channel-members-any-team| ✠| ✠update-message-any-team| ✠| ✠upload-attachment-any-team| ✠| ✠### Scope `livestream` Permission ID| global_moderator| global_admin add-links-any-team| ✠| ✠ban-channel-member-any-team| ✠| ✠ban-user-any-team| ✠| ✠create-call-any-team| ✠| ✠create-channel-any-team| ✠| ✠create-message-any-team| ✠| ✠create-attachment-any-team| ✠| ✠create-mention-any-team| ✠| ✠create-reaction-any-team| ✠| ✠create-system-message-any-team| ✠| ✠delete-attachment-any-team| ✠| ✠delete-channel-any-team| ✖️| ✠delete-message-any-team| ✠| ✠delete-reaction-any-team| ✠| ✠flag-message-any-team| ✠| ✠join-call-any-team| ✠| ✠mute-channel-any-team| ✠| ✠pin-message-any-team| ✠| ✠read-channel-any-team| ✠| ✠read-channel-members-any-team| ✠| ✠read-message-flags-any-team| ✠| ✠recreate-channel-any-team| ✖️| ✠remove-own-channel-membership-any-team| ✖️| ✠run-message-action-any-team| ✠| ✠send-custom-event-any-team| ✠| ✠skip-channel-cooldown-any-team| ✠| ✠skip-message-moderation-any-team| ✠| ✠truncate-channel-any-team| ✖️| ✠unblock-message-any-team| ✠| ✠update-channel-any-team| ✖️| ✠update-channel-cooldown-any-team| ✠| ✠update-channel-frozen-any-team| ✠| ✠update-channel-members-any-team| ✖️| ✠update-message-any-team| ✠| ✠upload-attachment-any-team| ✠| ✠### Scope `team` Permission ID| global_moderator| global_admin add-links-any-team| ✠| ✠ban-channel-member-any-team| ✠| ✠ban-user-any-team| ✠| ✠create-call-any-team| ✠| ✠create-channel-any-team| ✠| ✠create-message-any-team| ✠| ✠create-attachment-any-team| ✠| ✠create-mention-any-team| ✠| ✠create-reaction-any-team| ✠| ✠create-system-message-any-team| ✠| ✠delete-attachment-any-team| ✠| ✠delete-channel-any-team| ✖️| ✠delete-channel-owner-any-team| ✠| ✖️ delete-message-any-team| ✠| ✠delete-reaction-any-team| ✠| ✠flag-message-any-team| ✠| ✠join-call-any-team| ✠| ✠mute-channel-any-team| ✠| ✠pin-message-any-team| ✠| ✠read-channel-any-team| ✠| ✠read-channel-members-any-team| ✠| ✠read-message-flags-any-team| ✠| ✠recreate-channel-any-team| ✖️| ✠recreate-channel-owner-any-team| ✠| ✖️ remove-own-channel-membership-any-team| ✠| ✠run-message-action-any-team| ✠| ✠send-custom-event-any-team| ✠| ✠skip-channel-cooldown-any-team| ✠| ✠skip-message-moderation-any-team| ✠| ✠truncate-channel-any-team| ✖️| ✠truncate-channel-owner-any-team| ✠| ✖️ unblock-message-any-team| ✠| ✠update-channel-any-team| ✠| ✠update-channel-cooldown-any-team| ✠| ✠update-channel-frozen-any-team| ✠| ✠update-channel-members-any-team| ✠| ✠update-message-any-team| ✠| ✠upload-attachment-any-team| ✠| ✠### Scope `commerce` Permission ID| global_moderator| global_admin add-links-any-team| ✠| ✠ban-channel-member-any-team| ✠| ✠ban-user-any-team| ✠| ✠create-call-any-team| ✠| ✠create-channel-any-team| ✠| ✠create-message-any-team| ✠| ✠create-attachment-any-team| ✠| ✠create-mention-any-team| ✠| ✠create-reaction-any-team| ✠| ✠create-system-message-any-team| ✠| ✠delete-attachment-any-team| ✠| ✠delete-channel-any-team| ✖️| ✠delete-message-any-team| ✠| ✠delete-reaction-any-team| ✠| ✠flag-message-any-team| ✠| ✠join-call-any-team| ✠| ✠mute-channel-any-team| ✠| ✠pin-message-any-team| ✠| ✠read-channel-any-team| ✠| ✠read-channel-members-any-team| ✠| ✠read-message-flags-any-team| ✠| ✠recreate-channel-any-team| ✖️| ✠remove-own-channel-membership-any-team| ✠| ✠run-message-action-any-team| ✠| ✠send-custom-event-any-team| ✠| ✠skip-channel-cooldown-any-team| ✠| ✠skip-message-moderation-any-team| ✠| ✠truncate-channel-any-team| ✖️| ✠unblock-message-any-team| ✠| ✠update-channel-any-team| ✠| ✠update-channel-cooldown-any-team| ✠| ✠update-channel-frozen-any-team| ✠| ✠update-channel-members-any-team| ✠| ✠update-message-any-team| ✠| ✠upload-attachment-any-team| ✠| ✠### Scope `gaming` Permission ID| global_moderator| global_admin add-links-any-team| ✠| ✠ban-channel-member-any-team| ✠| ✠ban-user-any-team| ✠| ✠create-call-any-team| ✠| ✠create-channel-any-team| ✖️| ✠create-message-any-team| ✠| ✠create-attachment-any-team| ✠| ✠create-mention-any-team| ✠| ✠create-reaction-any-team| ✠| ✠create-system-message-any-team| ✠| ✠delete-attachment-any-team| ✠| ✠delete-channel-any-team| ✖️| ✠delete-message-any-team| ✠| ✠delete-reaction-any-team| ✠| ✠flag-message-any-team| ✠| ✠join-call-any-team| ✠| ✠mute-channel-any-team| ✠| ✠pin-message-any-team| ✠| ✠read-channel-any-team| ✠| ✠read-channel-members-any-team| ✠| ✠read-message-flags-any-team| ✠| ✠recreate-channel-any-team| ✖️| ✠remove-own-channel-membership-any-team| ✠| ✠run-message-action-any-team| ✠| ✠send-custom-event-any-team| ✠| ✠skip-channel-cooldown-any-team| ✠| ✠skip-message-moderation-any-team| ✠| ✠truncate-channel-any-team| ✖️| ✠unblock-message-any-team| ✠| ✠update-channel-any-team| ✖️| ✠update-channel-cooldown-any-team| ✠| ✠update-channel-frozen-any-team| ✠| ✠update-channel-members-any-team| ✖️| ✠update-message-any-team| ✠| ✠upload-attachment-any-team| ✠| ✠Did you find this page helpful? It was helpful It was not helpful I have feedback Submit Thank you for the feedback. An error has occurred. Please refresh the page and try again. [PreviousMulti-Tenant & Teams](/chat/docs/react/multi_tenant_chat/)[NextChannel Setting Overwrites](/chat/docs/react/channel-level_settings/) © Stream.io, Inc. All Rights Reserved. [Chat Messaging](https://getstream.io/chat/)[Video & Audio](https://getstream.io/video/)[Activity Feeds](https://getstream.io/activity- feeds/)[Moderation](https://getstream.io/moderation/) * Copy LLM prompt * [ View as markdown](https://getstream.io/chat/docs/react/permissions_reference.md) * * [ Open in ChatGPT](https://chatgpt.com/?q=I'm working with the Stream Chat React SDK and would like to ask questions about this documentation page: https://getstream.io/chat/docs/react/permissions_reference.md) * [ Open in Claude](https://claude.ai/new?q=I'm working with the Stream Chat React SDK and would like to ask questions about this documentation page: https://getstream.io/chat/docs/react/permissions_reference.md) * [ Open in Gemini](https://gemini.google.com/app?query=I'm working with the Stream Chat React SDK and would like to ask questions about this documentation page: https://getstream.io/chat/docs/react/permissions_reference.md) * [ Open in Grok](https://x.com/i/grok?text=I'm working with the Stream Chat React SDK and would like to ask questions about this documentation page: https://getstream.io/chat/docs/react/permissions_reference.md) * [ Open in Perplexity](https://www.perplexity.ai/search/new?q=I'm working with the Stream Chat React SDK and would like to ask questions about this documentation page: https://getstream.io/chat/docs/react/permissions_reference.md) On this page: * Actions * Default Grants * Scope video:development * Scope video:livestream * Scope video:audio_room * Scope .app * Scope video:default * Scope messaging * Scope livestream * Scope team * Scope commerce * Scope gaming * Multi-Tenant Default Grants * Scope video:livestream * Scope video:development * Scope .app * Scope video:audio_room * Scope video:default * Scope messaging * Scope livestream * Scope team * Scope commerce * Scope gaming Is this helpful? Thank you . An error has occurred. --- # Stream.io Documentation # Source: https://getstream.io/chat/docs/sdk/react/guides/ai-integrations/ * [Chat Messaging](/chat/) / * [Docs](/chat/docs/) / * [React](/chat/docs/sdk/react/) / * [AI Integrations](/chat/docs/sdk/react/guides/ai-integrations/) # AI Integrations The AI UI components are designed specifically for AI-first applications written in React. When paired with our real-time [Chat API](https://getstream.io/chat/), it makes integrating with and rendering responses from LLM providers such as ChatGPT, Gemini, Anthropic or any custom backend easier by providing rich with out-of-the-box components able to render markdown, syntax highlighted code blocks, tables, thinking indicators, charts and so on. This library includes the following components which assist with this task: * `StreamingMessage` \- a component that is able to render text, markdown and code in real-time, using a typewriter, character-by-character animation, similar to ChatGPT * `AIMessageComposer` \- a fully featured prompt composer with attachments and speech input * `AIStateIndicator` \- a component that is useful to keep the user’s attention while the AI generates an answer * `SpeechToTextButton` \- a reusable button that records voice input and streams the recognized transcript back into your UI Our team plans to keep iterating and adding more components over time. If there’s a component you use every day in your apps and would like to see added, please open an issue and we will take it into consideration. You can find a complete ChatGPT clone sample that uses these components [here](https://github.com/GetStream/chat-ai-samples/tree/main/react-native). ## Installation The `@stream-io/chat-react-ai` SDK is available on NPM. To install it and its peer dependencies, you may run the following command: yarnpnpmnpm yarn add @stream-io/chat-react-ai pnpm add @stream-io/chat-react-ai npm i @stream-io/chat-react-ai ## Components All of the components listed below are designed to work seamlessly with our existing [React Chat SDK](https://getstream.io/chat/react-chat/tutorial/). Our [developer guide](https://getstream.io/chat/solutions/ai-integration/) explains how to get started building AI integrations with Stream. ### `StreamingMessage` The `StreamingMessage` is a component that can render markdown content efficiently. It has code syntax highlighting, supporting all the major languages. It can render most of the standard markdown content, such as tables, inline code, headings, lists etc. Under the hood, it implements a letter-by-letter typewriter animation with a character queue, similar to ChatGPT. Name| Type| Required| Description `text`| `string`| yes| The text we want to pass as markdown. `letterIntervalMs`| `number`| no| A number signifying the interval at which the typewriter animation is going to render characters. Defaults to `30` `renderingLetterCount`| `number`| no| A number signifying the number of letters that are going to be rendered per tick of the interval during the typewriter animation. Defaults to `2` If you need to build your own `StreamingMessage` \- it’s as simple as importing `AIMarkdown` component and `useMessageTextStreaming` hook and combining them together. #### Example Provided below is an example of how to use the component. const markdownText = ``` # Heading some text ## Another heading ```; ; ### `AIStateIndicator` The `AIStateIndicator` is used to represent different states of the LLM, such as `Thinking`, `Checking External Sources` and so on, depending on the states you’ve defined on your backend. You can provide your own text or pass none to let the component pick one of the pre-defined phrases. To change the phrase pass any new value to a `key` prop which resets component’s internal state. Name| Type| Required| Description `text`| `string`| no| The text we want to be displayed inside of the component. #### Example { (aiState === "thinking" || aiState === "generating") && ( ); } // or { (aiState === "thinking" || aiState === "generating") && ( ); } ### `AIMessageComposer` The `AIMessageComposer` gives users a complete message composer component with support for text input, file attachments, speech-to-text, and model selection. Name| Type| Required| Description `resetAttachmentsOnSelect`| `boolean`| no| Resets file input after selection. Defaults to `true`. `nameMapping`| `{ message?: string; attachments?: string }`| no| Maps custom input names to internal state. By default, the composer expects inputs named `message` (for text) and `attachments` (for files). Use this prop to map different names to these internal keys. `onSubmit`| `(e: FormEvent) => void`| no| Form submission handler. `onChange`| `(e: FormEvent) => void`| no| Form change handler. | `...HTMLFormElement props`| no| Supports all standard HTML form element props. #### Sub-components * **`AIMessageComposer.FileInput`** \- File input button for attaching files. Supports multiple file selection. * **`AIMessageComposer.TextInput`** \- Text input field for typing messages. Automatically syncs with composer state. * **`AIMessageComposer.SpeechToTextButton`** \- Button to toggle speech-to-text input using the Web Speech API. * **`AIMessageComposer.SubmitButton`** \- Submit button for sending the message. * **`AIMessageComposer.ModelSelect`** \- Dropdown for selecting AI models. Customizable via `options` prop. * **`AIMessageComposer.AttachmentPreview`** \- Preview container for attached files. * **`AIMessageComposer.AttachmentPreview.Item`** \- Preview item component, renders a different look for file types that begin with `image/`. #### Example import { AIMessageComposer } from "@stream-io/chat-react-ai"; function ChatComposer({ attachments }: ChatComposerProps) { const handleSubmit = (e) => { e.preventDefault(); const formData = new FormData(e.target); // Handle submission }; return ( {attachments.map((attachment) => ( ))} ); } > [!NOTE] Some default input components come with default `name` attributes > (`TextInput` defaults to `"message"`, `FileInput` defaults to > `"attachments"`). You can override these names via props, and use the > `nameMapping` prop to tell the composer how to map your custom names to its > internal state. ### `SpeechToTextButton` The `SpeechToTextButton` is a button component for voice input using the Web Speech API. It provides a simple interface for converting speech to text with built-in microphone icon and listening state visualization. Name| Type| Required| Description `options`| `UseSpeechToTextOptions`| no| Options for speech recognition (see `useSpeechToText` hook documentation for available options like `lang`, `continuous`, etc.). | `...HTMLButtonElement props`| no| Supports all standard HTML button element props. #### Example import { SpeechToTextButton } from "@stream-io/chat-react-ai"; function VoiceInputButton() { return ( ); } > [!NOTE] When used within an `AIMessageComposer`, the button automatically > updates the composer’s text input. When used standalone, you can control > the behavior through the `speechToTextOptions.onTranscript` callback. ### AI States As per our current specification, the AI is allowed several states that are related to its current progress in producing a response. You may find the currently available states here: . Provided below is a brief explanation of what each state means: * `AI_STATE_THINKING` \- the AI is thinking and trying to internally craft an answer to your query * `AI_STATE_GENERATING` \- the actual response to your query is being generated * `AI_STATE_EXTERNAL_SOURCES` \- the AI is checking external resources for information * `AI_STATE_ERROR` \- the AI has reached an error state while trying to answer your query * `AI_STATE_IDLE` \- the AI is in an idle state and is not doing anything If you are using your own implementation and have different states than these, you can feel free to override our default components as well as their behaviour. Please, refer to [our React Assistant tutorial](https://getstream.io/blog/react-assistant/) for more in-depth guidance. It is highly encouraged to read the tutorial before integrating AI in your application. ### Theming Did you find this page helpful? It was helpful It was not helpful I have feedback Submit Thank you for the feedback. An error has occurred. Please refresh the page and try again. [PreviousAudio Playback](/chat/docs/sdk/react/guides/audio-playback/)[NextSDK Integration](/chat/docs/sdk/react/guides/ai-integrations/sdk-integration) © Stream.io, Inc. All Rights Reserved. [Chat Messaging](https://getstream.io/chat/)[Video & Audio](https://getstream.io/video/)[Activity Feeds](https://getstream.io/activity- feeds/)[Moderation](https://getstream.io/moderation/) * Copy LLM prompt * [ View as markdown](https://getstream.io/chat/docs/sdk/react/guides/ai-integrations.md) * * [ Open in ChatGPT](https://chatgpt.com/?q=I'm working with the Stream Chat React SDK and would like to ask questions about this documentation page: https://getstream.io/chat/docs/sdk/react/guides/ai-integrations.md) * [ Open in Claude](https://claude.ai/new?q=I'm working with the Stream Chat React SDK and would like to ask questions about this documentation page: https://getstream.io/chat/docs/sdk/react/guides/ai-integrations.md) * [ Open in Gemini](https://gemini.google.com/app?query=I'm working with the Stream Chat React SDK and would like to ask questions about this documentation page: https://getstream.io/chat/docs/sdk/react/guides/ai-integrations.md) * [ Open in Grok](https://x.com/i/grok?text=I'm working with the Stream Chat React SDK and would like to ask questions about this documentation page: https://getstream.io/chat/docs/sdk/react/guides/ai-integrations.md) * [ Open in Perplexity](https://www.perplexity.ai/search/new?q=I'm working with the Stream Chat React SDK and would like to ask questions about this documentation page: https://getstream.io/chat/docs/sdk/react/guides/ai-integrations.md) On this page: * Installation * Components * StreamingMessage * AIStateIndicator * AIMessageComposer * SpeechToTextButton * AI States * Theming Is this helpful? Thank you . An error has occurred. --- # Stream.io Documentation # Source: https://getstream.io/chat/docs/sdk/android/ * [Chat Messaging](/chat/) / * [Docs](/chat/docs/) / * [Android](/chat/docs/sdk/android/) # Overview The [Stream Chat Android SDK](https://github.com/GetStream/stream-chat- android) enables you to easily build any type of chat or messaging experience for Android, either in Kotlin or Java. The fastest way to get started with the SDK is by trying the [Android Views In-App Messaging Tutorial](https://getstream.io/tutorials/android-chat/). If you’re using Jetpack Compose, see the [Compose In-App Messaging Tutorial](https://getstream.io/chat/compose/tutorial/) instead. ## Architecture The SDK consists of five major components: * [Views/XML UI components](/chat/docs/sdk/android/ui/overview/). Provides a set of reusable and customizable UI components based on Android Views. * [Compose UI components](/chat/docs/sdk/android/compose/overview/). Provides a set of reusable and customizable Jetpack Compose UI components. * [Low-level client](/chat/docs/android/). Provides the main chat functionality. You can use it directly if you intend to build your own UI layer for the chat. * [State](/chat/docs/sdk/android/client/guides/state-plugin/). Plugin that gives you the possibility to observe data via `StateFlows`. It exposes `StateFlow` objects containing the loading state, channel and message lists, channel members, users that are typing and more. * [Offline Support](/chat/docs/sdk/android/client/guides/offline-support/). Plugin that enables offline data and actions, like cached channels, messages, sending messages and reactions. Good for improving UX when the network connection is poor. We recommend using either the [Views/XML UI Components](/chat/docs/sdk/android/ui/overview/) or the [Compose UI Components](/chat/docs/sdk/android/compose/overview/) to most of our customers. If your UI doesn’t significantly differ from the industry standard, you should be able to customize the built-in components to match your requirements. For more information about including each component in your project, see the [Installation](/chat/docs/sdk/android/basics/dependencies/) page. ## UI SDKs Built on top of the Stream Chat low-level client, the Stream Chat Android UI components enable you to easily build any type of chat or messaging experience for Android. We have UI component libraries available for both **Android Views** and **Jetpack Compose**. Each of these libraries provides an extensive collection of efficient and customizable UI components which enable you to quickly get started with little to no setup required. The libraries support: * Rich-media messages * Channel and message lists * Message Reactions * Message threads and quoted replies * Text input commands (ex: Giphy and @mentions) * Image and file uploads * Video playback * Indicators for read state and typing * Push notifications * Offline storage * Voice messages (only in the Android Views library for now) * and more. If needed, you can create your own UI components by listening to the state we expose and using our components as building blocks. You can learn more about how state is exposed [here](/chat/docs/sdk/android/client/guides/state- plugin/) and in the [low-level client docs](/chat/docs/android/). ### Choosing the Right UI SDK #### Views UI Components The UI Components library includes pre-built Android Views to easily load and display data from the Stream Chat API. These include a Channel List and a Message List, a Message Composer View, and more. See the [Getting Started](/chat/docs/sdk/android/ui/overview/) page for more details. This library is built on top of the state library, and offers the quickest integration of Stream Chat into an Android application. It also offers a variety of [theming](/chat/docs/sdk/android/ui/general-customization/theming/) options to make it fit your app’s needs. You can see the UI Components in action by checking out the [UI Components Sample App](https://github.com/GetStream/stream-chat-android/tree/main/stream- chat-android-ui-components-sample), available in the GitHub repository. #### Compose UI Components The Compose UI Components library is a chat UI implementation built from scratch with [Jetpack Compose](https://developer.android.com/jetpack/compose). It contains modular Composable functions for building channel lists, messaging screens, and more. See the [Getting Started](/chat/docs/sdk/android/compose/overview/) page for more details. This is also built on top of the state library, and offers easy integration of Stream Chat into a Compose-based Android application. It’s also highly modular and customizable. Check out the Compose implementation in action by trying the open-source [Compose UI Components Sample App](https://github.com/GetStream/stream-chat- android/tree/main/stream-chat-android-compose-sample). Using our Compose SDK in an Android Views based app is fully supported. It could provide you an amazing opportunity to explore and adopt Compose. #### The Right SDK for You If your use case requires a very high level of customization, runtime theming changes, replacing whole parts of the default UI or stateless components that don’t rely on our ViewModels, the **Compose SDK is the way to go**. It offers deep customization through several layers - the theme, modifiers for components, bound and stateless component overloads, smaller reusable components and slot APIs. If, instead, you’re looking for a simpler, less customizable SDK which currently offers slightly better performance in some scenarios or your project is limited by technology, then the **UI Components SDK is a great option**. It still offers a fair amount of customization through the theme and its attributes and some programmatic ways to customize the UI. Whichever SDK you choose, **we guarantee you’ll be happy and we’ll provide amazing support** with your integration, through detailed documentation, guides and direct support. ## Upgrade and Versioning Strategy The StreamChat Android SDK adheres to the [semantic versioning](https://semver.org/) rules. * Bug fixes and behavior improvements cause **patch** version bump. * New features are shipped with an increased **minor** version. * Incompatible changes in the API will cause a **major** version increase. Occasionally, the SDK can include visual changes (whitespace, color changes, sizing, etc) in minor versions, as we are continuously improving the default look of our UI components. Bumping the major version for such changes would not be practical. You can see all the SDK changes in the [releases page](https://github.com/GetStream/stream-chat-android/releases), and you can also find the release notes of all past releases in our [CHANGELOG file](https://github.com/GetStream/stream-chat- android/blob/main/CHANGELOG.md). You can get notified of new releases by using the _Watch_ button in the [getstream/stream-chat-android](https://github.com/GetStream/stream-chat- android) repository. You can tweak your watch preferences to subscribe only to release events. ### How Should I Specify My Dependency Version? You should use a fixed version in order to avoid any conflicts or unpredicted behaviour. For example: implementation "io.getstream:stream-chat-android-compose:6.4.4" Did you find this page helpful? It was helpful It was not helpful I have feedback Submit Thank you for the feedback. An error has occurred. Please refresh the page and try again. [PreviousSample Apps](/chat/docs/sdk/android/v5/resources/sample- apps/)[NextInstallation](/chat/docs/sdk/android/basics/dependencies/) © Stream.io, Inc. All Rights Reserved. [Chat Messaging](https://getstream.io/chat/)[Video & Audio](https://getstream.io/video/)[Activity Feeds](https://getstream.io/activity- feeds/)[Moderation](https://getstream.io/moderation/) * Copy LLM prompt * [ View as markdown](https://getstream.io/chat/docs/sdk/android.md) * * [ Open in ChatGPT](https://chatgpt.com/?q=I'm working with the Stream Chat Android SDK and would like to ask questions about this documentation page: https://getstream.io/chat/docs/sdk/android.md) * [ Open in Claude](https://claude.ai/new?q=I'm working with the Stream Chat Android SDK and would like to ask questions about this documentation page: https://getstream.io/chat/docs/sdk/android.md) * [ Open in Gemini](https://gemini.google.com/app?query=I'm working with the Stream Chat Android SDK and would like to ask questions about this documentation page: https://getstream.io/chat/docs/sdk/android.md) * [ Open in Grok](https://x.com/i/grok?text=I'm working with the Stream Chat Android SDK and would like to ask questions about this documentation page: https://getstream.io/chat/docs/sdk/android.md) * [ Open in Perplexity](https://www.perplexity.ai/search/new?q=I'm working with the Stream Chat Android SDK and would like to ask questions about this documentation page: https://getstream.io/chat/docs/sdk/android.md) On this page: * Architecture * UI SDKs * Choosing the Right UI SDK * Upgrade and Versioning Strategy * How Should I Specify My Dependency Version? Is this helpful? Thank you . An error has occurred. --- # Stream.io Documentation # Source: https://getstream.io/chat/docs/sdk/flutter/ * [Chat Messaging](/chat/) / * [Docs](/chat/docs/) / * [Flutter](/chat/docs/sdk/flutter/) # Overview About The Flutter SDK ! Stream Chat is a service that helps you easily build a full chat experience in your Flutter apps. We also support a variety of other SDKs. This section of the documentation focuses on our Flutter SDK which helps you easily ship high quality messaging experiences in apps and programs built with the [Flutter toolkit made by Google](https://flutter.dev). The Stream Chat Flutter SDK comprises five different packages to choose from, ranging from ones giving you complete control to ones that give you a rich out-of-the-box chat experience. The packages that make up the Stream Chat SDK are: 1. **Low Level Client (`stream_chat`)**: a pure Dart package that can be used on any Dart project. It provides a low-level client to access the Stream Chat service. 2. **Core (`stream_chat_flutter_core`)**: provides business logic to fetch common things required for integrating Stream Chat into your application. The core package allows more customisation and hence provides business logic but no UI components. 3. **UI (`stream_chat_flutter`)**: this library includes both a low-level chat SDK and a set of reusable and customizable UI components. 4. **Persistence (`stream_chat_persistence`)**: provides a persistence client for fetching and saving chat data locally. 5. **Localizations (`stream_chat_localizations`)**: provides a set of localizations for the SDK. We recommend building prototypes using the full UI package, [`stream_chat_flutter`](https://pub.dev/packages/stream_chat_flutter), since it contains UI widgets already integrated with Stream’s API. It is the fastest way to get up and running using Stream chat in your app. The Flutter SDK enables you to build any type of chat or messaging experience for Android, iOS, Web and Desktop. If you’re building a very custom UI and would prefer a more lean package, [`stream_chat_flutter_core`](https://pub.dev/packages/stream_chat_flutter_core) will be suited to this use case. Core allows you to build custom, expressive UIs while retaining the benefits of our full Flutter SDK. APIs for accessing and controlling users, sending messages, and so forth are seamlessly integrated into this package and accessible via providers and builders. Before going into the docs, let’s take a small detour to look at how the elements of Stream Chat are structured. ### Basic Structure There are two core elements in chat, **Users** and **Channels**. Channels are groups of one or more users that can message each other. In an app, you need to have a user connected to query channels. There is no specific distinction between a chat with only two people and a group chat, but there is a way to create a unique chat between a certain number of people by creating a **distinct** channel. ! In essence, a normal two-person chat would be a **distinct channel** created with two members (you cannot add or delete members in this channel), whereas a group created with two people would simply be a **non distinct channel** (possible to add or remove members). It is also possible to add more than two people in a distinct channel which retains the same add/removal properties and resembles the Slack DMs where you can DM one or more people as well. In summary, if you were creating a Whatsapp-like app, the first screen would be a **list of channels** \- which on opening would show a **list of messages** that were sent by the users in the Channel. While this is a simplistic overview of the service, the Flutter SDK handles the UI and more time consuming things (media upload, offline storage, theming, etc.) for you. Before reading the docs, consider trying our [online API tour](https://getstream.io/chat/get_started/), it is a nice way to learn how the API works. It’s in-browser so you’ll need to use JavaScript but the core concepts are pretty much the same as Dart. You may also like to look at the [Flutter tutorial](https://getstream.io/chat/flutter/tutorial/) which focuses on using the UI package to get Stream Chat integrated into a Flutter app. Further sections break down each individual packages and explain several common operations. Did you find this page helpful? It was helpful It was not helpful I have feedback Submit Thank you for the feedback. An error has occurred. Please refresh the page and try again. [Previousv8.0](/chat/docs/sdk/flutter/v8/guides/migration_guide_8_0/)[NextInstallation](/chat/docs/sdk/flutter/basics/installation/) © Stream.io, Inc. All Rights Reserved. [Chat Messaging](https://getstream.io/chat/)[Video & Audio](https://getstream.io/video/)[Activity Feeds](https://getstream.io/activity- feeds/)[Moderation](https://getstream.io/moderation/) * Copy LLM prompt * [ View as markdown](https://getstream.io/chat/docs/sdk/flutter.md) * * [ Open in ChatGPT](https://chatgpt.com/?q=I'm working with the Stream Chat Flutter SDK and would like to ask questions about this documentation page: https://getstream.io/chat/docs/sdk/flutter.md) * [ Open in Claude](https://claude.ai/new?q=I'm working with the Stream Chat Flutter SDK and would like to ask questions about this documentation page: https://getstream.io/chat/docs/sdk/flutter.md) * [ Open in Gemini](https://gemini.google.com/app?query=I'm working with the Stream Chat Flutter SDK and would like to ask questions about this documentation page: https://getstream.io/chat/docs/sdk/flutter.md) * [ Open in Grok](https://x.com/i/grok?text=I'm working with the Stream Chat Flutter SDK and would like to ask questions about this documentation page: https://getstream.io/chat/docs/sdk/flutter.md) * [ Open in Perplexity](https://www.perplexity.ai/search/new?q=I'm working with the Stream Chat Flutter SDK and would like to ask questions about this documentation page: https://getstream.io/chat/docs/sdk/flutter.md) On this page: * Basic Structure Is this helpful? Thank you . An error has occurred. --- # Stream.io Documentation # Source: https://getstream.io/chat/docs/sdk/ios/ * [Chat Messaging](/chat/) / * [Docs](/chat/docs/) / * [iOS](/chat/docs/sdk/ios/) # Overview Building on top of the Stream Chat API, the Stream Chat iOS components include everything you need to build feature-rich and high-functioning chat user experiences out of the box. We have component libraries available for both UIKit and SwiftUI. Each library includes an extensive set of fast performing and customizable UI components which allow you to get started quickly with little to no plumbing required. The libraries support: * Rich media messages * Reactions * Threads and quoted replies * Text input commands (ex: Giphy and @mentions) * Image and file uploads and downloads * Video playback * Read state and typing indicators * Channel and message lists * Push (APN or Firebase) * Offline storage * Voice messages * macOS * and a lot more. Before getting started with our docs, we recommend going through our tutorials for the [UIKit](https://getstream.io/tutorials/ios-uikit-chat/) and [SwiftUI](https://getstream.io/tutorials/ios-chat/) SDKs. ## Architecture StreamChat Swift SDK consists of three separate frameworks: * [`StreamChatUI`](/chat/docs/sdk/ios/uikit/getting-started/) provides a set of reusable and customizable UI components to add chat to your UIKit application. * [`StreamChatSwiftUI`](/chat/docs/sdk/ios/swiftui/getting-started/) provides a set of reusable and customizable UI components to add chat to your SwiftUI application. * [`StreamChat`](/chat/docs/ios-swift/) is the low-level client that provides the main chat functionality, including offline storage and optimistic updates. You can use it directly in case you want to build your own UI layer for the chat. We suggest using either [`StreamChatUI`](/chat/docs/sdk/ios/uikit/getting- started/) or [`StreamChatSwiftUI`](/chat/docs/sdk/ios/swiftui/getting- started/) to most of our customers. Unless your UI is completely different from the common industry standard, you should be able to customize the built- in components to match your needs. The UI SDKs provide both ready-made components that you can directly integrate (and customize) in your apps, or you can build your own, by reacting to the state we expose and re-using our components as building blocks, if needed. You can learn more about how the state is exposed on [this page](/chat/docs/sdk/ios/client/) and in the [low-level client docs](/chat/docs/ios-swift/). You can use this library to develop OSX application by using the `StreamChat` framework ### Dependencies The SDK tries to keep the list of external dependencies to a minimum, these are the dependencies currently used: #### StreamChatUI * [Nuke](https://github.com/kean/Nuke) for loading images * [SwiftyGif](https://github.com/alexiscreuzot/SwiftyGif) for high performance gif rendering * [StreamChat](/chat/docs/sdk/ios/\(https:/getstream.io/chat/docs/ios-swift/\)) the low-level client for the Stream Chat API #### StreamChatSwiftUI * [Nuke](https://github.com/kean/Nuke) for loading images * [NukeUI](https://github.com/kean/Nuke) for loading images * [SwiftyGif](https://github.com/alexiscreuzot/SwiftyGif) for high performance gif rendering * [StreamChat](/chat/docs/sdk/ios/\(https:/getstream.io/chat/docs/ios-swift/\)) the low-level client for the Stream Chat API Starting **4.6.0** , and in order to improve the developer experience, dependencies are hidden inside our libraries. ## Choosing the right SDK When integrating with our chat platform, you get to choose which SDK you would like to integrate with. Our best options are either the UIKit or SwiftUI SDKs. We suggest you choose what is closest to your current App. Note that integrating our SwiftUI SDK into a UIKit based app is fully supported. It could provide you and your development team an amazing opportunity to get started with SwiftUI in your codebase. Both UI SDKs expose a channel list and a channel component. The channel list component consists of a channel list header, channel list and other helper views (such as search, swipe actions, and more). You can learn more about the channel list in [UIKit](/chat/docs/sdk/ios/uikit/components/channel-list/) and [SwiftUI](/chat/docs/sdk/ios/swiftui/channel-list-components/helper-views/) in our docs. The channel component consists of a channel header, message list, message composer and other helper views (such as reactions overlay, different media pickers, threads etc). More details about these components can be found in our [UIKit](/chat/docs/sdk/ios/uikit/components/channel/) and [SwiftUI](/chat/docs/sdk/ios/swiftui/chat-channel-components/overview/) docs. ## Upgrade and Versioning Strategy The StreamChat Swift SDK adheres to the [semantic versioning](https://semver.org/) rules. * Bug fixes and behavior improvements cause **patch** version bump. * New features are shipped with an increased **minor** version. * Incompatible changes in the API will cause a **major** version increase. Occasionally, the SDK can include visual changes (whitespace, color changes, sizing, etc) in minor versions, as we are continuously improving the default look of our UI components. Bumping the major version for such changes would not be practical. ### How Should I Specify My Dependency Version? You should either use a fixed version, or an optimistic operator (a.k.a. squiggly arrow), with **all three versions specified**. For example with CocoaPods: pod 'StreamChat', '~> 4.62.0' To stay up-to-date with our updates and get a detailed breakdown of what’s new, subscribe to the releases of [getstream/stream-chat- swift](https://github.com/GetStream/stream-chat-swift/releases) by clicking the “watch” button. You can further tweak your watch preferences and subscribe only to the release events. Did you find this page helpful? It was helpful It was not helpful I have feedback Submit Thank you for the feedback. An error has occurred. Please refresh the page and try again. [NextInstallation](/chat/docs/sdk/ios/basics/integration/) © Stream.io, Inc. All Rights Reserved. [Chat Messaging](https://getstream.io/chat/)[Video & Audio](https://getstream.io/video/)[Activity Feeds](https://getstream.io/activity- feeds/)[Moderation](https://getstream.io/moderation/) * Copy LLM prompt * [ View as markdown](https://getstream.io/chat/docs/sdk/ios.md) * * [ Open in ChatGPT](https://chatgpt.com/?q=I'm working with the Stream Chat IOS SDK and would like to ask questions about this documentation page: https://getstream.io/chat/docs/sdk/ios.md) * [ Open in Claude](https://claude.ai/new?q=I'm working with the Stream Chat IOS SDK and would like to ask questions about this documentation page: https://getstream.io/chat/docs/sdk/ios.md) * [ Open in Gemini](https://gemini.google.com/app?query=I'm working with the Stream Chat IOS SDK and would like to ask questions about this documentation page: https://getstream.io/chat/docs/sdk/ios.md) * [ Open in Grok](https://x.com/i/grok?text=I'm working with the Stream Chat IOS SDK and would like to ask questions about this documentation page: https://getstream.io/chat/docs/sdk/ios.md) * [ Open in Perplexity](https://www.perplexity.ai/search/new?q=I'm working with the Stream Chat IOS SDK and would like to ask questions about this documentation page: https://getstream.io/chat/docs/sdk/ios.md) On this page: * Architecture * Dependencies * Choosing the right SDK * Upgrade and Versioning Strategy * How Should I Specify My Dependency Version? Is this helpful? Thank you . An error has occurred. --- # Stream.io Documentation # Source: https://getstream.io/chat/docs/sdk/react-native/ * [Chat Messaging](/chat/) / * [Docs](/chat/docs/) / * [React Native](/chat/docs/sdk/react-native/) # Overview Built on top of the Stream Chat API, the Stream Chat React Native SDK components include everything you need to build feature-rich and high- functioning chat user experiences out of the box. We have component libraries available for both RN CLI and Expo. Each approach includes an extensive set of fast performing and customizable UI components and support which allow you to get started quickly with little to no plumbing required. The libraries support: * Rich media messages * Reactions * Threads and quoted replies * Text input commands (ex: Giphy, emojis and @mentions) * Image and file uploads * Video playback * Read state and typing indicators. * Channel and message lists * Push (APN or Firebase) * Offline storage * and a lot more. Additionally, starting with version `6.0.0` our SDK supports the [React Native new architecture](https://reactnative.dev/architecture/landing-page) as well. You can read more about it [here](/chat/docs/sdk/react-native/guides/new- architecture). Before getting started with our docs, we recommend going through our tutorials for our [**React Native SDK**](https://getstream.io/chat/react-native- chat/tutorial/). ## Where to get started? If you are new to our SDK, it is best to go through our [**React Native SDK**](https://getstream.io/chat/react-native-chat/tutorial/) tutorial. ## Architecture Stream Chat React Native SDK primarily uses the [Stream Chat client](https://github.com/GetStream/stream-chat-js) to connect to and communicate with the Stream API. The full [JavaScript client docs](/chat/docs/javascript/) should be referenced for detailed information on directly using the client. Do not install the `stream-chat` dependency externally. This may lead to problems while using our SDK. Our SDK has it as a development dependency, so you need not install it externally. The Stream Chat React Native SDK is segregated into two separate packages: * `stream-chat-react-native` for **React Native CLI** applications. * `stream-chat-expo` for **Expo CLI** applications. We recommend using the corresponding package for the respective CLI that the application uses. Our SDK components are highly customizable for both the interfaces. Unless your UI is completely different from the common industry standard, you should be able to customize the built-in components to match your needs. The UI SDKs provide both ready-made components that you can directly integrate (and customize) in your apps, or you can build your own, by reacting to the state we expose and re-using our components as building blocks, if needed. ## Upgrading and Versioning Strategy The Stream Chat React Native SDK adheres to the [semantic versioning](https://semver.org/) rules. * Bug fixes and behavior improvements cause **patch**  version bump. * New features are shipped with an increased **minor**  version. * Incompatible changes in the API will cause a **major**  version increase. Occasionally, the SDK can include visual changes (whitespace, color changes, sizing, etc) in minor versions, as we are continuously improving the default look of our UI components. Bumping the major version for such changes would not be practical. ## Platform Compatibilities We only support **Android**  and **iOS**  as platforms for the React Native SDK. We do not support **Web**  currently, but this is in our backlog, and we plan to take this up in the future. As an alternative, you can use Stream’s [React SDK](/chat/docs/sdk/react/) for Web. ## Sample Apps We have created some of the sample apps to help understand the usage of the Stream Chat React Native SDK. They can be found in the [`examples`](https://github.com/GetStream/stream-chat-react- native/tree/develop/examples) directory of the main repository. Apart from the samples we use for internal development, we also provide some small clone projects like a Slack clone and an iMessage clone. You can check out the code in [our repository](https://github.com/GetStream/react-native-samples) and even run the apps yourself. Did you find this page helpful? It was helpful It was not helpful I have feedback Submit Thank you for the feedback. An error has occurred. Please refresh the page and try again. [PreviousMigration from 6.x to 7.x](/chat/docs/sdk/react- native/v7/basics/upgrading-from-v6/)[NextInstallation](/chat/docs/sdk/react- native/basics/installation/) © Stream.io, Inc. All Rights Reserved. [Chat Messaging](https://getstream.io/chat/)[Video & Audio](https://getstream.io/video/)[Activity Feeds](https://getstream.io/activity- feeds/)[Moderation](https://getstream.io/moderation/) * Copy LLM prompt * [ View as markdown](https://getstream.io/chat/docs/sdk/react-native.md) * * [ Open in ChatGPT](https://chatgpt.com/?q=I'm working with the Stream Chat React Native SDK and would like to ask questions about this documentation page: https://getstream.io/chat/docs/sdk/react-native.md) * [ Open in Claude](https://claude.ai/new?q=I'm working with the Stream Chat React Native SDK and would like to ask questions about this documentation page: https://getstream.io/chat/docs/sdk/react-native.md) * [ Open in Gemini](https://gemini.google.com/app?query=I'm working with the Stream Chat React Native SDK and would like to ask questions about this documentation page: https://getstream.io/chat/docs/sdk/react-native.md) * [ Open in Grok](https://x.com/i/grok?text=I'm working with the Stream Chat React Native SDK and would like to ask questions about this documentation page: https://getstream.io/chat/docs/sdk/react-native.md) * [ Open in Perplexity](https://www.perplexity.ai/search/new?q=I'm working with the Stream Chat React Native SDK and would like to ask questions about this documentation page: https://getstream.io/chat/docs/sdk/react-native.md) On this page: * Where to get started? * Architecture * Upgrading and Versioning Strategy * Platform Compatibilities * Sample Apps Is this helpful? Thank you . An error has occurred. --- # Stream.io Documentation # Source: https://getstream.io/chat/docs/sdk/react/ * [Chat Messaging](/chat/) / * [Docs](/chat/docs/) / * [React](/chat/docs/sdk/react/) # Overview > Building on top of the Stream Chat API, the Stream Chat React component > library includes everything you need to build feature-rich and high- > functioning chat user experiences out of the box. The library includes an > extensive set of performant and customizable React components which allow > you to get started quickly with little to no plumbing required. Use cases > include team and social messaging, virtual events, livestream gaming, and > customer support. The library supports: * Rich media messages * Reactions * Threads and quoted replies * Text input commands (ex: Giphy and @mentions) * Image and file uploads * Video playback * Audio recording * Read state and typing indicators * Channel and message lists ## Where to Get Started If you are new to our SDK it is best to go through our [tutorial](https://getstream.io/chat/react-chat/tutorial/). After that, our [getting started page](/chat/docs/sdk/react/basics/getting_started/) is a great next step. If you are integrating our SDK, please pay attention to our [Theming](/chat/docs/sdk/react/theming/themingv2/) and [Customizing Components](/chat/docs/sdk/react/guides/customization/) sections in our guides. We see that most of our users can get very far by utilizing the flexibility of our SDKs. ## Architecture > A common pattern in the library is the use of context provider hooks. These > custom hooks allow for effective value sharing between parent components and > their children. This makes customization straightforward, as you can use our > exported hooks in your custom components to receive the exact values needed, > while also subscribing to context changes. The left navigation will guide you to the various documentation sections for information on everything regarding our robust component library. Check out the instructions for adding the library to your React project. ## Supported Platforms Our React Chat SDK can run on all modern browsers and platforms released after April 2024. Here is the list of supported platforms: * Chrome 124+ * Firefox 124+ * Edge 124+ * Safari and Mobile Safari 17.4+ Although the SDK works on other exotic and older browser versions, these are the ones we officially support and test against, so we recommend using them for the best experience. Did you find this page helpful? It was helpful It was not helpful I have feedback Submit Thank you for the feedback. An error has occurred. Please refresh the page and try again. [PreviousResources](/chat/docs/sdk/react/v12/resources/)[NextInstallation](/chat/docs/sdk/react/basics/installation/) © Stream.io, Inc. All Rights Reserved. [Chat Messaging](https://getstream.io/chat/)[Video & Audio](https://getstream.io/video/)[Activity Feeds](https://getstream.io/activity- feeds/)[Moderation](https://getstream.io/moderation/) * Copy LLM prompt * [ View as markdown](https://getstream.io/chat/docs/sdk/react.md) * * [ Open in ChatGPT](https://chatgpt.com/?q=I'm working with the Stream Chat React SDK and would like to ask questions about this documentation page: https://getstream.io/chat/docs/sdk/react.md) * [ Open in Claude](https://claude.ai/new?q=I'm working with the Stream Chat React SDK and would like to ask questions about this documentation page: https://getstream.io/chat/docs/sdk/react.md) * [ Open in Gemini](https://gemini.google.com/app?query=I'm working with the Stream Chat React SDK and would like to ask questions about this documentation page: https://getstream.io/chat/docs/sdk/react.md) * [ Open in Grok](https://x.com/i/grok?text=I'm working with the Stream Chat React SDK and would like to ask questions about this documentation page: https://getstream.io/chat/docs/sdk/react.md) * [ Open in Perplexity](https://www.perplexity.ai/search/new?q=I'm working with the Stream Chat React SDK and would like to ask questions about this documentation page: https://getstream.io/chat/docs/sdk/react.md) On this page: * Where to Get Started * Architecture * Supported Platforms Is this helpful? Thank you . An error has occurred. --- # Stream.io Documentation # Source: https://getstream.io/chat/docs/search/ * [Chat Messaging](/chat/) / * [Docs](/chat/docs/) / * [React](/chat/docs/react/) / * [Message Search](/chat/docs/react/search/) # Message Search Search messages across channels using full-text search or specific field filters. Enable or disable search indexing per channel type in the Stream Dashboard. ## Searching Messages Search requires a channel filter and either a text query or message filter conditions. JavaScriptKotlinSwiftJavaPythonRubyPHPGoC#Unity // Search for messages containing text const results = await client.search( { members: { $in: ["john"] } }, "supercalifragilisticexpialidocious", { limit: 10 }, ); // Search with message filters const filtered = await client.search( { members: { $in: ["john"] } }, { text: { $autocomplete: "super" }, attachments: { $exists: true } }, { limit: 10 }, ); val channelFilter = Filters.eq("cid", "messaging:my-channel") val messageFilter = Filters.autocomplete("text", "supercali") client.searchMessages( channelFilter = channelFilter, messageFilter = messageFilter, limit = 10, ).enqueue { result -> if (result is Result.Success) { val messages: List = result.value.messages } else { // Handle Result.Failure } } let controller = client.messageSearchController() controller.loadNextMessages(limit: 10) { error in if let error = error { // Handle error } else { let messages = controller.messages } } var searchResult = Message.search() .filterCondition("text", condition) .query("supercalifragilisticexpialidocious") .limit(10) .request(); channel_filters = {"cid": "messaging:my-channel"} message_filters = {"text": {"$autocomplete": "supercali"}} page1 = client.search( channel_filters, message_filters, sort=[{"relevance": -1}, {"updated_at": 1}], limit=10 ) channel_filters = { cid: 'messaging:my-channel' } message_filters = { text: { '$autocomplete': 'supercali' }} page1 = client.search( channel_filters, message_filters, sort: [{ relevance: -1 }, { updated_at: 1 }], limit: 10 ) $response = $serverClient->search( $filters, 'supercalifragilisticexpialidocious', ['limit' => 10] ); resp, err := client.Search(ctx, SearchRequest{ Query: "supercalifragilisticexpialidocious", Filters: map[string]interface{}{ "members": map[string][]string{ "$in": {"john"}, }, }, Limit: 10, }) var response = await messageClient.SearchAsync(SearchOptions.Default .WithMessageFilterConditions(new Dictionary { { "members", new Dictionary { { "$in", new[] {"john"} }, } }, }) .WithQuery("supercalifragilisticexpialidocious") .WithLimit(10)); var results = await Client.LowLevelClient.MessageApi.SearchMessagesAsync(new SearchRequest { FilterConditions = new Dictionary { { "members", new Dictionary { { "$in", new[] { "John" } } } } }, Query = "supercalifragilisticexpialidocious", Limit = 30 }); foreach (var searchResult in results.Results) { Debug.Log(searchResult.Message.Id); Debug.Log(searchResult.Message.Text); Debug.Log(searchResult.Message.User); Debug.Log(searchResult.Message.Channel); } ### Query Parameters Name| Type| Description| Default| Optional filter_conditions| object| Channel filters. Maximum 500 channels are searched. See [Querying Channels](/chat/docs/react/query_channels/).| -| message_filter_conditions| object| Message filters. See Message Filter Conditions below. Either this or `query` is required.| -| ✓ query| string| Full-text search string. Equivalent to `{text: {$q: }}`. Either this or `message_filter_conditions` is required.| -| ✓ limit| integer| Number of messages to return.| 100| ✓ offset| integer| Pagination offset. Cannot be used with `sort` or `next`.| 0| ✓ sort| object/array| Sort order. Use field names with `1` (ascending) or `-1` (descending).| [{relevance: -1}, {id: 1}]| ✓ next| string| Pagination cursor. See Pagination below.| -| ✓ ### Message Filter Conditions Field| Description| Operators id| Message ID| $eq, $gt, $gte, $lt, $lte, $in text| Message text| $q, $autocomplete, $eq, $gt, $gte, $lt, $lte, $in type| Message type. System and deleted messages are excluded| $eq, $gt, $gte, $lt, $lte, $in parent_id| Parent message ID (for replies)| $eq, $gt, $gte, $lt, $lte, $in reply_count| Number of replies| $eq, $gt, $gte, $lt, $lte, $in attachments| Whether message has attachments| $exists, $eq, $gt, $gte, $lt, $lte, $in attachments.type| Attachment type| $eq, $in mentioned_users.id| Mentioned user ID| $contains user.id| Sender user ID| $eq, $gt, $gte, $lt, $lte, $in created_at| Creation timestamp| $eq, $gt, $gte, $lt, $lte, $in updated_at| Update timestamp| $eq, $gt, $gte, $lt, $lte, $in pinned| Whether message is pinned| $eq custom field| Any custom field on the message| $eq, $gt, $gte, $lt, $lte, $in ## Sorting Results are sorted by relevance by default, with message ID as a tiebreaker. If your query does not use `$q` or `$autocomplete`, all results are equally relevant. Sort by any filterable field, including custom fields. Numeric custom fields are sorted numerically; string fields are sorted lexicographically. ## Pagination Two pagination methods are available: **Offset pagination** allows access to up to 1,000 results. Results are sorted by relevance and message ID. You cannot use custom sorting with offset pagination. **Cursor pagination** (using `next`/`previous`) allows access to all matching results with custom sorting. The response includes `next` and `previous` cursors to navigate between pages. JavaScriptKotlinPythonRubyJavaPHPGoC#Unity const channelFilters = { cid: "messaging:my-channel" }; const messageFilters = { text: { $autocomplete: "supercali" } }; // First page with custom sorting const page1 = await client.search(channelFilters, messageFilters, { sort: [{ relevance: -1 }, { updated_at: 1 }, { my_custom_field: -1 }], limit: 10, }); // Next page using cursor const page2 = await client.search(channelFilters, messageFilters, { limit: 10, next: page1.next, }); // Previous page const page1Again = await client.search(channelFilters, messageFilters, { limit: 10, next: page2.previous, }); val channelFilter = Filters.eq("cid", "messaging:my-channel") val messageFilter = Filters.autocomplete("text", "supercali") val sort = QuerySortByField.descByName("relevance") .descByName("updatedAt") .descByName("my_custom_field") var nextPage: String? = null client.searchMessages( sort = sort, limit = 10, channelFilter = channelFilter, messageFilter = messageFilter, ).enqueue { result -> if (result is Result.Success) { nextPage = result.value.next val messages: List = result.value.messages } } // Next page var previousPage: String? = null client.searchMessages( limit = 10, channelFilter = channelFilter, messageFilter = messageFilter, next = nextPage, ).enqueue { result -> if (result is Result.Success) { previousPage = result.value.previous val messages: List = result.value.messages } } // Previous page client.searchMessages( limit = 10, channelFilter = channelFilter, messageFilter = messageFilter, next = previousPage, ).enqueue { /* ... */ } channel_filters = {"cid": "messaging:my-channel"} message_filters = {"text": {"$autocomplete": "supercali"}} # First page page1 = client.search( channel_filters, message_filters, sort=[{"relevance": -1}, {"updated_at": 1}, {"my_custom_field": -1}], limit=10 ) # Next page page2 = client.search(channel_filters, message_filters, next=page1["next"], limit=10) # Previous page page1_again = client.search(channel_filters, message_filters, next=page2["previous"], limit=10) channel_filters = { cid: 'messaging:my-channel' } message_filters = { text: { '$autocomplete': 'supercali' }} # First page page1 = client.search( channel_filters, message_filters, sort: [{ relevance: -1 }, { updated_at: 1 }, { my_custom_field: -1 }], limit: 10 ) # Next page page2 = client.search(channel_filters, message_filters, next: page1.next, limit: 10) # Previous page page1_again = client.search(channel_filters, message_filters, next: page2.previous, limit: 10) var searchResult = Message.search() .filterCondition("text", condition) .query("supercalifragilisticexpialidocious") .limit(2) .request(); // Next page var nextResult = Message.search() .filterCondition("text", condition) .query("supercalifragilisticexpialidocious") .sort(Sort.builder().field("relevance").direction(Sort.Direction.ASC).build()) .sort(Sort.builder().field("updated_at").direction(Sort.Direction.DESC).build()) .limit(2) .next(searchResult.getNext()) .request(); $response = $serverClient->search( $filters, 'supercalifragilisticexpialidocious', ['limit' => 10] ); // Next page $response = $serverClient->search( $filters, 'supercalifragilisticexpialidocious', ['limit' => 10, 'next' => $response['next']] ); resp, err := client.Search(ctx, SearchRequest{ Query: "supercalifragilisticexpialidocious", Filters: map[string]interface{}{ "members": map[string][]string{ "$in": {"john"}, }, }, Limit: 10, }) // Next page client.SearchWithFullResponse(ctx, SearchRequest{ Query: "supercalifragilisticexpialidocious", Filters: map[string]interface{}{ "members": map[string][]string{ "$in": {"john"}, }, }, Next: resp.Next, Limit: 10, }) var response = await messageClient.SearchAsync(SearchOptions.Default .WithMessageFilterConditions(new Dictionary { { "members", new Dictionary { { "$in", new[] {"john"} }, } }, }) .WithQuery("supercalifragilisticexpialidocious") .WithLimit(10)); // Next page response = await messageClient.SearchAsync(SearchOptions.Default .WithMessageFilterConditions(new Dictionary { { "members", new Dictionary { { "$in", new[] {"john"} }, } }, }) .WithQuery("supercalifragilisticexpialidocious") .WithLimit(10) .WithNext(response.Next)); // First page var resultsPage1 = await Client.LowLevelClient.MessageApi.SearchMessagesAsync(new SearchRequest { FilterConditions = new Dictionary { { "members", new Dictionary { { "$in", new[] { "John" } } } } }, Query = "supercalifragilisticexpialidocious", Limit = 30 }); // Next page var resultsPage2 = await Client.MessageApi.SearchMessagesAsync(new SearchRequest { FilterConditions = new Dictionary { { "members", new Dictionary { { "$in", new[] { "John" } } } } }, Next = resultsPage1.Next, Query = "supercalifragilisticexpialidocious", Limit = 30 }); Did you find this page helpful? It was helpful It was not helpful I have feedback Submit Thank you for the feedback. An error has occurred. Please refresh the page and try again. [PreviousPinned Messages](/chat/docs/react/pinned_messages/)[NextSilent & System Messages](/chat/docs/react/silent_messages/) © Stream.io, Inc. All Rights Reserved. [Chat Messaging](https://getstream.io/chat/)[Video & Audio](https://getstream.io/video/)[Activity Feeds](https://getstream.io/activity- feeds/)[Moderation](https://getstream.io/moderation/) * Copy LLM prompt * [ View as markdown](https://getstream.io/chat/docs/react/search.md) * * [ Open in ChatGPT](https://chatgpt.com/?q=I'm working with the Stream Chat React SDK and would like to ask questions about this documentation page: https://getstream.io/chat/docs/react/search.md) * [ Open in Claude](https://claude.ai/new?q=I'm working with the Stream Chat React SDK and would like to ask questions about this documentation page: https://getstream.io/chat/docs/react/search.md) * [ Open in Gemini](https://gemini.google.com/app?query=I'm working with the Stream Chat React SDK and would like to ask questions about this documentation page: https://getstream.io/chat/docs/react/search.md) * [ Open in Grok](https://x.com/i/grok?text=I'm working with the Stream Chat React SDK and would like to ask questions about this documentation page: https://getstream.io/chat/docs/react/search.md) * [ Open in Perplexity](https://www.perplexity.ai/search/new?q=I'm working with the Stream Chat React SDK and would like to ask questions about this documentation page: https://getstream.io/chat/docs/react/search.md) On this page: * Searching Messages * Query Parameters * Message Filter Conditions * Sorting * Pagination Is this helpful? Thank you . An error has occurred.