---
title: "Webhooks: Nachrichten in einen mssgs-Kanal posten"
description: "Poste mit einem HTTP-Request Nachrichten oder Karten aus CI, Monitoring oder Skripten in einen mssgs-Kanal. Formate, Dateien, Signatur, Fehler, Limits, GitHub."
canonical: https://docs.mss.gs/de/webhooks
language: de
---

# Nachrichten per Webhook posten

Ein Webhook ist eine URL, die in deine Community postet. Schick ihr JSON aus allem, was einen HTTP-Request senden kann, etwa CI, Monitoring, ein Cronjob oder ein Skript, und die Nachricht erscheint im Kanal.

## Was du damit machen kannst

- **Text oder eine Karte posten** Reiner Text oder eine Karte mit Titel, Farbe, Markdown, Feldern und Bildern.

- **Dateien anhängen** Bis zu fünf Dateien pro Nachricht: Logs, Berichte, Screenshots.

- **Buttons hinzufügen** Links oder Buttons, die die Karte ändern oder deinen Dienst erreichen.

- **Später ändern** Die Antwort enthält eine Callback-URL, mit der du die Nachricht aktualisierst oder löschst.

In der App

#### Build #1847 erfolgreich

Ein Request aus CI, eine Karte in #deploys. Der Name oben ist der Name, den du dem Webhook gegeben hast.

