Skip to content

Offer Event Webhooks

Beta

Joining the Beta

We are currently in a pilot phase. To participate in this phase as a beta tester, reach out to your representative. When you are enrolled in the pilot, you will need to provide the url where you'd like to receive webhook payloads. You will also need a secret key for authenticating the webhooks. See Authentication below.

Structure

A POST request will be made to your webhook url. Here is an example of the request body:

{
    "type": "offer.removed",
    "timestamp": "2024-07-11T20:26:10.344522Z",
    "data": {
        "offerId": "123456789456123"
    }
}
Field
Explanation
type The type of change that has occurred.
timestamp The unix time when the request was generated. Expect a slight delay between the time that the request is generated and the time it is received.
data.offerId The unique id of the offer. See the id field in the Offer API Response.

Available Webhooks

Type
Explanation
offer.removed Sent when an existing offer is removed and no longer available to new players. Players that have already started the offer will still be able to continue and finish. New players should not be shown the offer, as they are not eligible and will not be credited.

Retrying Failed Requests

When a webhook request is sent, a response with a 2xx-series status code is expected. If the response includes any other status code, the request will be retried up to three times. Be sure to account for this to avoid double-rewarding players.

Authentication

The webhook request headers contain a Signature. This is calculated by hashing the request body and the secret key using the HMAC-SHA256 algorithm. To authenticate the request, hash the request body and the secret key using the HMAC-SHA256 algorithm. Compare the result to Signature value to confirm a match.

Examples:

Route::post('/webhook-receiver', function () {
    $receivedSignature = request()->headers->get('Signature');

    $expectedSignature = hash_hmac('sha256', request()->getContent(), 'secret-key');

    if ($expectedSignature === $receivedSignature) {
        return response()->noContent(200);
    } else {
        return response()->noContent(401);
    }
});
const express = require('express');
const crypto = require('crypto');

const app = express();
const port = 3000;

app.use(express.json());

app.post('/webhook-receiver', (req, res) => {
    const receivedSignature = req.headers['Signature'];

    const postData = JSON.stringify(req.body);
    const expectedSignature = crypto.createHmac('sha256', 'secret-key').update(postData, 'utf8').digest('hex');

    if (expectedSignature === receivedSignature) {
        res.status(200).send();
    } else {
        res.status(401).send();
    }
});

app.listen(port, () => {
    console.log(`Server running on port ${port}`);
});
Back to top