문서로 건너뛰기
SDK

엔드포인트

`webhooks.list`, `get`, `create`, `update`, `delete`, `rotateSecret`, `test`, `listDeliveries`.

모든 메서드

usage.ts
const endpoint = await openemail.webhooks.create({  url: 'https://acme.com/hooks/mail',  eventTypes: ['email.sent', 'email.bounced'],  description: 'Billing service',}) await store(endpoint.secret) await openemail.webhooks.list()await openemail.webhooks.get(endpoint.id)await openemail.webhooks.update(endpoint.id, { enabled: false })await openemail.webhooks.test(endpoint.id)const rotated = await openemail.webhooks.rotateSecret(endpoint.id)await openemail.webhooks.delete(endpoint.id)

시크릿이 반환되는 것은 rotateSecret을 빼면 create 때뿐입니다. 읽기 호출은 절대 시크릿을 되돌려주지 않으므로, 다른 일을 하기 전에 먼저 저장하십시오. 이후 추가될 이벤트까지 모두 받으려면 eventTypes를 생략하십시오.

rotateSecret에는 겹침 구간이 없습니다. 예전 시크릿은 즉시 동작을 멈추므로, 회전하기 전에 새 시크릿을 먼저 배포하십시오. 이 호출은 절대 자동으로 재시도되지 않습니다. 재시도하면 두 번째 회전이 일어나 첫 번째 시도가 돌려준 시크릿이 무효가 되기 때문입니다.

구독할 수 있는 이벤트

WEBHOOK_EVENTS는 목록을 렌더링할 수 있도록 내보내집니다. 이 이벤트는 이 API의 이벤트가 아니라 **메일함**의 이벤트입니다. email.received는 앱에 메일이 도착할 때 발생하고, email.sent는 작성기가 메시지를 보냈을 때 발생합니다. 구독하는 것은 자신의 API 트래픽을 지켜보는 것과 다릅니다.

동작 확인하기

webhook-test.ts
const result = await openemail.webhooks.test('whe_…')console.log(result.delivery?.status, result.delivery?.responseCode) const deliveries = await openemail.webhooks.listDeliveries('whe_…')for (const d of deliveries) console.log(d.eventType, d.status, d.responseCode, d.error)

responseCodenull이면 응답이 아예 없었다는 뜻이며(DNS, TLS, 타임아웃), 이는 응답이 0이라고 말한 것과는 다른 사실입니다. 각 행에는 attemptmaxAttempts가 담기므로 여러 행이 하나의 이벤트를 설명할 수 있습니다. 행들에 걸쳐 동일한 payload.id가 그 이벤트이고, 시도 번호가 각각의 시도입니다.

파라미터: webhooks.create

urlstring필수
전달 요청이 POST될 주소입니다. HTTPS만 허용되며, 호스트는 `localhost`, `.localhost`/`.local`/`.internal` 이름, 루프백·사설·CGNAT·링크 로컬 IP 리터럴일 수 없습니다. 여러분이 지정한 주소로 서버가 직접 요청을 보내는 것이므로 그런 값은 `url`에 대한 422이며, 이 검사는 적힌 그대로의 호스트 이름만 읽고 DNS는 조회하지 않습니다. 저장되는 값은 보낸 것을 URL 파서가 다시 직렬화한 형태이므로, `https://acme.com`은 `https://acme.com/`으로 읽힙니다.
eventTypesWebhookEvent[]
이 엔드포인트로 전달할 이벤트이며, `WEBHOOK_EVENTS`에 있는 이름 중 아무거나 지정할 수 있습니다. `POST /webhooks`는 배열 길이를 존재하는 이벤트 수만큼으로 제한하므로 그보다 하나라도 많으면 `eventTypes`에 대한 422이며, `PATCH`는 제한하지 않습니다. 제한되는 것은 길이뿐이고, 반복된 이름은 보낸 그대로 저장되어 그대로 읽힙니다. 생략하거나 비워 두면 빈 목록으로 저장되며, 그래서 읽을 때 `['*']`로 나타납니다. 이는 `email.replied`를 제외한 모든 `email.*` 이벤트, 오늘 기준 열네 개를 뜻하며 도메인이나 수신 거부 계열은 결코 포함하지 않습니다. 나중에 추가되는 계열은 그 이름을 지정하지 않은 엔드포인트에 절대 도달하지 않으므로, 릴리스 때문에 통합이 한 번도 본 적 없는 형태를 받기 시작하는 일은 없습니다.
descriptionstring
엔드포인트에 붙이는 라벨이며 최대 200자입니다. 덕분에 웹훅 목록이 URL만 늘어선 열이 아니라 이름으로 읽힙니다. 생략하면 null로 저장되고 null로 반환됩니다.

