---
title: "Webhookok | Posty dokumentáció"
description: "A Posty szól a rendszerednek, ha egy bejegyzés kiment vagy elbukott. Események, a törzs alakja és az aláírás ellenőrzése."
canonical: https://posty.hu/de/dokumentation/automatisierung/webhooks
source: https://posty.hu/de/dokumentation/automatisierung/webhooks.md
---

Automatizálás

# Webhookok

A Posty szól a rendszerednek, ha egy bejegyzés kiment vagy elbukott. Események, a törzs alakja és az aláírás ellenőrzése.

## Wofür das da ist

Ein Webhook ist die umgekehrte Richtung: Du fragst Posty nicht ab, wir benachrichtigen dein System, wenn etwas passiert. Ein Beitrag ist rausgegangen, eine Veröffentlichung ist fehlgeschlagen, ein Kanal wurde getrennt.

Die Funktion gibt es ab dem Pro-Tarif, im linken Menü unter `Automatisierungen`, auf dem Tab `Webhooks`. Dein Tarif bestimmt, wie viele Webhooks du haben kannst.

## Webhook erstellen

1. 1
   
   Webhook hinzufügen
   
   Gib ihm einen Namen und die Adresse deines Endpunkts, der die Anfragen empfängt. Es muss eine HTTPS-Adresse sein.
2. 2
   
   Wähle die Ereignisse
   
   Du kannst ein paar auswählen oder die Liste leer lassen. Eine leere Liste bedeutet alles, auch Ereignisse, die später dazukommen.
3. 3
   
   Wähle die Kanäle
   
   Du kannst den Webhook auf bestimmte Kanäle einschränken, wenn dich nur die interessieren.
4. 4
   
   Speichere ihn und schreib das Signatur-Secret auf
   
   Das Secret beginnt mit dem Präfix `whsec_`. Im Webhook-Editor kannst du es jederzeit ansehen und neu generieren.

Eine leere Ereignisliste bedeutet alles

Wenn du kein Ereignis auswählst, bekommst du alle, auch die, die wir später hinzufügen. Wenn du sechs auswählst, bekommst du genau diese sechs, und ein siebtes, später hinzugefügtes Ereignis wird an diesen Webhook nicht zugestellt.

## Die Ereignisse

| Ereignis | Wann |
| --- | --- |
| `post.published` | Ein Beitrag ist auf einen Kanal rausgegangen. |
| `post.failed` | Ein Beitrag ist im Status Fehler gelandet: Die Plattform hat ihn abgelehnt, das Token ist ungültig geworden, der Kanal war offline oder deaktiviert, oder das Limit des Tarifs hat es nicht zugelassen. |
| `channel.disconnected` | Der Zugriff ist weggefallen, und der Kanal ist offline gegangen. Die Warteschlange dieses Kanals gibt nichts mehr raus, bis du ihn erneut verbindest. |
| `channel.refresh_needed` | Die Token-Erneuerung ist auf halbem Weg stecken geblieben. Der Kanal ist nicht offline, aber die Verbindung musst du manuell zu Ende führen. |
| `channel.disabled` | Der Kanal ist deaktiviert: Entweder hast du ihn ausgeschaltet, oder der Abrechnungsabgleich hat ihn nach einem Tarifwechsel deaktiviert. |
| `channel.enabled` | Ein ausgesetzter Kanal wurde wieder eingeschaltet. |

Es gibt kein `channel.connected`\-Ereignis: Das Verbinden ist ein mehrstufiger Ablauf, und die Zwischenzustände lohnen sich nicht zu melden.

Jede Zustellung trägt auch einen Header `X-Posty-Event`, aber verzweige auf das Feld `event` im Body. Der Header steckt nicht in der Signatur, das Feld schon.

## Der Request-Body

Der Body ist **immer ein JSON-Array**, bei jedem Ereignis. Nimm nicht an, dass die Länge immer eins ist.

### post.published

```
[
  {
    "id": "cm6tcts4f0005qcwit25cis26",
    "content": "Ez az első bejegyzés Instagramra",
    "publishDate": "2026-09-15T09:00:00.000Z",
    "releaseURL": "https://instagram.com/p/...",
    "state": "PUBLISHED",
    "integration": {
      "id": "cm6s4uyou0001i2r47pxix6z1",
      "name": "Posty",
      "providerIdentifier": "instagram",
      "picture": "https://uploads.posty.hu/...jpeg",
      "type": "social"
    },
    "event": "post.published"
  }
]
```

Kód másolása

`publishDate` ist UTC, wie jeder Zeitstempel in Posty.

### post.failed

Dasselbe Objekt, plus das Feld `error`. `state` ist `ERROR`, und `releaseURL` ist `null`, weil nichts veröffentlicht wurde. `error` ist der eigene Satz der Plattform, falls es einen gibt, sonst `null`.

### channel-Ereignisse

