# Webhooks server in PHP

This article presents a simple [webhooks server](../../developer-resources/webhooks/server.md) example.

> **Warning**
>
> We strongly advise you NOT to use this in a production environment.

<a id="dependencies">

## Dependencies

This example does not require any external PHP dependencies.\
However, for local development purposes, a tunneling service is required. This example uses [ngrok](https://ngrok.com/).

You can download ngrok here: <https://ngrok.com/download>.

<a id="examples">

## Examples

Below are two examples of a webhooks server.

<a id="example-without-checking-the-request-signature">

### Example without checking the request signature

This is a very simple example, with the server logging the `body` from the request to the console. The `body` contains the complete [webhook information](../../developer-resources/webhooks/overview.md#webhook-format) sent from CKEditor Cloud Services.

```php
<?php

$body = file_get_contents('php://input');

$webhook = json_decode($body);

file_put_contents('php://stdout', 'Webhook received: ' . print_r($webhook, true) . "\r\n");
```

<a id="example-with-checking-the-request-signature">

### Example with checking the request signature

This example shows how to verify if the request was sent from the CKEditor Cloud Services servers\
and was [signed](../../developer-resources/security/request-signature.md) with the correct [API secret](../../developer-resources/security/api-secret.md).

Several variables are needed to generate and check the signature. The [API secret](../../developer-resources/security/api-secret.md) is available in the [Customer Portal](https://portal.ckeditor.com/) for SaaS or in the Management Panel for On-Premises, the rest of the parameters are in the request:

* `method`: `$_SERVER['REQUEST_METHOD']`
* `url`: `$_SERVER['REQUEST_URI']`
* `timestamp`: `$_SERVER['HTTP_X_CS_TIMESTAMP']`
* `body`: `file_get_contents('php://input')`

```php
<?php

$apiSecret = 'your-api-secret';

$requestMethod = $_SERVER['REQUEST_METHOD'] ?? '';
$receivedHmac = $_SERVER['HTTP_X_CS_SIGNATURE'] ?? '';
$timestamp = $_SERVER['HTTP_X_CS_TIMESTAMP'] ?? '';
$url = $_SERVER['REQUEST_URI'];
$body = file_get_contents('php://input');

$data = $requestMethod . $url . $timestamp . $body;
$hmac = hash_hmac('sha256', $data, $apiSecret);

$isValid = hash_equals($hmac, $receivedHmac);

if (!$isValid) {
	// Invalid webhook signature, ignore the request.
	die();
}

$webhook = json_decode($body);

file_put_contents('php://stdout', 'Webhook event received: ' . print_r($webhook, true) . "\r\n");
```

<a id="usage">

## Usage

Save the above example file as `index.php` and start the server with:

```bash
php -S 127.0.0.1:9000
```

If needed, run ngrok with:

```bash
./ngrok http 9000
```

After this, you should see a `*.ngrok.io` URL. Copy the `*.ngrok.io` URL and paste it in the webhook configuration. You should be able to receive webhooks now.

---

Full index of the Cloud Services documentation: [llms.txt](../../../llms.txt)
