Hilfecenter & Dokumentation

Alle Anleitungen und Antworten auf einen Blick, durchsuche die Dokumentation oder filtere nach Thema.

56 Artikel

Sponsoring Modul – Getting Started

Das Sponsoring-Modul hilft dir, Sponsoringprojekte zentral zu verwalten: Projekte, Pakete, Sponsoren, Rechnungen und Kampagnen in einem Workflow. Es ist aktuell noch in Beta.
Artikel lesen →

Verwalten von Text-Vorlagen

Textvorlagen für deine Vereinskommunikation anpassen: E-Mail-, SMS- und App-Nachrichten personalisieren, mit Platzhaltern und automatischer Sprachwahl.
Artikel lesen →

DigitalMembers API verwenden

Mit der DigitalMembers API kannst du Integrationen bauen und automatisieren; die API nutzt eine Standard-REST-Schnittstelle mit OAuth2 (Client Credentials). Anleitung: API-Schlüssel erstellen, Token per OAuth2 holen, Anfragen mit Bearer-Token senden, Schlüssel widerrufen und Sicherheits-Hinweise.
Artikel lesen → 24

Mitgliederverwaltung: Beiträge mit Lizenzen automatisch verrechnen

Wiederkehrende Beiträge in der Mitgliederverwaltung als Lizenz hinterlegen, Mitgliedern zuweisen und automatisch verrechnen lassen.
Artikel lesen →

Vereinsbuchhaltung einrichten: Diese Unterlagen brauchst du für den Support-Termin

Was du vor dem Support-Termin zur Einrichtung deiner Vereinsbuchhaltung bereithalten solltest: Kontoplan, QR-IBAN und Schlussbilanz des Vorjahres.
Artikel lesen →

Lohn und Leiterentschädigungen verwalten als Vorstand

Mitarbeitende und Leitende erfassen, Lohnabrechnungen erstellen, monatliche Lohnzahlungen prüfen, per Pain.001 auszahlen und nach Camt.053-Import automatisch verbuchen — der ganze Vorstands-Workflow für Vereinslöhne und Leiterentschädigungen, inkl. AHV-Schwelle und Sozialversicherungs-Standardsätze.
Artikel lesen →

Webhooks: Ereignisse automatisch an deine Systeme senden

Webhooks in DigitalMembers: Ereignisse automatisch an deine Systeme senden, Signatur und OAuth2 prüfen — mit FastAPI-Beispiel.
Artikel lesen →

Passwort zurücksetzen

Passwort für DigitalMembers zurücksetzen, von der Login-Seite oder direkt im Profil unter Sicherheit. Reset-Mail wird über die E-Mail-Adresse deines Vereins verschickt und ist persönlich angesprochen.
Artikel lesen →

Domains in den Organisationseinstellungen verwalten

Vereins-Domain in DigitalMembers hinterlegen, SPF-/DKIM-/DMARC-Records eintragen und verifizieren — Voraussetzung für hohe Zustellrate und Phishing-Schutz.
Artikel lesen →

Passkeys und Authenticator-App einrichten

Schütze dein Konto mit einem zweiten Faktor: Passkey, Sicherheitsschlüssel oder Authenticator-App. Verwaltung direkt im Profil unter Sicherheit.
Artikel lesen →

E-Mail-Versand mit Sendgrid einrichten

Sendgrid für Vereins-Mails einrichten: Domain-Verifizierung, Absender-Daten, Echtzeit-Tracking und SMTP-Fallback bei Ausfällen.
Artikel lesen →

E-Mail-Versand mit SMTP einrichten

Richte SMTP in DigitalMembers ein: Basic Auth, interner Truecode-Mailserver oder OAuth2 — Zugangsdaten eingeben, Testmail senden, fertig.
Artikel lesen →

Webhooks: Ereignisse automatisch an deine Systeme senden

APIIntegrationenSicherheit

Mit Webhooks lässt du dein eigenes System automatisch auf Ereignisse in DigitalMembers reagieren — ohne ständig nachzufragen. Sobald sich etwas ändert, schicken wir dir eine signierte Nachricht an eine von dir hinterlegte Adresse. Du prüfst sie, bestätigst den Empfang und lädst bei Bedarf die Details über die API nach.

So funktioniert es

Tritt in deiner Organisation ein Ereignis ein, senden wir eine POST-Anfrage mit einem kompakten Datensatz an deine hinterlegte Adresse. Du prüfst die Signatur, antwortest mit einem Status im 2xx-Bereich und verarbeitest die Nachricht. Antwortest du nicht mit 2xx, wiederholen wir die Zustellung automatisch mit wachsenden Abständen — du musst nichts von Hand nachtriggern.

