[Resolved] Webhook sub accepted but not receiving events

Just starting out using webhooks in php and I can’t seem to get any events POSTs from Twitch. I’m able to successfully subscribe with a 202 code and I believe I’m responding to the challenge by doing:

echo $_GET[‘hub_challenge’]

Lease seconds has a value in the GET request so I know that isn’t 0 and I’ve checked the callback and it seems to be working correctly when I do a test POST. I’m not really sure where to look into now.

Any thoughts?

Check your web server access logs to see if Twitch is even attempting to send the POST. If you see the request there than there is probably an issue with your code receiving the POST.

I don’t see any post requests made by Twitch. The only ones I see are the ones I make when subscribing to an event.

Try 200 Statuscode instead of 202. Iirc there was a bug or sth

Or is the 202 from twitch?

202 is from Twitch. I believe 200 is default for php?
Should I be echo-ing the status code back?

What topics did you subscribe to?

Just the new followers one.

Whats the full topic URL?

Testing with this one right now: https://api.twitch.tv/helix/users/follows?first=1&to_id=23161357

The get request from Twitch:
Key: hub_challenge Val: Xi77C2JObkMIRmwCraeU3_AQyxUcdfwMuJXD60lN
Key: hub_lease_seconds Val: 86400
Key: hub_mode Val: subscribe
Key: hub_topic Val: https://api.twitch.tv/helix/users/follows?first=1&to_id=23161357

And I’m echoing “Xi77C2JObkMIRmwCraeU3_AQyxUcdfwMuJXD60lN” in this case.

Hmmm seems all should work.

Can you post your whole PHP handler with the secrets removed?

Is weird you are not seeing the posts in your server access log though…


header("Access-Control-Allow-Origin: *");
ini_set("allow_url_fopen", true);

    $printString = "";
    foreach ($_GET as $key => $value) {
        $printString = $printString  . "Key: " . $key . " Val: " . $value . "\n";
    file_put_contents("getRequest.txt", $printString);
    if (isset($_GET['hub_challenge'])) {
        $challenge = $_GET['hub_challenge'];
        echo $challenge;

    $payload = "POST received\n";
    //$payload = file_get_contents('php://input');
    file_put_contents("payload.txt", $payload);


There’s not much going on in the handler right now. I’m just writing to a file to see if a request is coming through.

And what about the code making the subscription request?

require "site.class.php"

header("Access-Control-Allow-Origin: *");

$app = new site('');

$mode = $_POST['submode'];
$client_id = <client id>;
$lease_seconds = 24*60*60;

$postData = array(
    'hub.mode' => $mode,
    'hub.topic' => "https://api.twitch.tv/helix/users/follows?first=1&to_id=23161357",
    'hub.callback' => '<website>/PHP/webHookHandle.php',
    'hub.lease_seconds' => $lease_seconds,

$dataEncode = json_encode($postData);

$httpHeader = array(
    'Content-Type: application/json',
    'Content-Length: ' . strlen($dataEncode),
    'Client-ID: ' . $client_id

$app->bufferPost("https://api.twitch.tv/helix/webhooks/hub", $dataEncode, $httpHeader);


public function bufferPost($link, $postField, $httpHeader) {
        curl_setopt($this->curl, CURLOPT_VERBOSE,true);
        curl_setopt($this->curl, CURLOPT_URL, $link);
        curl_setopt($this->curl, CURLOPT_CUSTOMREQUEST, "POST");
        curl_setopt($this->curl, CURLOPT_RETURNTRANSFER, 1);
        curl_setopt($this->curl, CURLOPT_USERAGENT, $this->userAgent);
        curl_setopt($this->curl, CURLOPT_POST, true);
        curl_setopt($this->curl, CURLOPT_POSTFIELDS, $postField);
        curl_setopt($this->curl, CURLOPT_HTTPHEADER, $httpHeader);
        //turn off HTTPs errors
        curl_setopt($this->curl, CURLOPT_SSL_VERIFYHOST, false);
        curl_setopt($this->curl, CURLOPT_SSL_VERIFYPEER, false);
        //where cookies are saved if cookie exists
        if ($this->cookieFile) {
            curl_setopt($this->curl, CURLOPT_COOKIESESSION, TRUE);
            curl_setopt($this->curl, CURLOPT_COOKIEJAR, $this->cookieFile);  
        curl_setopt($this->curl, CURLOPT_COOKIE, $this->cookie);
        curl_setopt($this->curl, CURLOPT_REFERER, $this->referer);
        $this->bufferPage = curl_exec($this->curl);
        $httpCode = curl_getinfo($this->curl , CURLINFO_HTTP_CODE);

That should cover everything for the subscription part.

Ok I think I know the issue

In your handler:


Add a

file_put_contents(“getRequestHeaders.txt”, getallheaders());

And get the contents:

I bet you are getting

‘hub.topic’ => "https://api.twitch.tv/helix/users/follows?first=1

instead of

‘hub.topic’ => "https://api.twitch.tv/helix/users/follows?first=1&to_id=23161357

If so you need to change your postData as follow:

$postData = array(
    'hub.mode' => $mode,
    'hub.topic' => "https://api.twitch.tv/helix/users/follows?first=1&amp;to_id=23161357",
    'hub.callback' => '<website>/PHP/webHookHandle.php',
    'hub.lease_seconds' => $lease_seconds,

And retest

This is what I’m getting from getallheaders()

Key: Content-Length Val: 0
Key: Accept-Encoding Val: gzip
Key: Connection Val: close
Key: User-Agent Val: Go-http-client/1.1
Key: Host Val:

Hmm weird.

Check all the passed $_GET vars?

Also try the &amp; fix and see if that works :slight_smile: (I still need to move from the old topic to the new myself…)

Yup, the $_GET vars look correct.

Using & returns a 400 code when trying to subscribe to the topic.

I figured it out. It was an issue with echo-ing the challenge back. Turns out there was an extra space/newline at the end of the echo.

Now I feel silly. :upside_down_face:

Thanks for all the help.


Glad to have helped and we got it sorted!

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.