EventSub webhook verification fails without reaching callback

Hello,

I’m hoping someone can help point me in the right direction.

I’m creating an EventSub channel.update subscription using the Helix API.

The registration succeeds with HTTP 202 and the subscription enters the expected webhook_callback_verification_pending state.

I have verified my callback endpoint independently using the Twitch CLI, which successfully validates the challenge, signature, HTTP 200 response, and content type. Manual testing of the endpoint also works correctly.

However, the production subscription consistently transitions to webhook_callback_verification_failed.

To troubleshoot, I enabled detailed application logging and reviewed my web server access logs during the entire verification window.

The only requests to the callback endpoint are my own manual tests. There is no POST request from Twitch before the subscription transitions to webhook_callback_verification_failed.

At this point, I’m trying to determine whether:

  • there are known situations where verification fails before an HTTP request reaches the origin server,
  • there are additional diagnostics I should perform,
  • or if there is anything commonly overlooked in an otherwise working EventSub implementation.

I’m happy to provide additional information, logs, timestamps, or registration details if they’re helpful.

Thank you.

Firewalls or other security implementations are the usaul thing that blocks webhook traffic “unexpectedly”

You are trying to use a web accessable address?

Webhook’s need to be accessable from the public internet.

The TwitchCLI will let you test your URL from your own machine and naturally localhost will work from there.

So things to check:

  • SSL is valid check with SSL Server Test (Powered by Qualys SSL Labs)
  • You already use the TwitchCLI to check your URI/endpoint works for validation/secrets handling
  • Check that the URL is accessable from the internet
  • Check if you have anything firewall-y thats blocking the requests.

Thanks Barry.

To answer your questions:

  • Yes, I’m using a publicly accessible HTTPS callback URL hosted with a web hosting provider (not localhost).
  • SSL is valid, and the callback URL is externally reachable (verified independently).
  • Twitch OAuth to the same hosted application works correctly, so communication with Twitch itself is working.
  • I’ve also tested the callback endpoint using the Twitch CLI from my local PowerShell against the same hosted callback URL, and the validation/challenge handling works as expected.

The one thing I can’t explain is that the actual EventSub webhook verification never appears in the hosted site’s access logs or application logs. It’s as though the request never reaches the origin.

I also found this older discussion where another developer reported their host indicated the default EventSub Go-http-client/1.1 User-Agent was being blocked by upstream security before reaching the application:

Webhook User Agent

I’m not assuming that’s the cause here, but the symptoms seem very similar. Have you seen anything like that recently, or is there anything else commonly overlooked that could prevent the verification request from ever reaching the origin?

If this is only affecting the callback, I might look into having it call my self-hosted core backend instead but it seems… Complicated.

Well thats the “wrong direction”

that is calls from your server to Twitch

Not calls to your server from Twitch.

Edit: So theres nothing blocking “outbound” traffic but something is blocking “inbound” traffic.

But inbound traffic requesting the website is not being blocked.

So it smells like firewall/security

What did you score out of interest?

This tests your ability for your computer to reach the URI which might not work from a different network.

Then that might be a firewall that your web hoster is providing that cannot be configure blocking the request. IE the same issue that OP had on the thread, given they cannot change/modify the webhoster provided firewall to allow the traffic. (This is common on VPS providers unless bare metal)

Or you are using cloudflare and cloudflare blocked the request before it reachs you.

99% of the time the problems with “I have no logs of webhook calls” is due to firewalls/security (been like they for 20 years, been diagnosing paypal IPN problems like this for a very long time and it’s always a firewall)


Ran it fresh just now.

Agreed 100%

No, I’m not using a CDN.

Gotcha, thanks.

Is there any way in the Twitch Developer Dashboard to manually test an EventSub callback and see Twitch’s view of the verification attempt (HTTP status, response, errors, etc.), or is the Helix API subscription status the only visibility we have into that process?

There isn’t.

That is correct

You could try building a POST request yourself and use the same header for the user agent (off hand I don’t know what header the CLI uses but since it’s coming from your machine then the firewall if any know who you are/it’s already trained to trust your IP).

But you’d want to simulate that test from not your IP I suspect.

I did something even simpler to prove it is on my host’s security layer.

I tested the same hosted EventSub callback URL from the same client, using the same POST body. The only thing I changed was the User-Agent header.

With a normal browser User-Agent:


HTTP/1.1 400 Bad Request
Server: Apache
X-ChattersOnly-EventSub-Callback: reached

missing EventSub headers

This is the expected behavior because the request reached my callback, and my callback correctly reported that the required Twitch EventSub headers were missing.

Then I repeated the test with:


User-Agent: Go-http-client/1.1

and received:


HTTP/1.1 503 Service Temporarily Unavailable
Server: nginx
Retry-After: 135

The request never reached my callback and never appeared in my application or access logs.

This appears to be a host security layer issue and not anything we have control over.
I’ll try my complicated workaround.

503 feels like the wrong code here which is odd. (5xx being “server fucked up” you’d expect a 4xx permission denied)

And a 503 would be logged in your logs, if your nginx was the one doing it.

So seems like a nginx layer in front of your apache is at fault. (very odd to have an nginx in front of apache when they do the same things)

It is almost like my host is reselling the webspace provided by another layer of host … gee I’d call them out but that would be rude. Thanks Barry, I appreciate your attention and somebody to talk through the issue with.

thats what a lot of VPS providers do, one box many clients

Depending on your overall use case, you can use free tiers of services like hookdeck (around 10k successful requests a month per “organization” which you can have multiple of) to intercept and replace the user agent string; otherwise, maybe you can get a friend to run a super simple proxy?

I made an educated guess that lightsail would work just fine, and it does. :grin: