Skip to content

Webhooks API

웹훅은 크리덴셜에 어떤 일이 일어날 때——발급, 전달, 취소, 조회될 때——애플리케이션에 실시간으로 알립니다. API를 폴링하는 대신 HTTPS 엔드포인트를 등록하면, badges.ninja가 구독한 각 이벤트마다 서명된 POST를 보냅니다.

모든 관리 엔드포인트는 X-Api-Key 헤더를 통한 인증이 필요합니다. 인증을 참조하세요. 엔드포인트를 생성하거나 삭제하려면 write 범위의 키가 필요하고, 목록 조회에는 read가 필요합니다. API 키를 참조하세요.

엔드포인트 등록

POST /webhooks

매개변수

매개변수타입필수설명
urlstring당신의 HTTPS 엔드포인트. https://로 시작해야 합니다.
eventsstring[]아니오구독할 이벤트 타입. 생략하거나 ["*"]를 전달하면 모든 이벤트를 받습니다.

예시

bash
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. 서명 시크릿은 한 번만 반환됩니다——지금 저장하세요. 다시 가져올 수 없습니다.

json
{
  "id": "e4b19ff5-063d-4799-bd75-d03641be624f",
  "url": "https://example.com/hooks/badges",
  "events": ["credential.issued", "credential.delivered"],
  "secret": "2be6d335682c1658242fde3a523fd8a2493bab8c"
}

엔드포인트 목록 조회

GET /webhooks

등록된 엔드포인트를 반환합니다. 서명 시크릿은 절대 포함되지 않습니다.

json
{
  "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}
bash
curl -X DELETE https://api.badges.ninja/webhooks/e4b19ff5-063d-4799-bd75-d03641be624f \
  -H "X-Api-Key: bws_your_api_key_here"

해당 엔드포인트로의 전달이 즉시 중단됩니다.

이벤트 타입

이벤트발생 시점…
credential.issued크리덴셜이 수신자에게 발급될 때.
credential.delivered크리덴셜의 알림 이메일이 수신자에게 전송될 때(단건 또는 대량).
credential.revoked크리덴셜이 취소될 때.
credential.viewed수신자의 공개 크리덴셜 페이지가 처음으로 조회될 때.

전달 페이로드

모든 전달은 다음 형태의 JSON 본문을 가진 POST입니다:

json
{
  "id": "b1c2d3e4-...",
  "type": "credential.issued",
  "createdAt": 1787685415083,
  "data": { }
}
필드설명
id고유한 전달 id(중복 제거에 사용).
type이벤트 타입.
createdAt이벤트 타임스탬프(에포크 밀리초).
data이벤트별 페이로드(아래 참조).

이벤트 타입별 data

credential.issued

json
{
  "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

json
{
  "awardId": "https://api.badges.ninja/certify-badge/award/<guid>",
  "recipient": { "email": "jane@example.com", "name": "Jane Doe" },
  "badgeName": "Advanced Certification"
}

credential.revoked

json
{ "awardId": "https://api.badges.ninja/certify-badge/award/<guid>", "reason": "Issued in error" }

credential.viewed

json
{
  "awardId": "https://api.badges.ninja/certify-badge/award/<guid>",
  "recipient": { "email": "jane@example.com", "name": "Jane Doe" }
}

요청 헤더

각 전달은 다음 헤더를 포함합니다:

헤더설명
X-Bws-Event이벤트 타입(본문의 type과 동일).
X-Bws-Delivery전달 id(본문의 id와 동일).
X-Bws-Signaturesha256= 뒤에, 엔드포인트 시크릿을 키로 한 원본 요청 본문의 HMAC-SHA256.
User-Agentbadges.ninja-webhooks/1

서명 검증

전달을 신뢰하기 전에 항상 서명을 검증하세요. 엔드포인트의 서명 시크릿을 사용해 원본 요청 본문의 HMAC-SHA256을 계산하고, 이를 (상수 시간으로) X-Bws-Signature 헤더와 비교하세요.

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

받은 바이트를 그대로 사용하세요——JSON을 먼저 파싱하고 다시 직렬화하면 바이트가 바뀌어 서명이 깨집니다.

재시도 및 신뢰성

  • 엔드포인트가 2xx 상태로 응답하면 전달이 성공으로 간주됩니다.
  • 실패한 전달은 몇 차례 재시도됩니다. 계속 실패하는 엔드포인트는 failureCount가 쌓이며, 20번 연속 실패하면 엔드포인트가 자동으로 비활성화되고(active: false) 이를 수정하고 새 엔드포인트를 등록할 때까지 전달 수신을 중단합니다.
  • 전달은 두 번 이상 도착할 수 있습니다. X-Bws-Delivery id(또는 본문의 id)를 사용해 핸들러를 멱등하게 만드세요.
  • 빠르게 응답하세요(약 10초 이내). 무거운 작업은 확인 응답 후 비동기로 처리하세요.

대시보드에서 웹훅 관리

API를 사용하지 않고도 엔드포인트를 관리할 수 있습니다——대시보드 사이드바에서 Webhooks를 열면 엔드포인트를 추가, 목록 조회, 삭제하고 각 엔드포인트가 받을 이벤트를 선택할 수 있습니다.

badges.ninja Documentation