Webhook einrichten

Webhooks verwaltest du unter Organisation → Einstellungen → Webhooks. Pro Webhook hinterlegst du eine HTTPS-Adresse und wählst die Ereignisse aus, die du abonnieren möchtest.

Die Absicherung — Signatur und optional OAuth2 — konfigurierst du einmalig pro Organisation im Bereich „Authentifizierung". Sie gilt für alle deine Webhooks. Aktiviere mindestens eine Absicherung.

Verfügbare Ereignisse

Aktuell stehen diese Ereignisse zur Verfügung:

  • member.changed — etwas rund um ein Mitglied hat sich geändert. Das Ereignis wird ausgelöst, wenn ein Mitglied erstellt, geändert oder gelöscht wird, aber auch, wenn sich ein Feld oder eine Feldzuweisung ändert. Welcher Objekttyp betroffen ist, steht im Feld data.model (members.member, members.field oder members.fieldassignment); die konkrete Aktion im Feld data.operation (created, updated, deleted).
  • registration.changed — eine Anmeldung hat sich geändert. Das Ereignis wird ausgelöst, wenn über ein öffentliches Formular eine neue Anmeldung eingeht, wenn ein Mitglied eine Profiländerung einreicht oder anpasst, oder wenn eine Anmeldung angenommen oder abgelehnt wird. Im Feld data.model steht registration.registration, die konkrete Aktion im Feld data.operation (created, updated). Über data.ids lädst du die betroffene Anmeldung bei Bedarf über die API nach.

Aufbau der Nachricht

Jede Zustellung hat denselben Aufbau: einen Umschlag mit Metadaten und ein data-Objekt, das die betroffenen Objekte beschreibt.

{
  "id": "1efdff58-1111-1111-1111-111111111111",
  "event": "member.changed",
  "version": "v2",
  "created_at": "2026-07-05T10:15:00+00:00",
  "org_id": "1efdff58-2222-2222-2222-222222222222",
  "data": {
    "ids": ["1efdff58-0000-0000-0000-000000000000"],
    "model": "members.member",
    "service": "members",
    "operation": "updated"
  }
}
  • id — eindeutige Kennung der Nachricht. Bleibt bei Wiederholungen gleich; verarbeite jede id nur einmal.
  • event — der Ereignistyp.
  • version — Version des Nachrichten-Formats. Bei einer grundlegenden Änderung erhöhen wir sie.
  • created_at — Zeitpunkt des Ereignisses.
  • org_id — die Organisation, zu der das Ereignis gehört.
  • data.ids — die Kennungen der betroffenen Objekte als Liste. Damit lädst du die Details über die API nach.
  • data.model / data.service — Objekttyp und zuständiger Bereich. data.model sagt dir, worauf sich data.ids beziehen: members.member (Mitglieder), members.field (Felder), members.fieldassignment (Feldzuweisungen) oder registration.registration (Anmeldungen). Lade je nach Typ das passende Objekt über die API nach.
  • data.operation — die Aktion: created, updated oder deleted. Bei deleted ist das Objekt über die API nicht mehr abrufbar.

Warum die Nachricht keine Personendaten enthält

Die Nachricht sagt dir bewusst nur, was sich geändert hat und wo — niemals die Inhalte selbst. Namen, Adressen oder andere Personendaten sind nie enthalten. Das hat mehrere Gründe:

  • Die Absicherung ist optional. Ein Webhook kann auch ohne OAuth2 betrieben werden. Damit selbst dann nichts Sensibles nach aussen gelangt — etwa wenn eine Adresse versehentlich falsch konfiguriert ist — enthält die Nachricht grundsätzlich keine Personendaten.
  • Du behältst die Kontrolle über deine Daten. Die eigentlichen Details holst du gezielt über die API ab, mit deinem eigenen Zugang. Ein kompromittierter Empfänger verrät so keine Mitgliederdaten.
  • Die Reihenfolge ist nicht garantiert und eine Nachricht kann in seltenen Fällen doppelt eintreffen. Behandle die Nachricht darum als Auslöser, nicht als endgültige Wahrheit: lade bei Bedarf den aktuellen Stand über die API nach, statt dich allein auf den Inhalt der Nachricht zu verlassen.

Signatur prüfen

Bei aktivierter Signatur trägt jede Zustellung zwei Kopfzeilen. Damit weist du nach, dass die Nachricht von DigitalMembers stammt und unterwegs nicht verändert wurde — auch wenn dein Endpoint sonst keine eigene Authentifizierung hat.

