Webhooks

Webhooks are a feature that allows you to have your system receive notifications about a certain event on our site.

When an event happens, the Smake server sends a POST request to your defined endpoint URLS. This request contains all the relevant information about the Event, including the type and the data associated with that. You can have Smake send a single event to multiple webhook endpoints.

Webhook data is sent as JSON in the POST request body.

To acknowledge receipt of a event, your endpoint must return a 2xx HTTP status code. All response codes outside this range indicate to Smake that you did not receive the event. If you do not acknowledge receipt of a event, Smake will continue to deliver your webhooks with an exponential backoff for up to one day.

This is similar to polling, webhooks provide your application a way of consuming data that takes longer to proccess, but instead of sending repeated requests for new data, you will be informed per events.

Webhooks are the prefered way of consuming data that takes longer to proccess, because there are far more efficient.


Webhooks and API versions

The structure of the payload an event sent in a webhook is dictated by the API Version you set in the app at the time of the event's occurrence. For example, if your app is set to an older API version, such as 2017-09-25, and you change the API version for a specific request via versioning, the payload generated and sent to your endpoint is still based upon the 2017-09-25 API version.

Signatures

Smake can optionally sign the webhook events it sends to your endpoints. We do so by including a signature in each event’s X-Signature header, when your secret token is set. Smake uses it to create a hash signature with each payload. This allows you to validate that the events were sent by Smake, not by a third party.

Validating payloads

Smake uses an HMAC hexdigest to compute the hash, so you could change your server to look a little like this:

class WebhookController extends Controller
{
    public function handleVariantDesigned(Request $request)
    {
        $payload = json_decode($request->getContent(), true);

        if (! $this->hasValidSignature($request, $payload)) {
            // Handle invalid Signature
            return response()->setStatusCode(422);
        }

        // Handle Payload
        return response()->setStatusCode(200);
    }

    protected function hasValidSignature(Request $request, string $payload): bool
    {
        $token = config('my-secret-token');

        return $request->header('X-Signature') === 'sha1='.hash_hmac('sha1', $payload, $token);
    }
}