```
[
  {
    "event": "channel.disconnected",
    "reason": "token_revoked",
    "detail": "— access was removed in the account's Meta settings",
    "integration": {
      "id": "cm6s4uyou0001i2r47pxix6z1",
      "name": "Posty",
      "providerIdentifier": "instagram",
      "picture": "https://uploads.posty.hu/...jpeg",
      "type": "social"
    }
  }
]
```

Kód másolása

`reason` ist eine geschlossene Menge: `token_revoked`, `refresh_failed`, `manual`, `plan_limit`. Verzweige darauf. `detail` ist Freitext auf Englisch oder `null`: Das liest ein Mensch, nicht dein Code.

## Die Signatur prüfen

Jede Zustellung ist signiert, im Header `X-Posty-Signature`:

```
X-Posty-Signature: t=1770000000,v1=10bd17b41e83eee170010df01daeeaa0edf2f939afa6e97f41e1fa7bd27e6191
```

Kód másolása

- `t`: Unix-Zeit in Sekunden, UTC, im Moment der Signatur.
- `v1`: hexadezimal in Kleinbuchstaben `HMAC-SHA256(Secret, "<t>.<roher Body>")`.
- Der Schlüssel ist das eigene Signatur-Secret des Webhooks, mit dem Präfix `whsec_`.

Das ist absichtlich dieselbe Form wie bei der Stripe-Signatur, damit vorhandene Stripe-Prüfbibliotheken damit funktionieren. Du musst nur den Header-Namen und das Secret anpassen.

Signiere den rohen Body, nicht den neu serialisierten

`JSON.stringify` ist nicht kanonisch: Die Reihenfolge der Schlüssel, das Unicode-Escaping und die Formatierung der Zahlen unterscheiden sich je nach Implementierung. Ein empfangendes System, das den Body erst verarbeitet und dann wieder zum String macht, berechnet einen anderen Hashwert und lehnt eine einwandfreie Zustellung ab. Lies den Body **vor der Verarbeitung** roh aus.

### Prüfung, Schritt für Schritt

- Lies den rohen Body und den Header X-Posty-Signature aus.
- Teile den Header am Komma, dann jeden Teil am ersten Gleichheitszeichen. So bekommst du t und v1.
- Lehne ab, wenn die Differenz zwischen t und der aktuellen Zeit größer als die Toleranz ist. Wir rechnen mit 300 Sekunden Toleranz. Das ist der Replay-Schutz.
- Berechne HMAC-SHA256(Secret, t + "." + roherBody) als hexadezimalen Wert in Kleinbuchstaben.
- Vergleiche das Ergebnis mit v1, mit einem zeitkonstanten Vergleich.

Node.js

```
const crypto = require('crypto');

function verify(secret, rawBody, header, toleranceSeconds = 300) {
  const parts = Object.fromEntries(
    header.split(',').map((p) => {
      const at = p.indexOf('=');
      return [p.slice(0, at).trim(), p.slice(at + 1).trim()];
    })
  );

  const t = Number(parts.t);
  if (!Number.isFinite(t)) return false;
  if (Math.abs(Math.floor(Date.now() / 1000) - t) > toleranceSeconds) return false;

  const expected = crypto
    .createHmac('sha256', secret)
    .update(`${t}.${rawBody}`)
    .digest('hex');

  return (
    expected.length === parts.v1.length &&
    crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(parts.v1))
  );
}
```

Kód másolása

Um eine mitgeschnittene Zustellung von Hand zu prüfen, dasselbe in der Shell:

```
printf '%s' "$T.$RAW_BODY" | openssl dgst -sha256 -hmac "$SECRET" -hex
```

Kód másolása

`v1` ist absichtlich versioniert: Wenn sich das Schema jemals ändert, tragen die Zustellungen für eine Übergangszeit das alte und das neue Element. Lies das Element, dessen Namen du verstehst, und ignoriere den Rest. Geh nicht davon aus, dass der Header genau zwei Teile hat.

## Was das empfangende System wissen muss

- Verzweige auf das Feld `event` im Body, bevor du irgendetwas anderes liest, und ignoriere unbekannte Ereignisse: Es werden mehr davon kommen.
- Nimm das Feld `id` des Beitrags als Schlüssel, oder das Paar aus `integration.id` und dem Ereignis, und behandle eine wiederholte Zustellung idempotent.
- Erwarte eine Zustellung pro Kanal, nicht eine pro Gruppe, und rechne nicht mit einer bestimmten Reihenfolge.
- Bei falscher Signatur lehne die Anfrage ab und schreib sie ins Log. Nur so wird ein gefälschtes POST sichtbar.

Wenn du nicht Ereignisse empfangen, sondern abfragen willst, gibt der Endpunkt [Benachrichtigungen](https://posty.hu/de/dokumentation/api/endpunkte/ertesitesek) dieselben Ereignisse als Liste zurück.

Dokumentationsseiten

Fehlt etwas auf dieser Seite? Schreib eine E-Mail an [norbert@posty.hu](mailto:norbert@posty.hu) oder nutze auf der [Hilfeseite](https://posty.hu/de/hilfe) das Formular.