X-Webhook-Signature: 5257a869e7ecebeda32affa62cdca3fa51cad7e77a0e56ff536d0ce8e108d8bd
X-Webhook-Timestamp: 1720087200
  • Die Signatur ist ein HMAC-SHA256 über die Zeichenkette {timestamp}{body} mit deinem Signaturschlüssel (in den Webhook-Einstellungen über „Signaturschlüssel kopieren" abrufbar).
  • Berechne den HMAC über {X-Webhook-Timestamp}{empfangener Body} und vergleiche ihn zeitkonstant mit X-Webhook-Signature.
  • Verwirf Nachrichten, deren Zeitstempel älter als 5 Minuten ist (Schutz vor Wiederholungsangriffen).
  • Prüfe immer gegen den rohen, unveränderten Body — verarbeite den Inhalt erst nach erfolgreicher Prüfung.
import hashlib
import hmac
import time

def signature_is_valid(secret, signature, timestamp, body, tolerance_seconds=300):
    if not timestamp.isdigit() or abs(time.time() - int(timestamp)) > tolerance_seconds:
        return False
    expected = hmac.new(secret.encode(), timestamp.encode() + body, hashlib.sha256).hexdigest()
    return hmac.compare_digest(expected, signature)
Dein Signaturschlüssel ist wie ein Passwort. Bewahre ihn sicher auf, gib ihn nicht weiter und lege ihn nie in öffentlich zugänglichem Code ab. Rotiere ihn sofort, wenn der Verdacht besteht, dass er nach aussen gelangt ist — das geht jederzeit in den Webhook-Einstellungen. Für Schäden aus einem geleakten oder unsorgfältig aufbewahrten Signaturschlüssel übernimmt DigitalMembers keine Verantwortung; die sichere Aufbewahrung liegt allein in deiner Verantwortung.

OAuth2 (optional)

Zusätzlich oder alternativ zur Signatur kann jede Zustellung ein OAuth2-Token tragen. Hinterlege dazu Token-Adresse, Client-ID und Client-Secret deines eigenen Identity-Providers. Vor jeder Zustellung holt DigitalMembers per Client-Credentials-Grant ein Token bei deiner Token-Adresse ab und sendet es als Authorization: Bearer <token> mit. Da das Token von deinem eigenen Provider ausgestellt wird, prüfst du es an deinem Endpoint gegen genau diesen Provider.

Beispiel: Webhook-Empfänger mit FastAPI

Ein vollständiger Empfänger liest den rohen Body, prüft die Signatur und verarbeitet die Nachricht erst nach bestandener Prüfung.

import hashlib
import hmac
import json
import time

from fastapi import FastAPI, Header, HTTPException, Request

WEBHOOK_SECRET = "whsec_dein_signaturschluessel"
SIGNATURE_TOLERANCE_SECONDS = 300  # 5 Minuten

app = FastAPI()


def signature_is_valid(signature, timestamp, body):
    if not signature or not timestamp or not timestamp.isdigit():
        return False
    if abs(time.time() - int(timestamp)) > SIGNATURE_TOLERANCE_SECONDS:
        return False
    expected = hmac.new(WEBHOOK_SECRET.encode(), timestamp.encode() + body, hashlib.sha256).hexdigest()
    return hmac.compare_digest(expected, signature)


@app.post("/webhooks/digitalmembers")
async def receive_webhook(request: Request,
                          x_webhook_signature: str | None = Header(default=None),
                          x_webhook_timestamp: str | None = Header(default=None)):
    body = await request.body()          # rohe Bytes lesen, bevor JSON geparst wird
    if not signature_is_valid(x_webhook_signature, x_webhook_timestamp, body):
        raise HTTPException(status_code=401, detail="invalid signature")

    event = json.loads(body)
    if event["event"] == "member.changed":
        model = event["data"]["model"]            # members.member | members.field | members.fieldassignment
        object_ids = event["data"]["ids"]         # Liste der betroffenen Kennungen
        operation = event["data"]["operation"]    # created | updated | deleted
        # Details bei Bedarf über die API nachladen (mit deinem eigenen Zugang)
        handle_member_change(model, object_ids, operation)
    elif event["event"] == "registration.changed":
        registration_ids = event["data"]["ids"]   # betroffene Anmeldungen
        operation = event["data"]["operation"]    # created | updated
        handle_registration_change(registration_ids, operation)

    return {"received": True}

Hast du zusätzlich OAuth2 aktiviert, prüfst du den mitgesendeten Bearer-Token gegen deinen eigenen Identity-Provider und lehnst ungültige Token mit 401 ab.

import jwt  # pip install "pyjwt[crypto]"
from jwt import PyJWKClient

# JWKS deines eigenen Identity-Providers (derselbe, dessen Token-Adresse du hinterlegt hast)
JWKS = PyJWKClient("https://dein-idp.example.com/.well-known/jwks.json")


def bearer_is_valid(authorization):
    if not authorization or not authorization.lower().startswith("bearer "):
        return False
    token = authorization.split(" ", 1)[1]
    try:
        signing_key = JWKS.get_signing_key_from_jwt(token).key
        jwt.decode(token, signing_key, algorithms=["RS256"])  # wirft bei ungültig oder abgelaufen
        return True
    except jwt.InvalidTokenError:
        return False

Zustellung und Wiederholungen

Wir stellen jede Nachricht zuverlässig zu und wiederholen sie bei Problemen automatisch — du musst nichts von Hand nachtriggern.

  • Erwartete Antwort: Dein Endpoint muss innerhalb von 10 Sekunden mit einem Status im 2xx-Bereich antworten. Jede andere Antwort — ein Fehlerstatus, eine Zeitüberschreitung oder eine nicht erreichbare Adresse — gilt als Fehlversuch und löst eine Wiederholung aus.
  • Wiederholungen: Nach dem ersten Versuch wiederholen wir mit wachsenden Abständen: nach 5 Minuten, 15 Minuten, 30 Minuten, 2 Stunden, 6 Stunden und 24 Stunden. Das sind insgesamt 7 Zustellversuche. Antwortet dein Endpoint bei einem davon mit 2xx, gilt die Nachricht als zugestellt und wir hören auf. Kommt auch der letzte Versuch nicht durch, markieren wir die Nachricht als endgültig fehlgeschlagen.
  • Mindestens einmal: Die Zustellung erfolgt „at least once" — eine Nachricht kann in seltenen Fällen doppelt eintreffen. Dedupliziere darum über die id und verarbeite jede nur einmal (Idempotenz).
  • Reihenfolge: Die Zustellreihenfolge pro Webhook ist meist stabil, aber nicht garantiert. Verlasse dich nicht darauf; lade bei Bedarf den aktuellen Stand über die API nach.
  • Von Hand erneut zustellen: Im Zustellprotokoll im Webhook-Detail siehst du zu jeder Nachricht den Antwort-Status und die Zahl der Versuche und kannst einzelne Zustellungen jederzeit erneut auslösen.
  • Automatische Deaktivierung: Schlägt ein Webhook über längere Zeit dauerhaft fehl — rund 20 aufeinanderfolgende Fehlversuche über mindestens eine Woche ohne einen einzigen Erfolg — deaktivieren wir ihn automatisch, damit sich keine Nachrichten an eine tote Adresse stauen. Du siehst das am Webhook-Status und kannst ihn in den Einstellungen wieder aktivieren; dabei wird der Fehlerzähler zurückgesetzt.

Schutz vor Endlosschleifen: Zusätzlich gilt eine grosszügige Obergrenze an Zustellungen pro Stunde und Organisation. Löst dein System auf ein eingehendes Ereignis hin wieder eine Änderung bei uns aus, die ihrerseits ein neues Ereignis erzeugt, kann eine Schleife entstehen; wird die Obergrenze überschritten, stellen wir weitere Ereignisse in dieser Stunde nicht mehr zu — sie werden auch später nicht nachgeliefert. Gleiche den Datenstand in diesem Fall über die REST-API ab. Vermeide darum Rückschreibungen, die dasselbe Ereignis erneut auslösen.

Anforderungen an die Adresse

  • Nur https:// mit einem öffentlich erreichbaren Hostnamen.
  • Antworte schnell mit 2xx und verarbeite aufwändige Logik im Hintergrund, damit du das Zeitlimit nicht reisst.
  • Behandle deinen Signaturschlüssel wie ein Passwort und rotiere ihn bei Verdacht.

Testen

Du musst nicht auf ein echtes Ereignis warten: Sende in den Webhook-Einstellungen ein Test-Event an deinen Endpoint. Im Zustellprotokoll siehst du zu jeder Nachricht den Antwort-Status und kannst einzelne Zustellungen erneut auslösen. So prüfst du deine Signatur- und OAuth-Verifikation von Anfang bis Ende, bevor du live gehst.

Zum Ausprobieren ohne eigenes System kannst du einen Webhook auch direkt auf unseren Test-Empfänger zeigen lassen:

https://signatera.digitalmembers.ch/v2/webhooks/test/{deine-org-id}/

Der Test-Empfänger nimmt jede Zustellung an, prüft die Signatur mit deinem Signaturschlüssel und liefert das Ergebnis im Antwort-Body zurück (signature_present, signature_valid, timestamp_valid).

Verwandte Artikel

Bereit, deinen Verein zu digitalisieren?

Kostenlos testen