SDK
エンドポイント
`webhooks.list`、`get`、`create`、`update`、`delete`、`rotateSecret`、`test`、`listDeliveries`。
すべてのメソッド
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 には移行期間がない。古いシークレットは即座に無効になるため、ローテーションの前に新しいシークレットをデプロイしておくこと。この呼び出しが自動でリトライされることはない。リトライすれば 2 回目のローテーションが起き、1 回目の試行で返されたシークレットが無効になるからである。
購読できるイベント
一覧を表示できるよう WEBHOOK_EVENTS がエクスポートされている。イベントはこの API のイベントではなく、**メールボックス**のイベントである。email.received はアプリに届いたメールに対して発火し、email.sent はコンポーザーが送信したメッセージに対して発火する。購読することは、自分の API トラフィックを監視することとは違う。
動作を確認する
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)responseCode が null の場合、応答がまったくなかったこと(DNS、TLS、タイムアウト)を意味し、0 を返した応答とは別の事実である。各行は attempt と maxAttempts を持つため、複数の行が 1 つのイベントを表すことがある。行をまたいで同一の payload.id がイベントを、試行番号が何回目の試行かを表す。
パラメーター: webhooks.create
urlstring必須- 配信の POST 先。HTTPS のみで、ホストに `localhost`、`.localhost`/`.local`/`.internal` の名前、ループバック・プライベート・CGNAT・リンクローカルの IP リテラルは指定できない。これは利用者が指定したアドレスに対するサーバー側からの fetch であるため、これらは `url` に対する 422 になる。検査はホスト名を書かれたとおりに読むだけで、DNS の解決は行わない。保存されるのは、送られた値を URL パーサーがシリアライズしたものである。そのため `https://acme.com` は `https://acme.com/` として読み出される。
eventTypesWebhookEvent[]- このエンドポイントに届くイベント。`WEBHOOK_EVENTS` に含まれる名前を指定する。`POST /webhooks` は配列の長さを、存在するイベント数を上限として制限するため、それを 1 つ超えると `eventTypes` に対する 422 になる。`PATCH` には上限がない。制限されるのは長さだけであり、同じ名前が重複していても、送ったとおりに保存され読み出される。省略または空の場合は空のリストとして保存され、読み出すと `['*']` になるのはそのためである。これは `email.replied` を除くすべての `email.*` イベント、現時点で 14 種類を意味し、ドメイン系や抑制系のイベント群は決して含まない。後から追加されたイベント群が、それを指定していないエンドポイントに届くことはない。そのため、リリースを理由に、インテグレーションが見たことのない形のデータを受け取り始めることはない。
descriptionstring- エンドポイントのラベル。最大 200 文字。Webhook の一覧が URL の列ではなく名前として読めるようにするためのもの。省略した場合は null として保存され、null として返る。
レスポンス: CreatedWebhookResource
object'webhook'- 常に `'webhook'`。通常の読み取りが返すのと同じ判別子である。シークレットは独自のオブジェクト型ではなく、通常の形に 1 つキーが増えただけだからである。`secret` が含まれるかどうかは、このフィールドではなく、どのメソッドを呼んだかによって決まる。
idstring- エンドポイントの識別子。`whe_` に続けて 16 進の 24 文字が並ぶ。他のすべての Webhook 呼び出し、すなわち `get`、`update`、`delete`、`rotateSecret`、`test`、`listDeliveries` がこの値を受け取る。
urlstring- HTTPS とホストのブロック検査を通過して保存されたエンドポイント。パースされた URL を再度シリアライズしたものであるため、比較には送った文字列ではなくこの値を使うこと。
descriptionstring | null- 指定したラベル。指定しなかった場合は null。`update` で明示的に null を送ると、値は null に戻る。
eventTypesWebhookEvent[] | ['*']- 購読しているイベント。エンドポイントが何も指定しなかった場合は `['*']`。`['*']` は、保存された空のリストが読み取り時に表現された形であり、送り返すことはできない。これはカタログ全体ではなく、13 種類のメッセージイベントを表す。`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` で置き換えるしかなく、その場合は古いものが即座に無効になる。