# Webhook Admin で最初の Webhook を送るまで（Node）

> Webhook Admin に登録してから、Node.js で顧客と送信先を作り、Webhook を送り、配信の記録で確かめ、受け側で署名を検証するまでの手順を、npm の webhookadmin と fetch のコードで示します。

公開日: 2026-11-12
Source: https://webhookadmin.com/blog/send-first-webhook-node/

## 要点

- 登録・プロジェクト・API キー・顧客と送信先・送信の 5 つの手順で、最初の Webhook が届きます。
- Node の送る側のコードは、npm の webhookadmin を使うと、顧客と送信先の作成から送信と記録の確認までで約 20 行です。
- Free プランは月 5 万通・1 プロジェクトまで無料で、テスト環境の送信と送信先への試し送信は数えません。

Webhook Admin で最初の Webhook を送るまでの手順は 5 つです。登録、プロジェクトの作成、API キーの発行、顧客と送信先の登録、送信です。Node.js なら、npm の `webhookadmin` を使って、顧客と送信先の作成から送信・記録の確認までを約 20 行で書けます。この記事では、各手順と、SDK を使わない書き方、受け側での署名の検証までを通しで示します。

## 手順の全体

1. 登録する
2. プロジェクトを作る
3. API キーを発行する
4. 顧客と送信先を登録する
5. 送信する

このあと、配信の記録で届いたことを確かめ、受け側で署名を検証します。

## 1. 登録

