Search code examples
google-chat

Using Google Chat webhooks to place a message inside a thread


I am in the process of writing a PowerShell script meant to send a series of incident related issues to Google Chat. I would like to be able to create & respond to threads in a scripted manner, but I have been struggling with the implementation.

I have been following the Google Documentation for Google Chat incoming webhooks, but so far with very little success. My relevant code looks a little like this:

$webhookURL = "https://chat.googleapis.com/v1/spaces/SPACE_ID/messages?threadKey=MY_KEY&key=SPACE_KEY&token=SPACE_TOKEN"
$message_headers = @{"Content-Type"="application/json"; "charset"="UTF-8"}
# Create a thread in Google Chat
Invoke-RestMethod -Method Post -Uri $webhookURL -Headers $message_headers -Body $message_body
# Respond to the same thread, with a new message_body
Invoke-RestMethod -Method Post -Uri $webhookURL -Headers $message_headers -Body $new_body

After running my code, both messages are posted independently. When I look at the 'active threads' section of google chat, it does not even indicate a thread has been created. Am I doing something wrong?


Solution

  • EDIT:

    I completely reworked this answer because I've been informed on how to work with the new threading style.

    This will soon be added to the documentation, but to support thread replies for the threaded space style you can add the URL parameter messageReplyOption=REPLY_MESSAGE_FALLBACK_TO_NEW_THREAD. The rest remains roughly the same. You can add the parameter at the end like this:

    $webhookURL = "https://chat.googleapis.com/v1/spaces/SPACE_ID/messages?threadKey=MY_KEY&key=SPACE_KEY&token=SPACE_TOKEN&messageReplyOption=REPLY_MESSAGE_FALLBACK_TO_NEW_THREAD"

    Note that you can add the threadKey in the URL to set an arbitrary key as already mentioned in the docs. This key is unique to each webhook or app and even if you use the same key with a different app it will create a different thread. However, there's a different way to also reply to existing threads, and this can be done in the POST body:

    $message_body = @{"text"="My message", "thread": {'name': '<THREAD_PATH>'}}
    

    The thread path follows the format spaces/<SPACE_ID>/threads/<THREAD_ID>. You can get this path under thread.name from the webhook response after a successful message:

     "thread": {
        "name": "spaces/<SPACE_ID>/threads/<THREAD_ID>",
        "retentionSettings": {
          "state": "PERMANENT"
        },
    

    You can also get the <THREAD_ID> from the data-topic-id HTML attribute on chat posts if you're inspecting the page, so you can potentially reply to any post with your webhook.

    Also, instead of using the threadKey as a URL parameter you can also place it in the POST body, which may be a more consistent way to use it if you also plan to reply using name:

    $message_body = @{"text"="My message", "thread": {'threadKey': '<YOUR_KEY>'}}
    

    So essentially you can work with threads in two ways:

    • Set an arbitrary key using thread.threadKey and keep replying to it with the same webhook or bot.
    • Get the path of an existing thread and set it as thread.name and reply to it from any webhook or bot.

    Most of this is how the threading previously worked, but keep in mind that the key here is the messageReplyOption parameter. Even if you send the correct POST body it won't work if you don't set this. Finally, all this applies to both Chat apps and webhooks, and I was able to test it successfully.