DevTunnels Webhook Example¶
Demonstrates Aspire 13's DevTunnels feature for exposing local services to the public internet, enabling webhook development and testing.
📋 Overview¶
This example shows how to:
- Expose local APIs to the internet using Azure DevTunnels
- Receive webhooks from external services during local development
- Support both public (anonymous) and private (authenticated) tunnel access
- View webhooks in real-time with a React dashboard
🏗️ Architecture¶
flowchart TB
External["External Webhook Provider<br/>(Any Service)"] --> DevTunnel
subgraph DevTunnel["DevTunnel (Azure)"]
Public["Public: https://xxx-23001...<br/>Anonymous access for webhooks"]
Private["Private: https://xxx-23002...<br/>Authenticated access for testing"]
end
DevTunnel --> API
subgraph API["WebhookReceiver.Api"]
PublicEndpoint["public endpoint :23001<br/>Receives webhooks"]
InternalEndpoint["internal endpoint :23002<br/>Admin/dashboard access"]
end
API --> Dashboard["WebhookReceiver.Dashboard<br/>(React/Vite/TypeScript)<br/>View webhooks in real-time"]
🧩 Components¶
| Project | Description |
|---|---|
WebhookReceiver.Api |
.NET Minimal API with named Kestrel endpoints (public/internal) |
WebhookReceiver.Dashboard |
React/Vite/TypeScript app for viewing webhooks |
WebhookReceiver.AppHost |
Aspire orchestration with DevTunnel configuration |
🔑 Key Features¶
- Named Endpoints: API exposes
public(23001) andinternal(23002) endpoints via Kestrel - Dual Tunnel Access: Public endpoint is anonymous, internal endpoint requires authentication
- Persistent Tunnel ID: Uses named tunnel for consistent identification and token generation
- Token Authentication: Supports DevTunnel tokens for secure access to private endpoint
- Service Discovery: Dashboard receives tunnel URL via Aspire's service discovery
- Custom Commands: "Delete Tunnel" command in Aspire dashboard to reset the tunnel
📂 Project Structure¶
foundry/dotnet/devtunnels-simple-webhook/
├── WebhookReceiver.sln
├── webhook.http # Test requests
├── WebhookReceiver.AppHost/
│ └── Program.cs # Aspire with DevTunnel config
├── WebhookReceiver.Api/
│ └── Program.cs # Webhook endpoints
└── WebhookReceiver.Dashboard/ # React frontend
├── src/
└── package.json
🚀 Getting Started¶
Prerequisites¶
- .NET 10.0 SDK
- Node.js 22.x or 24.x and npm
- DevTunnel CLI (authenticated with
devtunnel user login)
Running the Example¶
- Install Dashboard dependencies:
- Start with Aspire:
- Get Tunnel URLs from the Aspire Dashboard
📡 API Endpoints¶
| Endpoint | Method | Description |
|---|---|---|
/api/webhooks |
POST | Receive a webhook |
/api/webhooks |
GET | List all webhooks |
/api/webhooks/{id} |
GET | Get webhook by ID |
/api/webhooks |
DELETE | Clear all webhooks |
/api/webhooks/count |
GET | Get webhook count |
/health |
GET | Health check |
💡 Use Cases¶
- Third-Party Integrations: Test Stripe, GitHub, or other webhook integrations locally
- Development Workflows: Share local APIs with teammates for testing
- Demo Environments: Expose local services for demonstrations
🔗 Related Documentation¶
- Aspire Reference - Aspire fundamentals and configuration
- API Integration Testing - Testing distributed applications
- Microsoft DevTunnels Documentation - Official DevTunnels docs