[https://app.webhookadmin.com/signup](https://app.webhookadmin.com/signup) で、メールアドレス・Google・GitHub のどれかで登録します。メールアドレスのときは、ログイン用のリンクがメールで届きます（15 分間有効）。最初のログインで組織（会社やチームの単位）を作ります。プラン・請求・メンバーは組織ごとです。

## 2. プロジェクト

送る側のサービス 1 つにつき、プロジェクトを 1 つ作ります。プロジェクトには本番とテストの 2 つの環境があります。

| 環境 | API キー | 送信数 |
|---|---|---|
| 本番 | `sk_live_…` | 月の上限と料金の対象 |
| テスト | `sk_test_…` | 数えない |

最初はテスト環境で試し、動いたら本番の API キーに差し替えます。

## 3. API キー

管理画面の「API キー」で、環境ごとに作ります。キーの値は作成したときに 1 回だけ表示されます。権限は次の 5 つから選びます。

| 権限 | できること |
|---|---|
| `messages:send` | メッセージの送信 |
| `messages:retry` | 送信のやり直し |
| `logs:read` | 配信の記録・顧客・送信先の参照 |
| `endpoints:write` | 送信先の登録・変更・削除、署名の鍵の切り替え |
| `consumers:write` | 顧客の登録 |

この記事のコードは顧客と送信先の作成から記録の確認までを行うので、5 つすべてを付けたキーを使います。本番のサービスに組み込むときは、送信だけを行うサーバーには `messages:send` だけを付けます。有効期限は 30 日・90 日・1 年・なしから選べ、期限の 7 日前に組織の Owner と Admin へメールで知らせます。

キーは環境変数に入れておきます。SDK は `WEBHOOK_ADMIN_API_KEY` を読みます。

```bash
npm install webhookadmin
export WEBHOOK_ADMIN_API_KEY=sk_test_...
```

## 4〜5. 顧客と送信先の登録、送信

顧客は Webhook を受け取る側の会社や利用者で、`external_id` に自社のサービスでの顧客の ID を入れます。送信先は、その顧客が Webhook を受け取る URL です。送るときは、顧客の `external_id`・イベントの種類・本文を渡すと、その顧客の送信先のうち、そのイベントを受け取るものすべてに届きます。

```ts
import { WebhookAdmin } from 'webhookadmin';

const wha = new WebhookAdmin(); // WEBHOOK_ADMIN_API_KEY（sk_test_…）を読む

// 顧客（external_id は自社のサービスでの顧客の ID）
const consumer = await wha.consumers.create({ external_id: 'cus_1024', name: 'Example Inc.' });

// 送信先（secret はこのときだけ返る）
const endpoint = await wha.endpoints.create({
  consumer_id: consumer.id,
  url: 'https://example.com/webhooks',
  event_types: ['invoice.paid'],
});
console.log(endpoint.secret); // whsec_… を受け側に渡す

// 送信（同じ Idempotency-Key は 24 時間、同じメッセージを返す）
const { id } = await wha.messages.send(
  { consumer: 'cus_1024', event_type: 'invoice.paid', payload: { invoice_id: 'inv_88', amount: 128000 } },
  { idempotencyKey: 'inv_88-paid' },
);

// 記録で確かめる
const message = await wha.messages.get(id);
const d = message.deliveries[0];
console.log(d?.status, d?.attempts[0]?.response_status, d?.attempts[0]?.response_head);
```

送信先の登録の条件は次のとおりです。

- URL は https で、ポートは 443 か 8443 です。テスト環境でも同じです。手元のサーバーで受けるときは、ngrok や cloudflared のトンネルで https の URL を付けます（[ローカルで試す方法の記事](https://webhookadmin.com/blog/test-webhooks-locally/)）。
- IP アドレスを直接書いた URL、社内向けの名前、社内のアドレスを指す名前は登録できません（422）。
- `event_types` を省くと、すべてのイベントを送ります。
- `secret` は作成したときだけ返ります。後から見るときは管理画面か、developer 以上の権限で取得します。

送信の応答は `202 Accepted` と `{ id, deliveries }` です。`deliveries` は、そのイベントが届けられる送信先の数です。`external_id` の顧客が無いときは、その場で顧客を作ります（送信先が無いので `deliveries` は 0）。

## Idempotency-Key を付ける理由

送信の API を呼ぶ自社のサーバーも、ネットワークのエラーで同じ呼び出しを 2 回行うことがあります。`Idempotency-Key` が同じ送信は、24 時間のあいだ最初のメッセージの `id` を返し、2 通目を作りません。請求書の ID とイベントの種類のように、業務の上で 1 回しか起きない組み合わせから作ります。SDK は、キーを省いた場合も自動で 1 つ作り、再試行のときに同じキーを送ります。

## SDK を使わない書き方

公開 API は JSON の HTTP API なので、`fetch` からも呼べます。

```ts
const res = await fetch('https://api.webhookadmin.com/v1/messages', {
  method: 'POST',
  headers: {
    Authorization: `Bearer ${process.env.WEBHOOK_ADMIN_API_KEY}`,
    'Content-Type': 'application/json',
    'Idempotency-Key': 'inv_88-paid',
  },
  body: JSON.stringify({
    consumer: 'cus_1024',
    event_type: 'invoice.paid',
    payload: { invoice_id: 'inv_88', amount: 128000 },
  }),
});
console.log(res.status, await res.json()); // 202 { id: 'msg_…', deliveries: 1 }
```

SDK は、この呼び出しに次のことを足しています。429 のときは `retry-after` まで待って再試行する、5xx と接続のエラーのときは安全に繰り返せる呼び出しだけを再試行する、`Idempotency-Key` を自動で付ける、応答とエラーに型を付ける、の 4 つです。

## 配信の記録での確認

届いたかどうかは、管理画面の「配信記録」か `GET /v1/messages/{id}` で確かめます。送信先ごとに、試行の時刻・応答のコード・応答の本文の先頭 1,024 バイト・所要時間・エラーが残ります。失敗していれば、応答の本文を見て受け側を直し、記録から送り直します（`POST /v1/deliveries/{id}/retry`）。

送信先への試し送信（`POST /v1/endpoints/{id}/test`）を使うと、業務のイベントを起こさずに、その送信先だけに `webhook.test` を送れます。試し送信は使用量に数えません。

## 受け側での署名の検証

送信先には、Standard Webhooks の形式の署名を付けて送ります。受け側は、手順 4 で受け取った `whsec_…` を使って、生の本文とヘッダーで検証します。

```ts
import express from 'express';
import { Webhook } from 'webhookadmin';

const wh = new Webhook(process.env.WEBHOOK_SECRET!); // whsec_…
const app = express();

// 署名は届いた本文そのもので検証するので、JSON に変換する前の本文を受け取る
app.post('/webhooks', express.raw({ type: 'application/json' }), async (req, res) => {
  try {
    const event = await wh.verify(req.body, req.headers); // { type, timestamp, data }
    console.log(event.type, event.data);
    res.sendStatus(204);
  } catch {
    res.sendStatus(400);
  }
});

app.listen(3000);
```

受け側は Webhook Admin の SDK でなくても、Standard Webhooks の公式ライブラリ（Node・Python・Go・Ruby など）で検証できます。ヘッダーと署名の作り方は[署名検証のドキュメント](https://webhookadmin.com/docs/sdk/)にあります。受け側で重複を弾くときは `webhook-id` ヘッダーを使います。再送でも同じ値が付きます。

## 無料の範囲

| 項目 | Free プラン |
|---|---|
| 本番の送信 | 月 5 万通（上限に達すると翌月 1 日（UTC）まで新しい送信を受け付けない） |
| プロジェクト | 1 つ |
| 配信の記録の保存 | 7 日 |
| 公開 API | 1 分 600 回 |
| テスト環境の送信・再送・試し送信 | 数えない |

顧客向けの画面と固定の送信元 IP は Starter プランからです。プランごとの値は[料金表](https://webhookadmin.com/#pricing)にあります。

## 次に読むもの

- 手順の詳細: [始め方](https://webhookadmin.com/docs/)の[登録](https://webhookadmin.com/docs/#signup)・[プロジェクト](https://webhookadmin.com/docs/#project)・[API キー](https://webhookadmin.com/docs/#api-key)・[顧客と送信先](https://webhookadmin.com/docs/#consumer)・[送信](https://webhookadmin.com/docs/#send)・[署名の検証](https://webhookadmin.com/docs/#verify)
- 送る側で作る物の全体: [Webhook の送信を自作するときの全工程](https://webhookadmin.com/blog/how-to-send-webhooks/)
- 署名の形式の理由: [Standard Webhooks の仕様と実装](https://webhookadmin.com/blog/standard-webhooks-explained/)

ここまでの手順は無料で試せます。[https://app.webhookadmin.com/signup](https://app.webhookadmin.com/signup) から登録し、テスト環境の API キーで最初の 1 通を送ってみてください。

## よくある質問

### 無料でどこまで使えますか。

Free プランは、本番の送信が月 5 万通まで、プロジェクトが 1 つ、配信の記録の保存が 7 日、公開 API は 1 分 600 回までです。テスト環境の送信、再送、送信先への試し送信は月の通数に数えません。顧客向けの画面と固定の送信元 IP は Starter プランからです。

### SDK を使わずに送れますか。

送れます。公開 API は JSON の HTTP API なので、fetch や curl から POST /v1/messages を呼べば送れます。SDK は、429 や 5xx のときの再試行、Idempotency-Key の自動の付与、型を足したものです。

### テスト環境の送信は数えられますか。

数えられません。プロジェクトには本番とテストの 2 つの環境があり、sk_test_ で始まる API キーで送ったものはテスト環境の送信として扱われ、月の上限と料金の対象になりません。
