Deutsch
Deutsch
Appearance
Deutsch
Deutsch
Appearance
Webhooks benachrichtigen deine Anwendung in Echtzeit, wenn mit deinen Credentials etwas passiert — wenn eines ausgestellt, zugestellt, widerrufen oder angesehen wird. Anstatt die API abzufragen, registrierst du einen HTTPS-Endpunkt, und badges.ninja sendet ihm für jedes Ereignis, das du abonnierst, ein signiertes POST.
Alle Verwaltungsendpunkte erfordern eine Authentifizierung über den X-Api-Key-Header. Siehe Authentifizierung. Das Erstellen oder Löschen von Endpunkten erfordert einen Schlüssel mit write-Scope; das Auflisten erfordert read. Siehe API-Schlüssel.
POST /webhooks| Parameter | Typ | Erforderlich | Beschreibung |
|---|---|---|---|
url | string | Ja | Dein HTTPS-Endpunkt. Muss mit https:// beginnen. |
events | string[] | Nein | Ereignistypen, die abonniert werden sollen. Weglassen oder ["*"] übergeben, um alle Ereignisse zu empfangen. |
curl -X POST https://api.badges.ninja/webhooks \
-H "X-Api-Key: bws_your_api_key_here" \
-H "Content-Type: application/json" \
-d '{
"url": "https://example.com/hooks/badges",
"events": ["credential.issued", "credential.delivered"]
}'201 Created. Das Signatur-Secret wird nur einmal zurückgegeben — speichere es jetzt; du kannst es später nicht erneut abrufen.
{
"id": "e4b19ff5-063d-4799-bd75-d03641be624f",
"url": "https://example.com/hooks/badges",
"events": ["credential.issued", "credential.delivered"],
"secret": "2be6d335682c1658242fde3a523fd8a2493bab8c"
}GET /webhooksGibt deine registrierten Endpunkte zurück. Signatur-Secrets sind niemals enthalten.
{
"webhooks": [
{
"id": "e4b19ff5-063d-4799-bd75-d03641be624f",
"url": "https://example.com/hooks/badges",
"events": ["credential.issued", "credential.delivered"],
"active": true,
"failureCount": 0,
"createdAt": 1787685415083,
"lastStatus": 200,
"lastDeliveryAt": 1787685480777
}
]
}DELETE /webhooks/{id}curl -X DELETE https://api.badges.ninja/webhooks/e4b19ff5-063d-4799-bd75-d03641be624f \
-H "X-Api-Key: bws_your_api_key_here"Zustellungen an den Endpunkt stoppen sofort.
| Ereignis | Wird ausgelöst, wenn… |
|---|---|
credential.issued | Ein Credential an einen Empfänger ausgestellt wird. |
credential.delivered | Die Benachrichtigungs-E-Mail eines Credentials an den Empfänger gesendet wird (einzeln oder als Massenversand). |
credential.revoked | Ein Credential widerrufen wird. |
credential.viewed | Die öffentliche Credential-Seite eines Empfängers zum ersten Mal angesehen wird. |
Jede Zustellung ist ein POST mit einem JSON-Body in dieser Form:
{
"id": "b1c2d3e4-...",
"type": "credential.issued",
"createdAt": 1787685415083,
"data": { }
}| Feld | Beschreibung |
|---|---|
id | Eindeutige Zustellungs-ID (nutze sie zur Deduplizierung). |
type | Der Ereignistyp. |
createdAt | Ereignis-Zeitstempel (Epoch-Millisekunden). |
data | Ereignisspezifische Payload (siehe unten). |
data nach Ereignistyp credential.issued
{
"awardId": "https://api.badges.ninja/certify-badge/award/<guid>",
"badgeId": "https://api.badges.ninja/certify-badge/badge/<guid>",
"badgeName": "Advanced Certification",
"recipient": { "email": "jane@example.com", "name": "Jane Doe" },
"issuedOn": "2026-08-25",
"expires": null
}credential.delivered
{
"awardId": "https://api.badges.ninja/certify-badge/award/<guid>",
"recipient": { "email": "jane@example.com", "name": "Jane Doe" },
"badgeName": "Advanced Certification"
}credential.revoked
{ "awardId": "https://api.badges.ninja/certify-badge/award/<guid>", "reason": "Issued in error" }credential.viewed
{
"awardId": "https://api.badges.ninja/certify-badge/award/<guid>",
"recipient": { "email": "jane@example.com", "name": "Jane Doe" }
}Jede Zustellung trägt diese Header:
| Header | Beschreibung |
|---|---|
X-Bws-Event | Der Ereignistyp (identisch mit type im Body). |
X-Bws-Delivery | Die Zustellungs-ID (identisch mit id im Body). |
X-Bws-Signature | sha256= gefolgt vom HMAC-SHA256 des rohen Request-Bodys, mit deinem Endpunkt-Secret als Schlüssel. |
User-Agent | badges.ninja-webhooks/1 |
Verifiziere die Signatur immer, bevor du einer Zustellung vertraust. Berechne den HMAC-SHA256 des rohen Request-Bodys mit dem Signatur-Secret deines Endpunkts und vergleiche ihn (in konstanter Zeit) mit dem X-Bws-Signature-Header.
import crypto from "node:crypto";
function verify(rawBody, signatureHeader, secret) {
const expected = "sha256=" +
crypto.createHmac("sha256", secret).update(rawBody, "utf8").digest("hex");
const a = Buffer.from(signatureHeader);
const b = Buffer.from(expected);
return a.length === b.length && crypto.timingSafeEqual(a, b);
}Verwende exakt die Bytes, die du empfangen hast — das JSON zuerst zu parsen und neu zu serialisieren verändert die Bytes und macht die Signatur ungültig.
2xx-Status antwortet.failureCount an; nach 20 aufeinanderfolgenden Fehlschlägen wird ein Endpunkt automatisch deaktiviert (active: false) und empfängt keine Zustellungen mehr, bis du ihn korrigierst und einen neuen Endpunkt registrierst.X-Bws-Delivery-ID (oder die id im Body), um deinen Handler idempotent zu machen.Du kannst Endpunkte auch ohne die API verwalten — öffne Webhooks in der Seitenleiste des Dashboards, um Endpunkte hinzuzufügen, aufzulisten und zu löschen und auszuwählen, welche Ereignisse jeder Endpunkt empfängt.