WebhookサービスでローカルAPIをテストする方法

Ashley Innocent

Ashley Innocent

28 1月 2026

WebhookサービスでローカルAPIをテストする方法

外部サービスからのウェブフックやコールバックを受信する必要があるローカルホストAPIのテストでは、ローカル開発サーバーを一時的にインターネットに公開する必要があります。ngrok、NPort、Cloudflare Tunnelなどのトンネリングサービスは、ローカルホストに公開URLを提供する安全な接続を確立します。

💡
このガイドのウェブフックテストワークフローに沿って進めるには、Apidogをダウンロードしてください。このガイドでは、適切なツールの選び方、トンネリングのセットアップ方法、Apidogを使ったウェブフックの効果的なテスト方法、そして認証、レート制限、デバッグといった一般的な課題への対処法を解説します。
ダウンロード

ローカルホストトンネリングが必要な理由

あなたはサードパーティサービスと統合するAPIを構築しています。エンドポイントは正しく応答し、データはスムーズに流れるため、すべてラップトップで動作します。しかし、Stripe、GitHub、Twilio、またはその他の外部サービスからのウェブフックコールバックをテストしようとすると問題が発生します。

問題点: 外部サービスは localhost:3000 にアクセスできません。あなたの開発サーバーはインターネットからアクセスできないのです。

このことがワークフローを中断させる一般的なシナリオ:

1. ウェブフックのテスト

Stripeのようなサービスは支払い確認を、GitHubはリポジトリイベントを、Slackはインタラクションイベントを、すべてあなたのAPIへのPOSTリクエストとして送信します。開発中、これらのサービスはウェブフックを送信するための公開URLを必要とします。

2. OAuthコールバックURL

「Googleでサインイン」、「GitHubでログイン」、または任意のOAuthフローを実装する場合、認証プロバイダーは認証コードと共にユーザーをアプリケーションにリダイレクトします。リダイレクトURLは公開アクセス可能であり、プロバイダーに登録したものと一致している必要があります。

3. サードパーティAPIの統合

一部のAPIは非同期操作のためにコールバックURLを必要とします。例えば、ビデオトランスコーディングサービスは処理が完了したときにあなたのAPIに通知したり、決済処理業者は取引を確認したりします。

4. モバイルアプリ開発

同じネットワーク上のモバイルデバイスからAPIをテストすると、モバイルアプリが localhost を解決できないため、失敗することがよくあります。トンネルは、どのデバイスからでも機能するURLを提供します。

5. クライアントデモ

クライアントやステークホルダーに進捗中の作業を見せる必要がある場合があります。小さな変更ごとにステージングにデプロイすると、イテレーションが遅くなります。一時的な公開URLを使用すると、クライアントは開発環境をテストできます。

ローカルホストトンネリングの仕組み

トンネリングサービスは、そのクラウドサーバーとあなたのローカルマシン間に安全な接続を確立します。

外部サービス → トンネリングサービス(公開URL) → 安全な接続 → あなたのローカルホスト:3000

