Sending Webhooks to Firewalled Endpoints: Why Your Outbound IP Matters

QuotaGuard Engineering
April 23, 2026
5 min read
Pattern

Webhooks are simple in concept. An event happens in your system. You POST a JSON payload to your partner's URL. They process it. Done.

The complication shows up when the partner's webhook endpoint sits behind a firewall. They give you the URL and say "what IP will these requests come from? We need to whitelist it."

If your app runs on serverless infrastructure, you don't have a good answer.

The Webhook IP Problem

Most webhook discussions focus on receiving webhooks. You set up an endpoint, Stripe or GitHub sends you events, you process them. Inbound IP whitelisting is the receiver's problem, and services like Stripe publish their sending IPs.

The less-discussed case is sending webhooks. Your system sends event notifications to a partner, customer, or internal service. If the receiver firewalls their inbound traffic (which enterprise customers often do), they need to know your IP so they can allow it through.

On serverless platforms, your outbound IP rotates. Lambda, Cloud Functions, Heroku, Render. Every request might come from a different address. Your partner adds one IP to their allow list. It works for a while. Then your infrastructure shifts, the IP changes, and their firewall drops your webhook. They don't get the event. Nobody notices until something downstream breaks.

Why This Is Different from API Calls

With API calls, you typically get an error back. Your code sees a 403 or a connection timeout. You can catch it, log it, retry it.

With outbound webhooks, the failure is often silent from your side. You send the POST. The firewall drops it. Depending on your implementation, you might get a connection timeout after 30 seconds, or you might get nothing at all. If you're sending webhooks asynchronously (which you should be), the failure shows up in a retry queue, not in the original request flow.

This makes webhook delivery failures harder to detect and debug. Adding a stable IP that the partner can reliably whitelist prevents the problem entirely.

The Fix

Route your outbound webhook requests through QuotaGuard. Your webhooks exit from two static IPs. The partner whitelists those IPs. They don't change regardless of which serverless instance sends the request.

Python

import os
import requests

proxy_url = os.environ.get('QUOTAGUARD_URL')
proxies = {'http': proxy_url, 'https': proxy_url}

def send_webhook(url, payload):
    response = requests.post(
        url,
        json=payload,
        proxies=proxies,
        timeout=10
    )
    response.raise_for_status()
    return response

Node.js

const { HttpsProxyAgent } = require('https-proxy-agent');

const agent = new HttpsProxyAgent(process.env.QUOTAGUARD_URL);

async function sendWebhook(url, payload) {
  const response = await fetch(url, {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify(payload),
    agent
  });

  if (!response.ok) {
    throw new Error(`Webhook failed: ${response.status}`);
  }

  return response;
}

Ruby

require 'net/http'
require 'uri'
require 'json'

proxy_uri = URI.parse(ENV['QUOTAGUARD_URL'])

def send_webhook(url, payload)
  uri = URI.parse(url)

  proxy = Net::HTTP::Proxy(
    proxy_uri.host,
    proxy_uri.port,
    proxy_uri.user,
    proxy_uri.password
  )

  http = proxy.new(uri.host, uri.port)
  http.use_ssl = true

  request = Net::HTTP::Post.new(uri.path)
  request['Content-Type'] = 'application/json'
  request.body = payload.to_json

  http.request(request)
end

Webhook Retry Logic

Webhooks fail sometimes. The partner's server might be temporarily down, or a network issue causes a timeout. Good webhook implementations include retry logic.

When you're routing through a proxy, retries work the same way. The proxy doesn't add complexity to your retry flow. If the first attempt fails, retry through the same proxy. The partner's firewall sees the same whitelisted IP on every attempt.

import time

def send_webhook_with_retry(url, payload, max_retries=3):
    for attempt in range(max_retries):
        try:
            response = requests.post(
                url,
                json=payload,
                proxies=proxies,
                timeout=10
            )
            response.raise_for_status()
            return response
        except requests.RequestException as e:
            if attempt == max_retries - 1:
                raise
            time.sleep(2 ** attempt)  # Exponential backoff

Webhook Signatures and IP Verification

Some webhook receivers verify authenticity two ways: they check the request signature (HMAC or similar) and they check the source IP. The signature proves the payload hasn't been tampered with. The IP check provides a second layer of verification.

Routing through QuotaGuard doesn't affect webhook signatures. Your app generates the HMAC. The proxy forwards the request with the payload intact. The receiver validates the signature against the original payload. The proxy doesn't modify the request body or headers.

The IP verification becomes straightforward. Your partner knows both static IPs. They check that every incoming webhook comes from one of those two addresses. Combined with signature verification, this is a solid authentication model.

Multiple Partners, Same IPs

If you send webhooks to multiple partners, each with their own firewall, you give all of them the same two IPs. Every partner whitelists the same addresses. Adding a new partner integration doesn't require new infrastructure. You just share the IPs and start sending.

Getting Started

Sign up for QuotaGuard Static. Set the proxy URL as an environment variable. Route your outbound webhook POST requests through the proxy. Give your partners the two static IPs from the dashboard to whitelist.

QuotaGuard Static starts at $19/month. For compliance-level encryption (HIPAA, PCI-DSS), QuotaGuard Shield starts at $29/month with SSL passthrough.

QuotaGuard Static IP Blog

Practical notes on routing cloud and AI traffic through Static IPs.

Reliability Engineered for the Modern Cloud

For over a decade, QuotaGuard has provided reliable, high-performance static IP and proxy solutions for cloud environments like Heroku, Kubernetes, and AWS.

Get the fixed identity and security your application needs today.