Now that you got your homeserver you want some integrations right? Webhooks seems like a great place to start - it's fairly easy to set up and the use cases are virtually unlimited.

I have a couple of scenarios in Huginn for posting tomorrows weather, top voted posts from various subreddits and alerts from Grafana, to mention a few.

In this guide we will use an application service (👈 read this if you haven't) called matrix-appservice-webhooks to be able to add webhooks to a room by just issuing a command. It has a Docker image so it fits right into my standard Traefik setup. If your Synapse isn't set up like mine you'll have to make some adjustments.


First let's get the files we need for the appservice.

cd /opt/matrix # or wherever your stuff is 
mkdir matrix-appservice-webhooks
cd matrix-appservice-webhooks
curl -o database.json
curl -o config.yaml

Then we replace paths in database.json...

sed -i 's/db\//\/data\//' database.json

... so that it looks like this.

  "defaultEnv": {
    "ENV": "NODE_ENV"
  "development": {
    "driver": "sqlite3",
    "filename": "/data/development.db"
  "production": {
    "driver": "sqlite3",
    "filename": "/data/production.db"

We edit config.yaml...

nano config.yaml

... and put in the (internal) URL to Synapse - accessible via our Docker network - the public URL for our webhooks and our Matrix domain name.

  # The name here is from docker-compose.yaml
  url: "http://synapse:8008"

  # Domain for you matrix server, with subdomain if needed
  domain: ""

  # This domain will be proxied via Traefik
  hookUrlBase: ''
  # Because we're in a container
  bind: ''

☝️ I only included the settings that needs to be changed for this guide. Edit the others according to comments in the file and remember to replace

Registration file

Then we need to generate a registration file to add to Synapse via homeserver.yaml.

docker run --rm \
  -v /opt/matrix/matrix-appservice-webhooks:/data \
  turt2live/matrix-appservice-webhooks \
  node index.js -r \
  -f /data/appservice-registration-webhooks.yaml \
  -u "http://webhooks:9000" \
  -c /data/config.yaml

Now you should have a file called appservice-registration-webhooks.yaml in your appservice directory. Copy that file to your Synapse dir (/opt/matrix/synapse in my case).

sudo cp appservice-registration-webhooks.yaml ../synapse

Add/edit the line below in your homeserver.yaml, so that Synapse is aware of the appservice.

app_service_config_files: ['/data/appservice-registration-webhooks.yaml']


Time to add the container to our docker-compose.yaml.

    image: turt2live/matrix-appservice-webhooks
    restart: unless-stopped
      - synapse
      - web
      - default
      - "/opt/matrix/matrix-appservice-webhooks:/data"
      - "traefik.enable=true"
      - ""
      - "traefik.port=9000"
      - ""

☝️ If you've followed my previous guide, this should be enough. Remember to replace

Now we're all set and ready to start the service.

docker-compose up -d webhooks
docker-compose restart synapse

Adding hook to a room

Go to a room where you want to have a webhook, invite the bot user (adjust handle if you changed it in config.yaml), send the message !webhook in the room and you should see something like this 👇


Posting them hooks

Test your webhook with an app like Insomnia / Postman or just use curl.

curl --header "Content-Type: application/json" \
     --data '{
       "text": "Hello world!",
       "format": "plain",
       "displayName": "My Cool Webhook",
       "avatarUrl": ""
     }' \


Updating hooks

The first time you post the appservice will invite a virtual user with the name and avatar you set. If you change displayName on succeeding posts another user will join and if you change avatarUrl but not displayName the avatar will update.

That's it! Have fun 🎉