# 始め方

> Webhook Admin への登録から、配信した Webhook の署名を受信側で検証するまでの手順です。

Source: https://webhookadmin.com/docs/

登録から受信側での署名検証までを、6 つの手順で説明します。

## 1. 登録

[https://app.webhookadmin.com/signup](https://app.webhookadmin.com/signup) で、メールアドレス・Google・GitHub のいずれかで登録します。メールアドレスの場合は、ログイン用のリンクをメールでお送りします（有効期間 15 分）。

初回ログイン時に組織（会社やチームの単位）を作成します。プラン・請求・メンバーは組織単位で管理します。Free プランの組織は、1 人につき 2 つまで作成できます。

## 2. プロジェクト

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

| 環境 | API キー | 配信数 |
| --- | --- | --- |
| 本番 | `sk_live_…` | 月間上限と料金の対象（配信先のエンドポイントが無いメッセージは数えません） |
| テスト | `sk_test_…` | 対象外（1 日 1,000 通まで） |

## 3. API キー

管理画面の「API キー」で、環境ごとに作成します。キーの値は作成時に 1 回だけ表示されます。スコープは次の 5 つから選択します。

| スコープ | 許可される操作 |
| --- | --- |
| `messages:send` | メッセージの送信 |
| `messages:retry` | 配信の再送信 |
| `logs:read` | 配信ログ・顧客アカウント・エンドポイントの参照 |
| `endpoints:write` | エンドポイントの登録・変更・削除、署名シークレットのローテーション |
| `consumers:write` | 顧客アカウントの登録・削除 |

有効期限は 30 日・90 日・1 年・無期限から選択します。期限の 7 日前に、組織の Owner と Admin にメールで通知します。失効させたキーは 30 秒以内に使用できなくなります。

このページのサンプルコードでは、キーを環境変数 `WEBHOOK_ADMIN_API_KEY` に設定して使用します。

```bash
export WEBHOOK_ADMIN_API_KEY=sk_test_…
```

## 4. 顧客アカウントとエンドポイント

顧客アカウントは、Webhook を受信する会社や利用者を表します。`external_id` には、自社サービスでの顧客 ID を指定します。

**curl**

```bash
curl https://api.webhookadmin.com/v1/consumers \
  -H "Authorization: Bearer $WEBHOOK_ADMIN_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "external_id": "cus_1024", "name": "株式会社サンプル" }'
```

**Node.js**

```js
const res = await fetch('https://api.webhookadmin.com/v1/consumers', {
  method: 'POST',
  headers: {
    Authorization: `Bearer ${process.env.WEBHOOK_ADMIN_API_KEY}`,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({ external_id: 'cus_1024', name: '株式会社サンプル' }),
});
const consumer = await res.json(); // { id: 'con_…', external_id: 'cus_1024', … }
```

顧客アカウントの `id` を指定して、Webhook を受信する URL をエンドポイントとして登録します。レスポンスの `secret`（`whsec_` で始まる署名シークレット）は、登録時にだけ返ります。受信側で署名を検証するときに使用します。

**curl**

```bash
curl https://api.webhookadmin.com/v1/endpoints \
  -H "Authorization: Bearer $WEBHOOK_ADMIN_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "consumer_id": "con_…",
    "url": "https://example.com/webhooks",
    "event_types": ["invoice.paid"]
  }'
```

**Node.js**

```js
const res = await fetch('https://api.webhookadmin.com/v1/endpoints', {
  method: 'POST',
  headers: {
    Authorization: `Bearer ${process.env.WEBHOOK_ADMIN_API_KEY}`,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    consumer_id: consumer.id,
    url: 'https://example.com/webhooks',
    event_types: ['invoice.paid'],
  }),
});
const endpoint = await res.json(); // { id: 'ep_…', secret: 'whsec_…', … }
```

- URL は https、ポートは 443 または 8443 を指定します。IP アドレスを直接指定した URL や、社内アドレスに解決されるホスト名は登録できません。
- `event_types` を省略すると、すべてのイベントを配信します。
- `fixed_ip: true` を指定すると、固定送信元 IP `209.71.107.233` から配信します。受信側でこの IP を許可してください。

## 5. 送信

`POST /v1/messages` に、顧客の `external_id`・イベントタイプ・ペイロードを送信します。顧客アカウントのエンドポイントのうち、そのイベントを対象とするすべてのエンドポイントに配信されます。

**curl**

```bash
curl https://api.webhookadmin.com/v1/messages \
  -H "Authorization: Bearer $WEBHOOK_ADMIN_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: inv_88-paid" \
  -d '{
    "consumer": "cus_1024",
    "event_type": "invoice.paid",
    "payload": { "invoice_id": "inv_88", "amount": 128000 }
  }'
```

**Node.js**

```js
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 },
  }),
});
const message = await res.json(); // { id: 'msg_…', deliveries: 1 }
```

**レスポンス**

```
HTTP/1.1 202 Accepted

{ "id": "msg_…", "deliveries": 1 }
```

- `Idempotency-Key` が同じリクエストには、24 時間は最初の `id` を返し、メッセージを重複して作成しません。
- `external_id` に該当する顧客アカウントが無い場合は、自動で作成します（エンドポイントが無いため `deliveries` は 0 です）。
- 配信結果は、管理画面の「配信ログ」または `GET /v1/messages/{id}` で確認できます。

## 6. 受信側での署名検証

エンドポイントへの配信には、Standard Webhooks 形式の署名が付きます。受信側では公式ライブラリで検証できます。ヘッダーと署名の生成方法は[署名検証](https://webhookadmin.com/docs/sdk/)を参照してください。

```bash
npm install standardwebhooks express
```

**Node.js（Express）**

```js
import express from 'express';
import { Webhook } from 'standardwebhooks';

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

// 署名は受信したボディそのもので検証するため、JSON に変換する前のボディを受け取る
app.post('/webhooks', express.raw({ type: 'application/json' }), (req, res) => {
  try {
    const event = wh.verify(req.body, req.headers);
    console.log(event.type, event.data);
    res.sendStatus(200);
  } catch {
    res.sendStatus(400);
  }
});

app.listen(3000);
```

`WEBHOOK_SECRET` には、手順 4 で受け取った `whsec_…` を設定します。
