Presend Message Hook

Last Edit: Nov 11 2020

Sometimes you want to have more control over what users are allowed to post and either discard or rewrite their messages when they do not meet your content guidelines.

The presend message hook works in a very similar way as regular webhooks, the difference is that your handler gets called before the message is saved to the channel. This allows you to intercept a message and make sure that it will never appear to other users.

You can use the presend message hook to enforce any of these rules:

  1. Scrub PII from messages (ie. social security numbers, credit cards, ...)

  2. Restrict contact information sharing (ie. discard phone numbers, emails)

  3. Validate messages do not include complex words that are best matched using a regular expression (regex)

Setup


await client.updateAppSettings({
    before_message_send_hook_url: 'https://path/to/endpoint/',
});
                    

Request format

Your endpoint will receive a POST request with a JSON encoded body containing: message, user and channel objects.


{
   "message":{
      "id":"",
      "text":"hello, here's my CC information 1234 1234 1234 1234",
      "html":"",
      "type":"regular",
      "attachments":[],
      "latest_reactions":[],
      "own_reactions":[],
      "reaction_counts":null,
      "reaction_scores":null,
      "reply_count":0,
      "mentioned_users":[],
      "silent":false
   },
   "user":{
     "id":"17f8ab2c-c7e7-4564-922b-e5450dbe4fe7",
     "role":"user",
     "banned":false,
     "online":false
   },
   "channel":{
      "cid":"messaging:fun-01dce6d9-c6c8-4b59-8e3c-c31631e1f7c8",
      "id":"fun-01dce6d9-c6c8-4b59-8e3c-c31631e1f7c8",
      "type":"messaging",
      "last_message_at":"2020-06-18T14:10:30.823058Z",
      "created_at":"2020-06-18T14:10:29.457799Z",
      "updated_at":"2020-06-18T14:10:29.457799Z",
      "frozen":false,
      "config":{
         "created_at":"2020-06-18T14:10:29.494022Z",
         "updated_at":"2020-06-18T14:10:29.504722Z",
         "name":"messaging",
         "typing_events":true,
         "read_events":true,
         "connect_events":true,
         "search":true,
         "reactions":true,
         "replies":true,
         "mutes":true,
         "uploads":true,
         "url_enrichment":true,
         "message_retention":"infinite",
         "max_message_length":5000,
         "automod":"disabled",
         "automod_behavior":"flag",
         "commands":[]
      }
   }
}
                    
Please make sure to follow the same security best-practices explained in the web-hooks section (https, signature validation, ...)

Response format

If you intend to make any change to the message, you should return a JSON encoded response with the same message structure. Please note that not all message fields can be changed, the full list of fields that can be modified is available in the rewriting messages section.

Discarding messages

Your endpoint can decide to disallow the message and return a user message. To do that the endpoint must return a regular message with type set to error.


{
   "message":{
      "type":"error",
      "text":"this message did not meet our content guidelines"
   }
}
                    

Rewriting messages

You can also decide to modify the message, in that case you return the updated version of the message and it will overwrite the user input.


{
   "message":{
      "text":"hello, here's my CC information **** **** **** ****"
   }
}
                    

Rewritable message fields

Not all message fields can be rewritten by your hook handler, fields such as created_at or updated_at for instance are reserved and can only be set by Stream Chat APIs. Any non custom field that is not listed here will be ignored and not updated on the final message.

  1. text

  2. i18n

  3. show_in_channel

  4. silent

  5. type

  6. attachments

  7. any custom field

Performance considerations

Your webhook endpoint will be part of the send message transaction, you should avoid performing any networking call or any slow or potentially slow operation while processing the webhook. Stream Chat will give your endpoint 1 second of time to reply. If your endpoint is not available (ie. returns a response with status codes 4xx or 5xx) or takes too long, Stream Chat will continue with the execution and save the message as usual.

To make sure that an outage on the hook does not impact your application, Stream will pause your webhook once it is considered as unreachable and it will automatically resume once the webhook is found to be healthy again.

Example presend hook

An example of how to configure this webhook can be found in this repo here.