# How to process webhooks

When you get a webhook from Ecwid API, you need to let Ecwid know that your server received it, verify its identity, and parse the data inside for further automation. We refer to this process as **webhook handling**.

{% hint style="info" %}
Webhooks are triggered by any changes in the store data no matter their source. For example, if you create a new order with the REST API request, you'll still receive the `order.created` webhook.
{% endhint %}

### Step 1. Respond with status 200

Your app must send a confirmation when it receives a webhook. Otherwise, according to our resend policy, Ecwid API will retry to deliver this webhook for the next 24h.&#x20;

So, the first step is to inform Ecwid about the successful webhook delivery. The app must return the HTTP `200 OK`  status code or one of the allowed alternatives in response to every received webhook:

| Response HTTP code                     | Result                           |
| -------------------------------------- | -------------------------------- |
| `200`, `201`, `202`, `204`, `209`      | Webhook counts as delivered.     |
| `203`, `208`, any other `2xx` or `3xx` | Webhook counts as not delivered. |

If something goes wrong and the webhook is not delivered, Ecwid makes several attempts to deliver it in the next 24h by the following schedule:

<table><thead><tr><th width="371">Attempt №</th><th>Schedule</th></tr></thead><tbody><tr><td>1</td><td>15 min</td></tr><tr><td>2</td><td>30 min</td></tr><tr><td>3</td><td>45 min</td></tr><tr><td>4</td><td>1h</td></tr><tr><td>5</td><td>2h</td></tr><tr><td>6</td><td>3h</td></tr><tr><td>7</td><td>4h</td></tr><tr><td>8</td><td>5h</td></tr><tr><td>9</td><td>6h</td></tr><tr><td>...</td><td>...</td></tr><tr><td>27</td><td>24h</td></tr></tbody></table>

{% hint style="warning" %}
If your `webhookUrl` fails to respond in 2 weeks, webhooks for your app will be blocked.
{% endhint %}

Your app must also send the response in time. Ecwid tries to connect with your `webhookUrl` and waits for the response for a limited time.&#x20;

If your app fails to respond in time, Ecwid calls a timeout and counts this webhook as not delivered:

|                                              | Timeout in |
| -------------------------------------------- | ---------- |
| `webhookUrl` connection time                 | 3 sec      |
| Time to receive a response from `webhookUrl` | 10 sec     |

### Step 2. Parse webhook data

After confirming webhook delivery, the app must decode and parse the webhook body and verify that it comes from Ecwid.

Code example for webhook body decoding and parsing:

```php
$decodedBody = json_decode($requestBody, true);

$eventId = $decodedBody['eventId'];
$eventCreated = $decodedBody['eventCreated'];
$storeId = $decodedBody['storeId'];
$entityId = $decodedBody['entityId'];
$eventType = $decodedBody['eventType'];
$data = $decodedBody['data'];
```

All of the resulting variables except for the `$data` are of a string type. The `$data` variable is an object of strings.

### Step 3. Verify webhook signature

After parsing the webhook body, get its `X-Ecwid-Webhook-Signature` header and validate webhook data with it using `sha256` encryption.

Code example for webhook verification:

<pre class="language-php"><code class="lang-php">$client_secret = 'abcde123456789';
<strong>
</strong><strong>if (!$signatureHeaderPresent) {
</strong>	echo 'Signature verification failed';
	exit;
}

if (!function_exists('getallheaders')) {
    function getallheaders()
    {
        foreach ($_SERVER as $name => $value) {
            if (substr($name, 0, 5) == 'HTTP_') {
                $headers[str_replace(' ', '-', ucwords(strtolower(str_replace('_', ' ', substr($name, 5)))))] = $value;
            }
        }
        return $headers;
    }
}

foreach (getallheaders() as $name => $value) {
    if ($name == "X-Ecwid-Webhook-Signature") {
        $headerSignature = "$value";
      	$signatureHeaderPresent = true;
        
        $hmac_result = hash_hmac("sha256", "$eventCreated.$eventId", $client_secret, true);
        $generatedSignature = base64_encode($hmac_result);
        
        if ($generatedSignature !== $headerSignature) {
            echo 'Signature verification failed';
            exit;
        }
    }
}
</code></pre>

After completing these steps, you can safely process the data received in the webhook.


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.ecwid.com/webhook-automations/setup-webhooks/how-to-process-webhooks.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
