uVersion
English
Download →

Wiki

Webhooks

Per-repository outbound notifications (Discord, Slack, Teams, custom) on check-ins 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 project versioned on the server): a check-in, 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.

Good to know The Webhooks tab uses the multi-webhook system (several entries per repository). A single-URL Discord notification also exists on the server side for compatibility, but it is not exposed here: use the webhooks described on this page.

Create a webhook

1. Open the Webhooks tab

In the admin panel, first choose the repository in the PROJECT row selector, then open the Webhooks tab of that same row: a webhook belongs to a repository. A repository that has none shows No webhooks configured.

2. Open the form

Click Add Webhook, at the top right of the tab. The Create Webhook window opens, empty.

3. Fill in the fields

Two fields are required, Name and URL, and at least one event must be selected in Events (these are clickable pills, not a drop-down list). The Type must match the service that the URL points to.

The Create Webhook window: the Name and URL fields, the Type drop-down (discord, slack, teams, custom) and the row of Events pills with checkin selected.
FieldValue
NameA label to find it again (e.g. Discord équipe). Required.
URLThe webhook URL provided by the target service. Required. See Security for refused URLs.
Typediscord, slack, teams or custom.
EventsAt least one is required. In practice: checkin and activity_summary. See Events about checkout.
EnabledActivation toggle (visible when editing, and from the list).

To get the URL on the Discord side: Channel settings → Integrations → Webhooks → New Webhook → Copy URL, detailed in the tutorial below. On the Slack side: create an Incoming Webhook in the Slack app settings. On the Teams side: Connectors → Incoming Webhook on the channel.

4. Confirm, then send a test

Click Create Webhook. The webhook appears in the list, active. On its row, click the plane icon Send test: uVersion sends a test notification to the service and shows the result at the end of the row, a green check or a cross with the returned HTTP code. Do it now: it is the only way to know the URL and the type are right before relying on this webhook.

A webhook row in the list: its toggle, its name, the discord type badge, the event pills, the Send test button and the green result check next to it.

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

  1. Open Discord and go to your server. Choose (or create) the text channel that will receive the notifications, for example #uversion.
  2. Hover over the channel name and click the gear icon ("Edit Channel").
  3. In the left-hand menu, open the Integrations tab.
  4. Click Webhooks, then New Webhook. Discord creates one automatically, attached to this channel.
  5. 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.
  6. Click Copy Webhook URL. The URL looks like https://discord.com/api/webhooks/123456789/AbCdEf....
Keep this URL secret Anyone who has the URL can post messages in your channel. Do not commit it into the repository and do not share it publicly. If it leaks, delete the webhook on the Discord side and create a new one.

On the uVersion side: connect the URL

Run through the Create a webhook procedure above with these values: Name a label for you (e.g. Discord équipe), URL the one you just copied, Type discord (essential so the message goes out as a Discord embed), Events checkin. Finish with Send test: a 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).

TypeFormat sent
discordDiscord embed (title, color, fields).
slackSlack payload (message blocks).
teamsMicrosoft Teams card (MessageCard).
customJSON body fully defined by you: see Custom webhooks.

Events

Two events are actually emitted by the server:

EventTriggers when…
checkinA user submits a commit to the repository.
activity_summaryA periodic activity summary is produced by the server scheduler (daily / weekly).
checkout: checkbox present, event never emitted The form offers a third checkbox, checkout, meant to signal the locking of a file (a lock is the reservation a user places on a file while they modify it). It is declared but never emitted to date: checking it will trigger no notification. Do not rely on it, and do not use it as the only selection: a webhook with only this event checked will stay silent forever.

Check only what your channel needs. In practice, the useful combination is checkin for the team's work feed, and activity_summary for a periodic recap.

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:

VariableContent
{{event_type}}Event type (checkin or 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.

Valid JSON required The Headers and Template fields are validated on save. Invalid JSON blocks saving with an explicit message ("Invalid JSON in headers" / "… template"). Check your braces and your quotes.

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).
The test does not return the response body On failure, uVersion reports only the HTTP status returned by the service (e.g. "Webhook returned HTTP 404"), never the content of the response. This is deliberate (see Security). If the test fails, check the URL and the type first, then the webhook's permissions on the service side.

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 http or https. 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 metadata 169.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.