Your team’s work already lives in HackMD: the spec, Monday’s meeting notes, the patch notes going out on Friday. The tools around it have no idea when any of that changes. So someone pastes a link into Slack by hand, or a script asks the HackMD API every few minutes whether anything is different, and usually the answer is no.
Webhooks are live. When a note or folder in the scope you choose changes, HackMD sends a signed event to a URL you control, and your tools can act on it.
A doorbell, not a copy of the note
Think of a webhook as a doorbell. You do not stand at the door checking. When something changes, HackMD knocks.
The knock is small on purpose. Each event is an HTTPS POST with a short JSON body saying what happened, such as note.updated, and which note or folder it was. It does not carry the note’s content. If your receiver needs the body, it calls the HackMD API after the event, so it always works from the latest version.
A webhook listens to one of two scopes:
- Entire workspace: every folder and note in it
- Specific folder: that folder and its subfolders. Scope follows the folder, so moving it does not break the webhook
Confirm folder.moved and folder-scope matching in production before publishing.
Every webhook receives every event in its scope, for notes and folders alike. Choosing a subset is not available yet, so filtering happens in your receiver. Editor changes are grouped: note.updated arrives when HackMD saves a revision or shortly after the last person leaves the note, not on every keystroke.
It started with GitHub and got bigger
The first request was specific: keep a whole folder of notes in step with a GitHub repo. Our built-in GitHub Sync works one note at a time, by hand, and as more of that work moved to scripts and agents, one at a time stopped holding up.
We could have built a bigger GitHub Sync. We built the layer underneath it instead, because the same problem kept showing up elsewhere: a Slack channel that should hear about new meeting notes, a Discord server waiting on patch notes, a tool polling for changes. GitHub became one recipe among several. We also want HackMD to be a better foundation to build on, and Prime raises the limits for teams that build more.
Who hears the knock
For most people writing in HackMD, nothing changes day to day. You keep writing. The tools your team connects just stop needing a nudge.
For the people wiring those tools together:
- Integration builders can replace a polling timer with one webhook and spend API quota on real work instead of empty checks
- Product and engineering teams can scope a webhook to one folder, so moving a spec into
Shippingpings engineering without the rest of the workspace joining in. That is a team convention, not an approval gate - Operations and admin teams can send new meeting notes from one folder into the Slack channel people already watch
- Community managers can announce a patch note in Discord when it is published and retract it when it is unpublished. Publishing makes a note public on Community, so keep this for notes meant to be public
Single-note GitHub Sync is unchanged. For a whole repo, there is a copy-paste recipe using GitHub Actions and a folder webhook. It is last write wins, does not sync deletions, and is not live co-editing.
Put a receiver in the middle

Do not paste a Slack or Discord webhook URL into HackMD. Those services expect their own message format. Point HackMD at a small receiver you control instead, which checks the signature, fetches what it needs from the API, and posts in the format chat expects. It has to be always on and reachable over public HTTPS, so a tool that only runs while your laptop is open will miss events.
Setting one up, and what it counts against
Open Settings → Webhook, or Team Settings → Webhook in a team. Name it, paste a public HTTPS URL, and choose a scope. Worth knowing:
- The signing secret appears once. Copy it, and have your receiver verify the
X-HackMD-Signatureheader on every delivery - Scope is fixed. To watch a different folder, delete the webhook and create a new one
- Send test event fires a
pingand does not count toward your API quota. Real deliveries do, whether they succeed or fail - Free workspaces get 1 webhook and 400 API calls a month, shared with the rest of your API use. Prime gets 10 webhooks and 20,000 calls. If quota runs out, events are skipped until it resets and are not sent later
- Recent deliveries shows the latest attempts, and the downloadable log covers 7 days on Free or 30 on Prime. It records deliveries, not every edit
Start with one folder
The easiest first build is one folder, note.created, and one Slack channel. The Webhooks Guide walks through setup, and Webhook recipes covers what to connect it to.
Your notes already know when they change, and now your tools do too. If you build something with it, or hit a wall, come tell us in Discord. 💜
