Wiki
Webhooks
Per-repository outbound notifications (Discord, Slack, Teams, custom) on check-in, check-out and activity summaries. Creation, message format, template variables, SSRF guard.
Introduction
A webhook sends an outbound notification to an external service (Discord, Slack, Microsoft Teams, or a URL of your choice) every time an event happens in a repository: a check-in, a check-out, or a periodic activity summary. It is the simplest way to keep a team informed without opening the client: a message drops into your channel when someone submits work.
Webhooks are configured per repository, in the admin panel of the desktop client, under the Webhooks tab. A repository can have several webhooks (for example one to Discord for the whole team, one to a private Slack for the leads).
Access and roles
Managing webhooks is reserved for repository administrators: a super admin
(admin role) on any repository, or a project_admin on the repositories
they administer. Other roles do not see this tab.
Create a webhook
- Open the admin panel, select the repository, then the Webhooks tab.
- Click Add Webhook.
- Fill in the fields, then Create.
| Field | Value |
|---|---|
| Name | A label to find it again (e.g. Discord équipe). Required. |
| URL | The webhook URL provided by the target service. Required. See Security for refused URLs. |
| Type | discord, slack, teams or custom. |
| Events | One or more of checkin, checkout, activity_summary. At least one is required. |
| Enabled | Activation toggle (visible when editing, and from the list). |
To get the URL on the Discord side: Channel settings → Integrations → Webhooks → New Webhook → Copy Webhook URL. On the Slack side: create an Incoming Webhook in the Slack app settings. On the Teams side: Connectors → Incoming Webhook on the channel.
Tutorial: Discord webhook
This is the most common case. The "get the URL" part happens entirely inside Discord, just once.
On the Discord side: get the URL
- Open Discord and go to your server. Choose (or create) the text channel that will receive the notifications, for example
#uversion. - Hover over the channel name and click the gear icon ("Edit Channel").
- In the left-hand menu, open the Integrations tab.
- Click Webhooks, then New Webhook. Discord creates one automatically, attached to this channel.
- Click the created webhook to open it. Give it a name (for example
uVersion), and check that the target channel is the right one. An avatar image is optional. - Click Copy Webhook URL. The URL looks like
https://discord.com/api/webhooks/123456789/AbCdEf....
On the uVersion side: connect the URL
- In the desktop client, open the admin panel, select the repository, then the Webhooks tab.
- Click Add Webhook.
- Name: a label for you (e.g.
Discord équipe). - URL: paste the URL copied from Discord.
- Type: choose
discord(essential so the message is formatted as a Discord embed). - Events: check the events you want, for example
checkin. - Click Create.
- On the webhook row, click Send test: a test message should appear in the Discord channel within a few seconds.
If the test fails with an HTTP 401 or 404 status, the URL is wrong or the webhook was
deleted on the Discord side: copy the URL again. If nothing arrives even though the test is green, check that you are looking at
the right channel and that the webhook has not been disabled in Discord.
Types and formats
The Type determines how uVersion formats the message before sending it. Choose the one that matches the service pointed to by the URL, otherwise the message will arrive malformed (or be rejected by the service).
| Type | Format sent |
|---|---|
discord | Discord embed (title, color, fields). |
slack | Slack payload (message blocks). |
teams | Microsoft Teams card (MessageCard). |
custom | JSON body fully defined by you: see Custom webhooks. |
Events
| Event | Triggers when… |
|---|---|
checkin | A user submits a commit to the repository. |
checkout | A user locks (checks out) one or more files. |
activity_summary | A periodic activity summary is produced by the server scheduler (daily / weekly). |
Check only what your channel needs. In a large studio, checkout can be noisy:
many teams keep only checkin and activity_summary.
Custom webhooks
With the custom type, two extra fields appear: Custom Headers (JSON)
and Custom Template (JSON). They let you integrate any service that accepts a JSON POST.
Template
The template is the JSON body that is sent. uVersion replaces the variables in double braces with the values of the event. Example:
{"text": "{{event_type}} par {{username}} dans {{repository}}"}
Available variables:
| Variable | Content |
|---|---|
{{event_type}} | Event type (checkin, checkout, activity_summary). |
{{repository}} | Repository name. |
{{username}} | User who triggered the event. |
{{message}} | Commit message (for a check-in). |
{{file_count}} | Number of files involved. |
{{commit_hash}} | Commit hash. |
{{timestamp}} | Event timestamp. |
Headers
A JSON object of HTTP headers to attach to the request, for example an authentication token:
{"Authorization": "Bearer VOTRE_JETON"}
Defaults to {} (no headers). Headers reserved for transport
(host, content-length, transfer-encoding, connection)
are stripped automatically and cannot be overridden.
Test, enable, delete
Each webhook in the list offers the following actions:
- Send test (plane icon): sends a test notification to the service and shows an inline result (green check or cross). Useful to verify the URL and the type before relying on it.
- Toggle: enables / disables the webhook without deleting it.
- Edit: modify any field.
- Delete: permanent deletion (confirmation required).
Security: SSRF guard
A webhook makes an HTTP request be issued by the server. To prevent a malicious URL from being used to probe the server's internal network (SSRF attack), uVersion applies a strict guard on creation, on modification and on test:
- The scheme must be
httporhttps. Any other scheme is refused. - The hostname is resolved via DNS, and every resulting IP address is checked. The webhook
is refused if one points to a non-public address: loopback, private networks (RFC1918), link-local,
broadcast, CGNAT range
100.64.0.0/10, cloud metadata169.254.169.254, ULA / IPv6 link-local, and their IPv4-mapped-IPv6 equivalents. - HTTP redirects are not followed (so a 307 to an internal host cannot bypass the guard).
- The upstream response body is never returned to the client (no SSRF oracle).
In practice: a webhook URL must point to a public service (Discord, Slack, Teams, or
your own endpoint reachable from the Internet). A URL to localhost, a private IP
(10.x, 192.168.x, 172.16-31.x) or an internal service is refused with a
"Webhook URL refused: …" message.
Common pitfalls
The type does not match the service
Sending a Discord format to a Slack URL (or the reverse) produces a malformed message or a rejection on the service side. The Type field must match the URL. When in doubt, do a Send test.
No event checked
A webhook with no event never triggers. The client blocks saving as long as no event is selected ("At least one event is required").
Internal URL refused
If you test against a service on your own machine or your LAN, the SSRF guard refuses it. Expose the service on a public URL (or a tunnel) to use it as a webhook target.
Forgotten disabled webhook
A disabled webhook stays in the list but sends nothing. If notifications have gone silent, check the activation toggle first before suspecting the URL.