Skip to content
Login

Webhooks

HLE webhook tunnels let external services (GitHub, Stripe, GitLab, etc.) deliver HTTP callbacks to your home lab without opening ports or configuring dynamic DNS.

How it works

Webhook tunnels are a specialized mode of HLE tunnels designed for incoming HTTP callbacks:

  • No authentication gate — external services can reach your endpoint directly (no SSO prompt)
  • HTTP-only — WebSocket is disabled (webhooks are simple POST/GET requests)
  • Path-restricted — only requests matching your webhook path prefix are forwarded
  • Randomized URL — the subdomain includes a cryptographic token to prevent enumeration

When you create a webhook tunnel, HLE generates a URL like:

https://wh-a3f7b2c9e1d0f485-x7k.hle.world/hook/github

The wh- prefix and 16-character hex token make the URL unguessable. Your 3-character user code (x7k) is appended so the URL updates automatically if you purchase a custom tunnel code.

Quick start

Terminal window
# Forward GitHub webhooks to a local service
hle webhook --path /hook/github --forward-to http://localhost:3000/webhook
# Forward Stripe webhooks
hle webhook --path /stripe --forward-to http://localhost:4242/stripe/webhook
# With a custom label (used for custom zones only)
hle webhook --path /hook --forward-to http://localhost:8080 --label my-webhook

The CLI prints the public URL you can paste into your webhook provider’s settings.

Security

Randomized subdomains

Unlike regular tunnels (e.g. myapp-x7k.hle.world), webhook tunnels use a randomized subdomain with 16 hex characters (2^64 possibilities). This prevents attackers from guessing your webhook URL.

Server-side path enforcement

The HLE relay server enforces that incoming requests match the registered webhook path prefix. Even if someone discovers your webhook URL, they can only reach the specific path you configured — not your entire local service.

Signature verification

Most webhook providers sign their payloads:

ProviderHeaderDocs
GitHubX-Hub-Signature-256Securing webhooks
StripeStripe-SignatureCheck signatures
GitLabX-Gitlab-TokenWebhook secrets
SlackX-Slack-SignatureVerifying requests

Rate limits

Webhook tunnels have per-tier rate limits to prevent abuse:

PlanWebhooks/minWebhook tunnels
Free301
Pro603
Business12010

Rate limit headers are included in every response:

X-RateLimit-Limit: 60
X-RateLimit-Remaining: 42

When the limit is exceeded, the server returns HTTP 429 with a Retry-After: 60 header.

Payload limits

  • Maximum body size: 10 MB per request
  • Requests exceeding this limit receive HTTP 413

CLI reference

hle webhook

Create a webhook tunnel.

FlagTypeDefaultDescription
--pathstringrequiredWebhook path prefix (e.g. /hook/github)
--forward-tostringrequiredLocal URL to forward webhooks to
--labelstringauto-generatedService label (used for custom zones)
--api-keystringAPI key (also checked in HLE_API_KEY and config file)
--zonestringCustom zone domain

Examples

GitHub → self-hosted Gitea

Forward push events from GitHub to a Gitea mirror:

Terminal window
hle webhook --path /hook/github --forward-to http://localhost:3000/api/v1/repos/mirror/hooks/trigger

In GitHub repository settings → Webhooks → Add webhook:

  • Payload URL: paste the HLE URL from the CLI output
  • Content type: application/json
  • Secret: set a secret and verify it in your Gitea config

Stripe → local dev server

Test Stripe webhooks against your development environment:

Terminal window
hle webhook --path /stripe --forward-to http://localhost:4242/webhook

In the Stripe Dashboard → Developers → Webhooks → Add endpoint:

  • Endpoint URL: paste the HLE URL
  • Events: select the events you need (e.g. checkout.session.completed)

n8n workflow triggers

Receive webhook triggers for n8n automations:

Terminal window
hle webhook --path /webhook --forward-to http://localhost:5678/webhook

Troubleshooting

404 Not Found

The request path doesn’t match the configured webhook path prefix. If you registered with --path /hook/github, only requests to /hook/github and /hook/github/* are forwarded.

429 Rate Limit Exceeded

You’ve exceeded your plan’s webhook rate limit. Wait 60 seconds or upgrade your plan for higher limits.

413 Payload Too Large

The webhook payload exceeds 10 MB. This is uncommon for webhooks — check if the sender is including large attachments.