プロセス:

  1. あなたは自分のマシン上で、ローカルポートを指すトンネルクライアントを起動します
  2. クライアントはトンネリングサービスのクラウドインフラストラクチャに接続します
  3. サービスは公開URL(例: https://abc123.ngrok.io)を割り当てます
  4. その公開URLへの受信リクエストは、暗号化された接続を介してあなたのローカルホストに転送されます
  5. あなたのローカルサーバーは、クライアントから直接来たかのようにリクエストを受信します
  6. 応答はトンネルを介してリクエスト元に戻されます

これは透過的に行われます。あなたのローカルサーバーは、自分がトンネルの背後にあることを知る必要はありません。

主要なトンネリングサービスの比較

2026年における最も人気のあるオプションとその長所と短所は以下の通りです。

ngrok(最も人気)

最適用途: 確立されたプロジェクト、信頼性を求めるチーム

ngrok http 3000

長所:

短所:

無料プラン:

有料プラン: 月額8ドル〜20ドル

NPort(注目すべき無料代替サービス)

最適用途: サブスクリプション費用を避けたい開発者

nport start 3000

長所:

短所:

無料プラン:

これは、開発者が継続的な費用なしでngrokの代替を探しているため、Dev.toで注目を集めているツールです。

Cloudflare Tunnel(本番環境に近い用途に最適)

最適用途: 既にCloudflareを使用しているチーム、長期運用するトンネル

cloudflared tunnel --url http://localhost:3000

長所:

短所:

無料プラン:

Localtunnel(最もシンプル)

最適用途: 短い単発テスト、インストール不要

npx localtunnel --port 3000

長所:

短所:

無料プラン:

Tailscale Funnel(チーム向けに最適)

最適用途: プライベートなチーム共有、安全なデモ

tailscale serve https / http://localhost:3000
tailscale funnel 443 on

長所:

短所:

無料プラン:

比較表

機能ngrokNPortCloudflare TunnelLocaltunnelTailscale
価格無料/$10+無料無料無料無料/有料
セッション制限2時間なしなしなしなし
カスタムドメイン有料無料はいいいえはい
リクエスト検査はい基本いいえいいえいいえ
セットアップの複雑さ非常に低
信頼性優秀良好優秀悪い優秀
最適な用途本番テストコストを意識する開発者エンタープライズクイックテストチーム共有

初めてのローカルホストトンネルをセットアップする

最も一般的なツールを使用したセットアップについて見ていきましょう。Node.js Express APIを例として使用しますが、これは任意のローカルサーバーで動作します。

例:ローカルAPIサーバー

// server.js
const express = require('express');
const app = express();

app.use(express.json());

app.post('/webhook', (req, res) => {
  console.log('Webhook received:', req.body);
  res.json({ received: true });
});

app.get('/health', (req, res) => {
  res.json({ status: 'healthy' });
});

app.listen(3000, () => {
  console.log('Server running on http://localhost:3000');
});

オプション1:ngrokを使用する

ステップ1:ngrokをインストールする

# macOS
brew install ngrok

# Windows (via Chocolatey)
choco install ngrok

# Linux
curl -s https://ngrok-agent.s3.amazonaws.com/ngrok.asc | \
  sudo tee /etc/apt/trusted.gpg.d/ngrok.asc >/dev/null && \
  echo "deb https://ngrok-agent.s3.amazonaws.com buster main" | \
  sudo tee /etc/apt/sources.list.d/ngrok.list && \
  sudo apt update && sudo apt install ngrok

ステップ2:認証する(オプションですが推奨)

ngrok config add-authtoken YOUR_AUTH_TOKEN

ステップ3:トンネルを開始する

ngrok http 3000

出力:

Session Status                online
Account                       you@example.com (Plan: Free)
Version                       3.5.0
Region                        United States (us)
Forwarding                    https://abc123.ngrok.io -> http://localhost:3000

あなたのAPIは https://abc123.ngrok.io でアクセス可能になりました。

ステップ4:テストする

curl https://abc123.ngrok.io/health
# {"status":"healthy"}

オプション2:NPortを使用する(無料代替サービス)

ステップ1:NPortをインストールする

npm install -g nport-cli
# or
curl -sSL https://nport.io/install.sh | bash

ステップ2:トンネルを開始する

nport start 3000 --subdomain myapi

出力:

✓ Tunnel started successfully
Public URL: https://myapi.nport.io
Local URL:  http://localhost:3000

ステップ3:テストする

curl https://myapi.nport.io/health
# {"status":"healthy"}

オプション3:Cloudflare Tunnelを使用する

ステップ1:cloudflaredをインストールする

# macOS
brew install cloudflare/cloudflare/cloudflared

# Linux
wget -q https://github.com/cloudflare/cloudflared/releases/latest/download/cloudflared-linux-amd64.deb
sudo dpkg -i cloudflared-linux-amd64.deb

ステップ2:クイックトンネル(サインアップ不要)

cloudflared tunnel --url http://localhost:3000

出力:

2026-01-27T12:00:00Z INF Your quick tunnel is: https://xyz789.trycloudflare.com

永続的なトンネルの場合(Cloudflareアカウントが必要):

# Login
cloudflared tunnel login

# Create tunnel
cloudflared tunnel create myapi

# Configure and run
cloudflared tunnel --config config.yml run myapi

Apidogでウェブフックをテストする

これでローカルホストが公開アクセス可能になったので、Apidogを使用してウェブフックを体系的にテストしましょう。

トンネリングとApidogを組み合わせる理由

トンネリングはアクセスを解決し、Apidogは検証を解決します。

Apidogでのウェブフックテストのセットアップ

ステップ1:APIをインポートまたは作成する

  1. Apidogを開く

2. 新しいプロジェクトを作成

3. ウェブフックエンドポイントを追加する:

ステップ2:環境変数を設定する

2つの環境をセットアップします:

開発(トンネル経由):

{
  "base_url": "https://abc123.ngrok.io"
}

本番環境:

{
  "base_url": "https://api.yourapp.com"
}

これにより、同じエンドポイントをローカルと本番環境でワンクリックでテストできます。

ステップ3:テストシナリオを作成する

ウェブフックが到着したときに何が起こるかをテストします:

例:Stripe決済ウェブフックテスト

// Request Body
{
  "type": "payment_intent.succeeded",
  "data": {
    "object": {
      "id": "pi_test123",
      "amount": 2000,
      "currency": "usd",
      "status": "succeeded"
    }
  }
}

Apidogでのアサーション:

  1. ステータスコードが200であること
  2. 応答に received: true が含まれていること
  3. 応答時間が1000ms未満であること
  4. Content-Typeが application/json であること

ステップ4:サードパーティサービスをシミュレートする

StripeやGitHubから実際のウェブフックをトリガーする代わりに、Apidogでそれらをシミュレートします。

  1. サービスドキュメントからウェブフックペイロードの例をコピーする
  2. さまざまなシナリオ(成功、失敗、エッジケース)でテストケースを作成する
  3. トンネル経由のローカルホストに対してすべてのシナリオを実行する
  4. APIが各ケースを正しく処理することを確認する

OAuthコールバックのテスト

シナリオ: 「Googleでサインイン」を実装している

ステップ1:カスタムサブドメインでトンネルを開始する

ngrok http 3000 --subdomain myapp
# URL: https://myapp.ngrok.io

ステップ2:Google ConsoleでOAuthリダイレクトを設定する

コールバックURLを設定: https://myapp.ngrok.io/auth/google/callback

ステップ3:Apidogでフローをテストする

  1. /auth/google にリクエストを送信して認証URLを取得する
  2. リダイレクトを手動またはプログラムでフォローする
  3. コールバックが認証コードを受信することを確認する
  4. トークン交換が正しく機能することを確認する

ステップ4:トークンストレージを検証する

Apidogを使用して:

一般的な使用例

1. 決済ウェブフックのテスト(Stripe, PayPal)

課題: 決済プロバイダーは、支払い成功、返金、異議申し立てなどのイベントに対してウェブフックを送信します。

解決策:

# トンネルを開始
ngrok http 3000

# StripeダッシュボードでウェブフックURLを設定
# https://abc123.ngrok.io/webhook/stripe

# Stripe CLIを使用してテストウェブフックを転送
stripe listen --forward-to localhost:3000/webhook/stripe

# テストイベントをトリガー
stripe trigger payment_intent.succeeded

Apidogでテスト:

2. Slack/Discordボットコマンドのテスト

課題: チャットプラットフォームは、ユーザーがボタンをクリックしたりコマンドを実行したりしたときにインタラクションイベントを送信します。

解決策:

# トンネルを開始
nport start 3000 --subdomain myslackbot

# Slack APIで設定:
# インタラクティビティURL: https://myslackbot.nport.io/slack/interactions
# スラッシュコマンド: https://myslackbot.nport.io/slack/commands

Apidogでテスト:

3. SMS/音声ウェブフックのテスト(Twilio)

課題: Twilioは、SMSが届いたときや音声通話が受信されたときにウェブフックを送信します。

解決策:

cloudflared tunnel --url http://localhost:3000

TwiMLウェブフックをトンネルURLにポイントするように設定します。

Apidogでテスト:

4. モバイルアプリAPIのテスト

課題: 物理デバイスまたはエミュレーターからAPIをテストする。

localhost の問題点:

// これはモバイルデバイスから失敗する
fetch('http://localhost:3000/api/users')

トンネルによる解決策:

// これはどこからでも機能する
fetch('https://myapi.ngrok.io/api/users')

Apidogでテスト:

  1. トンネル経由のベースURLでAPIドキュメントを生成する
  2. モバイルチームと共有する
  3. モバイル開発者はライブ開発サーバーに対してテストできる
  4. 準備ができたらステージング/本番URLに切り替える

5. GitHub/GitLabウェブフックのテスト

課題: リポジトリウェブフック(プッシュ、プルリクエスト、イシュー)をローカルでテストする。

解決策:

# トンネルを開始
ngrok http 4000

# GitHubリポジトリ設定で設定:
# ウェブフックURL: https://abc123.ngrok.io/github/webhook
# コンテンツタイプ: application/json
# イベント: Push, Pull requests

Apidogでテスト:

セキュリティのベストプラクティス

ローカルホストをインターネットに公開するとセキュリティリスクが生じます。以下の実践に従ってください。

1. HTTPSのみを使用する

すべてのトンネリングサービスはデフォルトでHTTPSを提供します。トンネルにプレーンなHTTPを絶対に使用しないでください。

# 良い例
ngrok http 3000
# https://abc123.ngrok.io を作成

# 悪い例(これはしないでください)
ngrok http --scheme=http 3000

2. ウェブフック署名検証を実装する

受信ウェブフックを盲目的に信用しないでください。署名を検証してください。

const crypto = require('crypto');

function verifyStripeSignature(payload, signature, secret) {
  const expectedSignature = crypto
    .createHmac('sha256', secret)
    .update(payload)
    .digest('hex');

  return crypto.timingSafeEqual(
    Buffer.from(signature),
    Buffer.from(expectedSignature)
  );
}

app.post('/webhook/stripe', (req, res) => {
  const signature = req.headers['stripe-signature'];

  if (!verifyStripeSignature(req.body, signature, process.env.STRIPE_SECRET)) {
    return res.status(401).send('Invalid signature');
  }

  // ウェブフックを処理する
});

3. 基本認証でアクセスを制限する

トンネルに認証を追加する:

# 基本認証付きngrok
ngrok http 3000 --auth="username:password"

# 基本認証付きNPort
nport start 3000 --auth username:password

これでリクエストには認証情報が必要になります:

curl -u username:password https://abc123.ngrok.io/webhook

4. 環境固有のシークレットを使用する

ウェブフックのシークレットやAPIキーをコミットしないでください。

// .env.development
STRIPE_WEBHOOK_SECRET=whsec_test_abc123
WEBHOOK_TUNNEL_URL=https://abc123.ngrok.io

// .env.production
STRIPE_WEBHOOK_SECRET=whsec_live_xyz789
WEBHOOK_URL=https://api.yourapp.com

5. トンネルアクセスを監視する

リクエストインスペクターを使用して不審なアクティビティを監視してください。

# ngrokはウェブインターフェースを提供します:
http://localhost:4040

# すべてのリクエスト、レスポンス、リプレイアタックを表示

6. トンネルの継続時間を制限する

トンネルを無期限に実行し続けないでください。

# 1時間後にトンネルを自動的に期限切れにする
ngrok http 3000 --session-duration 1h

7. リクエスト送信元を検証する

受信IPアドレスを確認するか、許可リストを使用してください。

const allowedIPs = [
  '192.0.2.1',  // Stripe webhook IPs
  '198.51.100.0/24'
];

app.use('/webhook', (req, res, next) => {
  const clientIP = req.ip;

  if (!allowedIPs.includes(clientIP)) {
    return res.status(403).send('Forbidden');
  }

  next();
});

一般的な問題のトラブルシューティング

問題1:トンネルURLがセッションごとに変わる

問題点: 無料のngrokトンネルは、再起動ごとに変更されるランダムなURLを使用します。古いURLで設定されたウェブフックは機能しなくなります。

解決策:

  1. 静的URLには有料プランを使用する:
ngrok http 3000 --domain=myapp.ngrok.app
  1. 無料のカスタムサブドメイン付きNPortに切り替える:
nport start 3000 --subdomain myapp
# 常に https://myapp.nport.io
  1. トンネル開始時にAPI経由でウェブフックをプログラムで更新する

問題2:ウェブフックのタイムアウト

問題点: ローカルサーバーの応答に時間がかかりすぎます。Slackのようなサービスは3秒以内の応答を要求します。

解決策:

非同期で処理する:

app.post('/webhook', async (req, res) => {
  // すぐに確認応答する
  res.json({ received: true });

  // バックグラウンドで処理する
  processWebhookAsync(req.body).catch(console.error);
});

async function processWebhookAsync(data) {
  // ここで時間のかかる作業(データベース、外部APIなど)を行う
  await heavyProcessing(data);
}

テストシナリオで厳格なタイムアウト制限を設定することで、Apidogでタイムアウトをテストします。

問題3:ブラウザからのCORSエラー

問題点: トンネルURLへのリクエストを行うフロントエンドがCORSエラーになる。

解決策:

CORSヘッダーを設定する:

const cors = require('cors');

app.use(cors({
  origin: [
    'http://localhost:3001',  // あなたのフロントエンド開発サーバー
    'https://abc123.ngrok.io'  // あなたのトンネルURL
  ],
  credentials: true
}));

問題4:無料プランでのレート制限

問題点: 無料トンネルには接続制限があります(ngrok:40回/分)。

解決策:

  1. 個別の高速テストではなく、Apidogでバッチテストリクエストを行う
  2. 異なるサービスに複数のトンネルを使用する
  3. 大量にテストする場合は有料プランにアップグレードする
  4. Cloudflare TunnelやNPortのような無制限サービスに切り替える

問題5:トンネルが頻繁に切断される

問題点: ネットワークの不安定さによりトンネルが切断される。

解決策:

systemd/pm2を使用して自動再起動する:

# systemdサービスを作成する
sudo nano /etc/systemd/system/ngrok.service
[Unit]
Description=ngrok tunnel
After=network.target

[Service]
Type=simple
User=youruser
WorkingDirectory=/home/youruser
ExecStart=/usr/local/bin/ngrok http 3000
Restart=always
RestartSec=10

[Install]
WantedBy=multi-user.target
sudo systemctl enable ngrok
sudo systemctl start ngrok

問題6:特定のネットワークからトンネルに到達できない

問題点: 会社のファイアウォールや制限されたネットワークがトンネルトラフィックをブロックする。

解決策:

  1. Cloudflare Tunnelを使用する(ブロックされることはほとんどない)
  2. 自分に近いトンネルリージョンに切り替える:
ngrok http 3000 --region eu
  1. 公開トンネルの代わりにプライベートネットワークにTailscaleを使用する

高度なパターン

パターン1:マルチポートトンネリング

複数のサービスを同時に公開する:

# ターミナル1:APIサーバー
ngrok http 3000

# ターミナル2:フロントエンド開発サーバー
ngrok http 3001

# ターミナル3:ウェブフックワーカー
ngrok http 3002

またはngrok設定ファイルを使用する:

# ~/.ngrok2/ngrok.yml
tunnels:
  api:
    proto: http
    addr: 3000
  frontend:
    proto: http
    addr: 3001
  worker:
    proto: http
    addr: 3002
ngrok start --all

パターン2:トンネル + Docker Compose

# docker-compose.yml
version: '3'
services:
  api:
    build: .
    ports:
      - "3000:3000"

  ngrok:
    image: ngrok/ngrok:latest
    command:
      - "http"
      - "api:3000"
    environment:
      NGROK_AUTHTOKEN: ${NGROK_AUTHTOKEN}
docker-compose up

パターン3:動的トンネルURLの挿入

トンネルURLでアプリを自動的に更新する:

// start-tunnel.js
const ngrok = require('ngrok');
const fs = require('fs');

(async function() {
  const url = await ngrok.connect(3000);
  console.log(`Tunnel started: ${url}`);

  // .envファイルを更新
  fs.appendFileSync('.env', `\nTUNNEL_URL=${url}\n`);

  // Stripeウェブフックを更新
  await updateStripeWebhook(url);
})();

パターン4:複数の環境へのリクエスト転送

同じウェブフックを開発、ステージング、本番環境に対してテストする:

// webhook-multiplexer.js
app.post('/webhook', async (req, res) => {
  const environments = [
    'http://localhost:3000',
    'https://staging.api.com',
    'https://api.yourapp.com'
  ];

  // すべての環境に転送
  const results = await Promise.all(
    environments.map(env =>
      fetch(`${env}/webhook`, {
        method: 'POST',
        headers: req.headers,
        body: JSON.stringify(req.body)
      })
    )
  );

  res.json({ forwarded: results.length });
});

結論

ウェブフックやコールバックを受信するローカルホストAPIのテストは、変更ごとにステージングにデプロイする必要はありません。トンネリングサービスは、外部サービスが開発環境にアクセスできる一時的な公開URLを作成します。

まずはいずれかのツールの無料プランから始めてみてください。ウェブフックのテストが日々のワークフローの一部となる場合は、静的URLや追加機能のために有料プランを検討してください。しかし、ほとんどの開発者にとって、無料のトンネリングサービスとApidogのAPIテスト機能を組み合わせれば、ローカルホストAPIを効果的にテストするために必要なすべてが提供されます。

ダウンロード

ApidogでAPIデザイン中心のアプローチを取る

APIの開発と利用をよりシンプルなことにする方法を発見できる