- [Schnellstart](#quick-start)

- [Was du senden kannst](#format)

- [Dateien](#attachments)

- [Signieren](#signing)

- [Antworten und Fehler](#responses)

- [Limits](#limits)

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

## Schnellstart

### Webhook anlegen

Öffne in der Desktop-App bei deiner Community **Server verwalten → Webhooks**, leg einen Webhook an, wähl die Kanäle, in die er posten darf, und kopier die URL für einen Kanal. Sie sieht so aus:

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

### Eine Nachricht senden

Signiere das JSON mit dem Secret des Webhooks und sende es per POST. Ein Webhook aus der Desktop-App hat immer eins: Kopier es unter **Webhook-Secret** in den Einstellungen des Webhooks.

```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"
```

### Die Antwort lesen

Die Antwort liefert dir die Nachrichten-ID und eine callback_url , mit der du die Nachricht später änderst.

```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-..."
}
```

## Was du senden kannst

Eine Nachricht ist entweder die Kurzform (Text mit Titel und Farbe) oder eine vollständige Karte, und beide können Buttons und Dateien tragen. Der Name oben auf der Karte ist immer der Name des Webhooks selbst. In den Einstellungen des Webhooks legst du außerdem fest, ob er Bilder posten und Leute erwähnen darf.

### Kurzform

Reicht für die meisten Alarme.

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

| Feld | Typ | Was es tut |
| --- | --- | --- |
| content | string | Der Nachrichtentext. Pflicht, außer du sendest eine Karte oder Dateien. |
| color | string | blue (Standard), green , orange , red , yellow oder purple . |
| title | string | Ein Titel über dem Text. Standardmäßig der Name des Webhooks. |

### Eine vollständige Karte

Sende einen message_container für eine Karte mit verlinktem Titel, Untertitel, Markdown, Feldern und Bildern. Über einen Webhook nimmt eine Karte type , color , title , title_url , sub_title , description , fields , avatar_url , image_url , image_base64 , images und die Loader-Felder an. Status-Pille, Badge, Diff-Statistik und eingeklappter Denkprozess sind Befehlsantworten vorbehalten. Alle Felder stehen unter [Nachrichtenkarten](https://docs.mss.gs/de/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 erfolgreich

### Buttons

Füg ein actions -Array hinzu, um Buttons unter die Nachricht zu setzen. Wie sie funktionieren, steht unter [Buttons](https://docs.mss.gs/de/buttons).

## Dateien

Poste echte Dateien mit einer Nachricht: ein Log, einen Bericht, einen Screenshot. Sie erscheinen wie jeder andere Anhang, als Download-Zeile oder, bei Bildern, Video und Audio, direkt in der Nachricht. Eine Nachricht nur mit Dateien ist in Ordnung: Lass content und die Karte 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"
    }
  ]
}
```

| Feld | Typ | Was es tut |
| --- | --- | --- |
| name | string | Der Dateiname beim Herunterladen. Pflicht. Ein Pfad wird auf seinen letzten Teil gekürzt. |
| content_base64 | string | Die Bytes der Datei als Base64, roh oder als data: -URI. mssgs speichert die Datei und behält an der Nachricht nur einen Link. |
| mime_type | string | Der Content-Type von content_base64 . Standard ist text/plain . |
| url | string | Eine Datei, die schon bei mssgs liegt: ein /static/... -Pfad oder eine https://mss.gs/... -URL. |

| Limit | Wert |
| --- | --- |
| Dateien pro Nachricht | **5** |
| Größe pro Datei, nach dem Dekodieren | **8 MB** |
| Dateiname | 200 Zeichen |
| Gesamter Request | Etwa 10 MB. Base64 macht eine Datei um ein Drittel größer, eine einzelne Datei über etwa 7 MB passt also nicht hinein. |

### Warum url nur mssgs-Adressen annimmt

Eine Webhook-URL landet oft in den Dashboards anderer Dienste. Wird sie geleakt, darf niemand damit die App jedes Mitglieds eine Datei von einem Server laden lassen, den er selbst ausgesucht hat. Liegt deine Datei woanders, sende sie als content_base64 , und mssgs hostet sie.

### Ein fehlgeschlagener Upload bringt die Nachricht nicht zum Scheitern

Dateien werden vorab geprüft, aber erst danach hochgeladen. Schlägt ein Upload fehl, fällt diese Datei weg, und der Rest der Nachricht wird trotzdem gepostet, ohne Fehler: Lieber die Datei verlieren als den Bericht. Ist eine Datei wichtig, prüf, ob sie angekommen ist.

### Eine Datei von der Kommandozeile

```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 signieren

Ein Webhook mit Secret nimmt nur Requests an, die beweisen, dass sie es kennen, und ein Webhook aus der Desktop-App hat immer eins (**Webhook-Secret** in seinen Einstellungen). Signiere den unveränderten Request-Body mit HMAC-SHA256 und dem Secret, und sende den Hex-Digest in Kleinbuchstaben im 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
});
```

Auch GitHubs eigener Header X-Hub-Signature-256 wird angenommen, ein GitHub-Webhook mit demselben Secret funktioniert also unverändert. Die Signatur hat keinen Zeitstempel und verhindert daher nicht, dass ein abgefangener Request noch einmal gesendet wird: Die URL bleibt das Geheimnis, auf das es ankommt.

## Antworten und Fehler

Eine gepostete Nachricht kommt mit ihrer ID und einer callback_url zurück, mit der du sie 30 Minuten lang aktualisieren oder löschen kannst.

```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}`);
}
```

Hat die Nachricht Buttons, enthält die Antwort außerdem eine stream_url : einen Live-Stream der Antworten, Reaktionen und Button-Drücke auf diese Nachricht, 10 Minuten lang offen, oder eine Stunde, wenn du "sse_event_extended_timeout": true mitsendest. Siehe [Live-Updates](https://docs.mss.gs/de/live-updates).

### Statuscodes

| Status | Wann |
| --- | --- |
| 401 | Der Webhook hat ein Secret, und die Signatur fehlt oder ist falsch. |
| 403 | Dieser Webhook darf nicht in diesen Kanal posten. |
| 404 | Unter dieser URL gibt es keinen Webhook. |
| 413 | Der Request ist zu groß. |
| 429 | Zu viele Requests. Mach langsamer und versuch es erneut. |
| 502 | Die Nachricht konnte nicht zugestellt werden. Versuch es erneut. |

### Fehlercodes

| Code | Bedeutung |
| --- | --- |
| MISSING_CONTENT | Nichts zu posten: kein Text, keine Karte und keine Dateien. |
| INVALID_MESSAGE_CONTAINER | message_container ist kein Objekt. |
| INVALID_MESSAGE_CONTAINER_TYPE | Der Kartentyp ist weder embed_message noch system_message . |
| MISSING_MESSAGE_CONTAINER_DESCRIPTION | Eine Karte braucht eine Beschreibung, außer sie ist ein Loader. |
| MISSING_MESSAGE_CONTAINER_LOADER_TEXT | Eine Loader-Karte braucht loader_text . |
| INVALID_WEBHOOK_BINDING | Dieser Webhook darf nicht in diesen Kanal posten. |
| INVALID_SIGNATURE | Der Signatur-Header fehlt oder ist falsch. |
| REQUEST_BODY_TOO_LARGE | Der Request überschreitet das Größenlimit. |
| PUBLISH_FAILED | Die Nachricht konnte nicht zugestellt werden. |
| INVALID_ACTIONS_FORMAT , INVALID_ACTION_MISSING_FIELDS , DUPLICATE_ACTION_ID , INVALID_TRIGGERS_FORMAT , INVALID_TRIGGER_MISSING_ACTION , INVALID_TRIGGER_ACTION_NOT_ALLOWED | Mit einem Button stimmt etwas nicht. Siehe [Buttons](https://docs.mss.gs/de/buttons). |

### Dateifehler

| Code | Bedeutung |
| --- | --- |
| INVALID_ATTACHMENTS_FORMAT | attachments ist keine Liste, oder ein Eintrag ist kein Objekt. |
| TOO_MANY_ATTACHMENTS | Mehr als fünf Dateien. |
| MISSING_ATTACHMENT_NAME | Eine Datei hat keinen Namen. |
| INVALID_ATTACHMENT_NAME | Vom Namen bleibt nichts Brauchbares übrig, etwa bei .. . |
| MISSING_ATTACHMENT_SOURCE | Weder url noch content_base64 . |
| AMBIGUOUS_ATTACHMENT_SOURCE | Sowohl url als auch content_base64 . |
| INVALID_ATTACHMENT_BASE64 | Das Base64 lässt sich nicht dekodieren. |
| ATTACHMENT_TOO_LARGE | Eine Datei ist nach dem Dekodieren größer als 8 MB. |
| INVALID_ATTACHMENT_URL | Die url ist keine mssgs-Adresse. |

## Limits

| Limit | Wert |
| --- | --- |
| Request-Größe | Etwa 10 MB |
| Dateien pro Nachricht | 5, je bis zu 8 MB |
| Kartenbeschreibung | Bis zu 50.000 Bytes. Ab 1.000 Bytes sehen Mitglieder den Anfang und einen Button **Mehr anzeigen**. |
| Die Nachricht nachträglich aktualisieren | 30 Minuten, über callback_url |
| Live-Stream einer Nachricht mit Buttons | 10 Minuten, auf Wunsch eine Stunde |

Requests sind rate-limitiert. Bekommst du eine 429 , warte, bevor du erneut sendest, und fass Alarme, die schubweise kommen, in einer Nachricht zusammen.

## GitHub, UniFi und App Store Connect

Richte einen dieser Dienste auf eine Webhook-URL, und mssgs erkennt ihn und postet eine passende Karte, ohne dass du eine Payload schreiben musst. Siehe [Integrationen](https://mss.gs/de/integrations). Diese Dienste bekommen {"success": true} als Antwort und keine Callback-URL.

| Quelle | Erkannt an | Was gepostet wird |
| --- | --- | --- |
| GitHub | Der Header x-github-event | Pushes, Pull Requests und Reviews, Issues und Kommentare, Branches und Tags, Releases. Viele Änderungen kurz hintereinander an einem Issue oder Pull Request werden in einer Karte zusammengefasst. |
| UniFi Protect | Der User-Agent protect-alarm-manager | Klingeln an der Tür, Bewegung sowie Personen, Fahrzeuge oder Pakete, die deine Kameras erkennen. |
| App Store Connect | Der Body seiner Benachrichtigungen oder der Header x-apple-signature | Benachrichtigungen von App Store Connect. |

## Weiterbauen