응답: CreatedWebhookResource

object'webhook'
항상 `'webhook'`이며, 일반 읽기가 반환하는 것과 같은 판별자입니다. 시크릿은 별도의 객체 타입이 아니라 평범한 형태에 키 하나가 더해진 것이기 때문입니다. `secret`이 포함되는지는 이 필드가 아니라 어떤 메서드를 호출했는지로 결정됩니다.
idstring
엔드포인트의 식별자로, `whe_` 뒤에 16진수 24자가 붙습니다. `get`, `update`, `delete`, `rotateSecret`, `test`, `listDeliveries` 등 다른 모든 웹훅 호출이 이 값을 받습니다.
urlstring
HTTPS 검사와 차단 호스트 검사를 통과해 저장된 엔드포인트 주소입니다. 파싱된 URL을 다시 직렬화한 값이므로, 보낸 문자열이 아니라 이 값과 비교하십시오.
descriptionstring | null
지정한 라벨이며, 지정하지 않았으면 null입니다. `update`로 명시적 null을 보내면 다시 null로 비워집니다.
eventTypesWebhookEvent[] | ['*']
구독한 이벤트이며, 엔드포인트가 아무것도 지정하지 않았으면 `['*']`입니다. `['*']`는 비어 있는 저장 목록이 읽을 때 표현되는 방식일 뿐 되돌려 보낼 수는 없으며, 전체 카탈로그가 아니라 열세 개의 메시지 이벤트를 뜻합니다. `create`와 `update`는 리터럴 이벤트 이름만 받습니다.
enabledboolean
전달을 시도할지 여부입니다. 비활성화된 엔드포인트는 이벤트를 발송할 때 건너뛰지만 시크릿과 전달 이력은 그대로 유지합니다. `WebhookCreate`에는 `enabled`가 없고 `WebhookPatch`에만 있으므로, 여기서는 항상 true입니다.
lastDeliveryAtstring | null
마지막 성공이 아니라 마지막 전달 시도의 ISO 8601 타임스탬프입니다. 실패한 POST 뒤에도 찍히므로, 이 값은 엔드포인트를 시도했다는 사실을 알려 주고 결과가 어땠는지는 `listDeliveries`가 알려 줍니다. 첫 시도 전까지는 null이므로 `create` 직후에는 언제나 null입니다.
createdAtstring
엔드포인트가 등록된 시각의 ISO 8601 타임스탬프입니다. `list`는 이 필드를 기준으로 최신 엔드포인트부터 반환합니다.
secretstring
각 전달의 `X-OpenEmail-Signature`에 서명하는 HMAC-SHA-256 키입니다. `whsec_` 뒤에 무작위 32바이트를 base64url로 인코딩한 값이 붙으며, `verifyWebhookSignature`에 넘기는 값입니다. `create`와 `rotateSecret`만 반환하고 그 밖에는 어디서도 반환하지 않습니다. 읽기 호출은 절대 되돌려주지 않으므로 지금 저장하십시오. 잃어버린 시크릿은 `rotateSecret`으로만 교체할 수 있으며, 그러면 예전 시크릿은 즉시 무효가 됩니다.