---
title: "Webhooks: berichten posten in een mssgs-kanaal"
description: "Stuur met één HTTP-request een bericht of kaart naar een mssgs-kanaal vanuit CI, monitoring of scripts. Formaten, bestanden, ondertekenen, fouten en limieten."
canonical: https://docs.mss.gs/nl/webhooks
language: nl
---

# Berichten posten met een webhook

Een webhook is een URL die in je community post. Stuur er JSON naartoe vanuit alles wat een HTTP-request kan doen, zoals CI, monitoring, een cronjob of een script, en het bericht verschijnt in het kanaal.

## Wat je kunt doen

- **Tekst of een kaart posten** Platte tekst, of een kaart met een titel, een kleur, markdown, velden en afbeeldingen.

- **Bestanden bijvoegen** Tot vijf bestanden per bericht: logs, rapporten, screenshots.

- **Knoppen toevoegen** Links, of knoppen die de kaart veranderen of je service aanroepen.

- **Later aanpassen** Het antwoord bevat een callback-URL om het bericht bij te werken of te verwijderen.

In de app

#### Build #1847 geslaagd

Eén request vanuit CI, één kaart in #deploys. De naam bovenaan is de naam die je de webhook hebt gegeven.

- [Snel aan de slag](#quick-start)

- [Wat je kunt sturen](#format)

- [Bestanden](#attachments)

- [Ondertekenen](#signing)

- [Antwoorden en fouten](#responses)

- [Limieten](#limits)

- [GitHub, UniFi, App Store](#special)

## Snel aan de slag

### Maak de webhook aan

Open in de desktop-app bij je community **Server beheren → Webhooks**, maak een webhook aan, kies de kanalen waarin hij mag posten en kopieer de URL voor een kanaal. Die ziet er zo uit:

```url
https://mss.gs/api/v1/webhook/{webhook_guid}/{token}/{channel_guid}
```

### Stuur een bericht

Onderteken de JSON met het secret van de webhook en POST hem. Een webhook die je in de desktop-app maakt, heeft er altijd een: kopieer hem bij **Webhook Secret** in de instellingen van de webhook.

```bash
BODY='{"content": "Build #1847 passed on main"}'
SIG=$(printf '%s' "$BODY" | openssl dgst -sha256 -hmac "$MSSGS_WEBHOOK_SECRET" | sed 's/^.* //')

curl -X POST "$MSSGS_WEBHOOK_URL" \
  -H "Content-Type: application/json" \
  -H "X-Mssgs-Signature: sha256=$SIG" \
  -d "$BODY"
```

### Lees het antwoord

Het antwoord geeft je het bericht-id, en een callback_url om het bericht later aan te passen.

```json
{
  "success": true,
  "message_id": "aZZ1a2b-...",
  "callback_url": "https://mss.gs/api/v1/trigger-callback/8f14e45f-...",
  "stream_url": "https://mss.gs/api/v1/instant/6b1e...c0?token=a1b2c3d4-..."
}
```

## Wat je kunt sturen

Een bericht is de korte vorm (tekst met een titel en een kleur) of een volledige kaart, en allebei kunnen ze knoppen en bestanden meekrijgen. De naam bovenaan de kaart is altijd de eigen naam van de webhook. In de instellingen van de webhook bepaal je ook of hij afbeeldingen mag posten en mensen mag noemen.

### Korte vorm

Genoeg voor de meeste meldingen.

```json
{
  "content": "Server backup completed at 03:00 UTC",
  "color": "green",
  "title": "Backup Bot"
}
```

| Veld | Type | Wat het doet |
| --- | --- | --- |
| content | string | De berichttekst. Verplicht, tenzij je een kaart of bestanden stuurt. |
| color | string | blue (standaard), green , orange , red , yellow of purple . |
| title | string | Een titel boven de tekst. Standaard de naam van de webhook. |

### Een volledige kaart

Stuur een message_container voor een kaart met een gelinkte titel, een subtitel, markdown, velden en afbeeldingen. Via een webhook kent een kaart type , color , title , title_url , sub_title , description , fields , avatar_url , image_url , image_base64 , images en de loadervelden. De statuspill, de badge, de diff-stats en de ingeklapte redenering zijn voor antwoorden op commando's. Elk veld staat bij [berichtkaarten](https://docs.mss.gs/nl/bots).

```json
{
  "message_container": {
    "type": "embed_message",
    "color": "green",
    "title": "Build #1847 passed",
    "title_url": "https://ci.example.com/builds/1847",
    "description": "All 212 tests green on **main**.",
    "fields": [
      { "field": "Duration", "value": "2m 34s" },
      { "field": "Commit", "value": "1a2b3c4" }
    ]
  }
}
```

#### Build #1847 geslaagd

### Knoppen

Voeg een actions -array toe om knoppen onder het bericht te zetten. Hoe ze werken lees je bij [knoppen](https://docs.mss.gs/nl/buttons).

## Bestanden

Post echte bestanden bij een bericht: een log, een rapport, een screenshot. Ze verschijnen zoals elke andere bijlage, als downloadregel of, bij afbeeldingen, video en audio, direct in het bericht. Een bericht met alleen bestanden mag ook: laat content en de kaart weg.

```json
{
  "message_container": {
    "color": "orange",
    "title": "Log dump: ios",
    "description": "DMs stopped arriving after switching networks"
  },
  "attachments": [
    {
      "name": "mssgs-logs-20260803-141205.log",
      "content_base64": "MjAyNi0wOC0wMyAxNDoxMjowNSBbV1NdIGNvbm5lY3RlZAo=",
      "mime_type": "text/plain"
    }
  ]
}
```

| Veld | Type | Wat het doet |
| --- | --- | --- |
| name | string | De bestandsnaam waaronder het wordt gedownload. Verplicht. Van een pad blijft alleen het laatste deel over. |
| content_base64 | string | De bytes van het bestand als base64, kaal of als data: -URI. mssgs slaat het bestand op en bewaart alleen een link op het bericht. |
| mime_type | string | Het content type van content_base64 . Standaard text/plain . |
| url | string | Een bestand dat al op mssgs staat: een /static/... -pad of een https://mss.gs/... -URL. |

| Limiet | Waarde |
| --- | --- |
| Bestanden per bericht | **5** |
| Grootte per bestand, na decoderen | **8 MB** |
| Bestandsnaam | 200 tekens |
| Het hele request | Ongeveer 10 MB. Base64 maakt een bestand een derde groter, dus één bestand van meer dan zo'n 7 MB past er niet in. |

### Waarom url alleen mssgs-adressen accepteert

Een webhook-URL wordt vaak in andere dashboards geplakt. Een gelekte URL mag iemand niet de kans geven om de app van elk lid een bestand te laten ophalen van een server die hij zelf kiest. Staat je bestand ergens anders, stuur het dan als content_base64 en mssgs host het voor je.

### Een mislukte upload laat het bericht niet mislukken

Bestanden worden vooraf gecontroleerd, maar pas daarna geüpload. Mislukt een upload, dan valt dat bestand weg en wordt de rest van het bericht gewoon gepost, zonder foutmelding: het bestand kwijtraken is beter dan het hele rapport kwijtraken. Is een bestand belangrijk, controleer dan of het is aangekomen.

### Een bestand vanaf de commandline

```bash
BODY='{"attachments":[{"name":"report.csv","content_base64":"'"$(base64 < report.csv | tr -d '\n')"'","mime_type":"text/csv"}]}'
SIG=$(printf '%s' "$BODY" | openssl dgst -sha256 -hmac "$MSSGS_WEBHOOK_SECRET" | sed 's/^.* //')

printf '%s' "$BODY" | curl -sS -X POST "$MSSGS_WEBHOOK_URL" \
  -H 'Content-Type: application/json' \
  -H "X-Mssgs-Signature: sha256=$SIG" \
  --data-binary @-
```

## Requests ondertekenen

Een webhook met een secret accepteert alleen requests die bewijzen dat ze dat secret kennen, en een webhook die je in de desktop-app maakt, heeft er altijd een (**Webhook Secret** in zijn instellingen). Onderteken de ruwe request body met HMAC-SHA256 en het secret, en stuur de hex-digest in kleine letters mee in de header X-Mssgs-Signature , als sha256=<hex> .

```javascript
import crypto from 'node:crypto';

const body = JSON.stringify({ content: 'Deploy finished' });
const signature = crypto.createHmac('sha256', process.env.MSSGS_WEBHOOK_SECRET)
  .update(body)
  .digest('hex');

await fetch(process.env.MSSGS_WEBHOOK_URL, {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    'X-Mssgs-Signature': `sha256=${signature}`
  },
  body
});
```

De eigen header X-Hub-Signature-256 van GitHub wordt ook geaccepteerd, dus een GitHub-webhook met hetzelfde secret werkt meteen. De handtekening bevat geen tijdstempel en houdt dus niet tegen dat een onderschept request opnieuw wordt verstuurd: de URL blijft het geheim waar het om draait.

## Antwoorden en fouten

Een bericht dat is gepost, komt terug met zijn id en een callback_url om het 30 minuten lang bij te werken of te verwijderen.

```json
{
  "success": true,
  "message_id": "aZZ1a2b-...",
  "callback_url": "https://mss.gs/api/v1/trigger-callback/8f14e45f-...",
  "stream_url": "https://mss.gs/api/v1/instant/6b1e...c0?token=a1b2c3d4-..."
}
```

```http
HTTP/1.1 200 OK
Content-Type: application/json

{ "error": "ATTACHMENT_TOO_LARGE" }
```

```javascript
const res = await fetch(webhookUrl, { method: 'POST', headers, body });
const reply = await res.json().catch(() => null);

// A rejected payload still comes back as 200: read the body.
if (!res.ok || (reply && reply.error)) {
  throw new Error(`webhook rejected: ${reply?.error ?? res.status}`);
}
```

Heeft het bericht knoppen, dan bevat het antwoord ook een stream_url : een live stream van de antwoorden, reacties en knopdrukken op dat bericht, 10 minuten open, of een uur als je "sse_event_extended_timeout": true meestuurt. Zie [live-updates](https://docs.mss.gs/nl/live-updates).

### Statuscodes

| Status | Wanneer |
| --- | --- |
| 401 | De webhook heeft een secret en de handtekening ontbreekt of klopt niet. |
| 403 | Deze webhook mag niet in dat kanaal posten. |
| 404 | Er is geen webhook op deze URL. |
| 413 | Het request is te groot. |
| 429 | Te veel requests. Doe het rustiger aan en probeer het opnieuw. |
| 502 | Het bericht kon niet worden afgeleverd. Probeer het opnieuw. |

### Foutcodes

| Code | Betekenis |
| --- | --- |
| MISSING_CONTENT | Niets om te posten: geen tekst, geen kaart en geen bestanden. |
| INVALID_MESSAGE_CONTAINER | message_container is geen object. |
| INVALID_MESSAGE_CONTAINER_TYPE | Het kaarttype is niet embed_message of system_message . |
| MISSING_MESSAGE_CONTAINER_DESCRIPTION | Een kaart heeft een beschrijving nodig, tenzij het een loader is. |
| MISSING_MESSAGE_CONTAINER_LOADER_TEXT | Een loaderkaart heeft loader_text nodig. |
| INVALID_WEBHOOK_BINDING | Deze webhook mag niet in dat kanaal posten. |
| INVALID_SIGNATURE | De handtekening-header ontbreekt of klopt niet. |
| REQUEST_BODY_TOO_LARGE | Het request is groter dan de limiet. |
| PUBLISH_FAILED | Het bericht kon niet worden afgeleverd. |
| INVALID_ACTIONS_FORMAT , INVALID_ACTION_MISSING_FIELDS , DUPLICATE_ACTION_ID , INVALID_TRIGGERS_FORMAT , INVALID_TRIGGER_MISSING_ACTION , INVALID_TRIGGER_ACTION_NOT_ALLOWED | Er klopt iets niet aan een knop. Zie [knoppen](https://docs.mss.gs/nl/buttons). |

### Fouten bij bestanden

| Code | Betekenis |
| --- | --- |
| INVALID_ATTACHMENTS_FORMAT | attachments is geen lijst, of een item is geen object. |
| TOO_MANY_ATTACHMENTS | Meer dan vijf bestanden. |
| MISSING_ATTACHMENT_NAME | Een bestand heeft geen naam. |
| INVALID_ATTACHMENT_NAME | Van de naam blijft niets bruikbaars over, zoals bij .. . |
| MISSING_ATTACHMENT_SOURCE | Geen url en geen content_base64 . |
| AMBIGUOUS_ATTACHMENT_SOURCE | Zowel url als content_base64 . |
| INVALID_ATTACHMENT_BASE64 | De base64 is niet te decoderen. |
| ATTACHMENT_TOO_LARGE | Een bestand is na decoderen groter dan 8 MB. |
| INVALID_ATTACHMENT_URL | De url is geen mssgs-adres. |

## Limieten

| Limiet | Waarde |
| --- | --- |
| Grootte van een request | Ongeveer 10 MB |
| Bestanden per bericht | 5, van maximaal 8 MB per stuk |
| Beschrijving van een kaart | Tot 50.000 bytes. Voorbij 1.000 bytes zien leden het begin en een knop **Meer tonen**. |
| Het bericht achteraf bijwerken | 30 minuten, via callback_url |
| Live stream van een bericht met knoppen | 10 minuten, of een uur op verzoek |

Requests hebben een rate limit. Krijg je een 429 , wacht dan voordat je opnieuw stuurt, en bundel meldingen die in golven binnenkomen tot één bericht.

## GitHub, UniFi en App Store Connect

Wijs een van deze services naar een webhook-URL en mssgs herkent hem en post een nette kaart, zonder dat je zelf een payload hoeft te schrijven. Zie [integraties](https://mss.gs/nl/integrations). Deze antwoorden met {"success": true} en zonder callback-URL.

| Bron | Herkend aan | Wat het post |
| --- | --- | --- |
| GitHub | De header x-github-event | Pushes, pull requests en reviews, issues en reacties, branches en tags, releases. Een reeks wijzigingen aan één issue of pull request wordt samengevoegd tot één kaart. |
| UniFi Protect | De user agent protect-alarm-manager | Aanbellen, beweging, en mensen, voertuigen of pakketten die je camera's zien. |
| App Store Connect | De body van de melding of de header x-apple-signature | Meldingen van App Store Connect. |

## Verder bouwen
