Webhook URLs are public, so design them that way
A webhook URL feels private. You create it in your admin settings, copy it, and paste it into another product. But the moment you paste it, it lives in someone else’s database, their logs, their support tool, and the screenshot their support engineer sends to a colleague.
So we design every Freesbe webhook URL on the assumption that it will be seen by people we’ll never meet. Three rules came out of that.
Rule 1: nothing readable about the customer
A Freesbe webhook URL never contains a workspace name, a company name, a channel name or anything a person could read and learn from:
https://api.freesbe.net/hooks/custom/<random id>/<secret token>
It’s tempting to make URLs friendly, like /hooks/northwind-traders/alerts. But a friendly URL
tells everyone who sees it who your customer is and what they use. A random id tells them nothing.
The token is the secret, so anyone who has the URL can post, and anyone who doesn’t, can’t guess
it. Admins can rotate a token at any time, and the old one stops working at once.
Rule 2: the path matches the settings page
Built-in integrations follow the same shape, with the category and provider in the path:
/hooks/<category>/<provider>/<token>
/hooks/finance/mercury/<token>
/hooks/monitoring/pagerduty/<token>
The category and provider are the same words a person sees under Workspace settings → Integrations. That makes support easy: when a customer pastes a URL into a support chat, we know at a glance which integration it belongs to, without the URL saying anything about the customer.
Rule 3: old URLs work forever
Once you give a URL to another product, you have to assume it’ll never be updated. Nobody goes back into their monitoring tool to change a webhook because the receiving end reorganised its URLs.
So when we moved to the paths above, every older URL kept working, and any future change will do the same. It costs us a route that never goes away. Breaking a customer’s alerts silently would cost a lot more.
Bonus: accept the payloads people already send
The most useful decision about incoming webhooks wasn’t the URL, it was the body. Freesbe’s
incoming webhooks accept the same JSON as Slack’s: text, Block Kit blocks, attachments
with colours and fields, username and icons, answered with ok just like Slack. They also take
the Adaptive Cards that tools send to Microsoft Teams.

That means moving an integration to Freesbe is changing one URL. Every CI system, monitoring tool and home-grown script that already posts to a Slack or Teams channel works unchanged.
What we turned down
- Readable URLs with the workspace’s name. Nicer to look at, and a small leak every time one is pasted somewhere.
- Versioned URLs that expire. Good hygiene in theory; in practice, alerts that stop arriving on a Saturday night.
- Our own payload format only. Cleaner to design, and a reason for every customer to rewrite every integration before switching.
What we’d tell another team
Write down your URL rules before your second integration, not after your twentieth. Ours fit in three lines, and every new integration follows them without a discussion.
See API and webhooks in the help center to set one up.