Webhooks
Our webhooks automatically send notifications about important events, reducing the need for frequent API polling. This guide explains how to set up, manage, and handle webhooks efficiently to ensure seamless data synchronization.
The list of available events can be found in the documentation.
Example of webhook usage
First, you need to register a webhook. This is done using the POST /api/webhooks endpoint.
For example, if you want to be notified about new orders, send:
{
"data": [
{
"event": "order:create",
"url": "https://myapplication.tld/new_order.php"
}
]
}
The response to the webhook registration request looks like this:
{
"data": {
"webhooks": [
{
"id": 123,
"event": "order:create",
"url": "https://myapplication.tld/new_order.php",
"created": "2025-03-02T17:22:02+0200",
"updated": null
}
]
},
"errors": null
}
From now on, whenever a new order is created in the e-shop, Shoptet will invoke https://myapplication.tld/new_order.php
via POST with the following content:
{
"eshopId": 222651,
"event": "order:create",
"eventCreated": "2025-02-08T15:13:39+0100",
"eventInstance": "2025000057"
}
The event notification contains the e-shop identification (eshopId
), event type (order:create
, meaning order creation), time of creation, and the instance concerned (eventInstance
) — in our case, the order with number 2018000057
.
Now, we are likely interested in the details of this order. Based on eshopId
, we need to find the correct OAuth access token
. Using the standard method, we will request an access token
and then retrieve the order using GET /api/orders/2018000057.
Webhooks registration
The above demonstrated how to register a new webhook. When doing so, it is not possible to register more than one URL under for a single event (e.g., order:update
). URLs using ports 80
, 8080
, 443
, and 8443
are permitted.
It is also important to remember that webhooks are registered separately for each installation (i.e., each e-shop and add-on). Therefore, it is not possible to register a single webhook for an add-on that would send notifications from all e-shops that install it. This gives you the flexibility to register webhooks only for the e-shops where they are needed (for example, when a user disables notifications). Additionally, you can use URLs specific to an e-shop—making it easier to identify the shop—such as https://call.me/order/shopId134
.
The registration or modification of these “add-on events” is not subject to any approval process; they take effect immediately. These events are fully controlled by the add-on’s author.
Further endpoints for the webhook content
- List of registered webhooks (your addon): GET /api/webhooks
- Change of webhook (called by URL): PATCH /api/webhooks/{id}
- Deletion of registered webhook: DELETE /api/webhooks/{id}`
Registered webhooks are valid for one add-on and one e-shop at a time. It is not possible to register or read webhooks for any other add-on, even if it is from the same developer and for the same e-shop, as they are linked to the specific installation of the add-on.
Notifications
A notification sent to a webhook URL must be confirmed by the webhook using HTTP status code 200 within 4 seconds. Otherwise, we will resend the notification after 15 minutes, up to two more times (a maximum of three attempts in total). If the last notification is not confirmed, we will mark it as inactive.
Be careful to split the webhook notification retrieval and further processing. You should end up with 200 Ok once the webhook notification is retrieved properly, otherwise the same notification will be sent again (if e. g. your script faces a problem in later processing and the response finally returns 500
, 422
etc.).
The notifications made on the webhooks are logged, including the number of repetitions, status, timestamps and whether they are active. The author of the addon has the possibility to read the logs of the implemented requests for webhooks using the endpoint GET /api/webhooks/notifications.
Notifications from Shoptet will only be sent from IP addresses 185.184.254.0/24
.
You should process the notification quickly and execute only the most essential actions. Otherwise, there is a higher risk of an error occurring, which may result in the webhook being triggered again or the response timeout being exceeded (4 seconds). Ideally, you should only store the change identifier (e.g., "order/new/number"), and any further processing (such as reading details, internal operations, or sending an email) should be handled asynchronously.
Additionally, notifications may not always be sent one by one; they can be delivered in parallel.
Signing the webhooks
To verify that the event notification was sent by Shoptet and that the message was not altered in transit, you can use the Shoptet-Webhook-Signature
header, which contains a hash of the data sent in the notification body.
First, you must call the POST /api/webhooks/renew-signature-key endpoint, which generates the signatureKey
. Save it.
Shoptet will also store it for the add-on and e-shop. When an event notification is issued, Shoptet calculates the hash as follows:
ShoptetWebhookSignature = hash_hmac('sha1', $messageBody, $signatureKey);
This checksum (hash) is inserted into the Shoptet-Webhook-Signature
HTTP header before calling the specified URL.
It is recommended to verify the signature as soon as the message is received. This involves taking the body of the received message, generating a custom signature using the signatureKey
obtained above (with hash_hmac
or sha1
), and then comparing it with the Shoptet-Webhook-Signature
value from the HTTP header.
Example of verification in PHP:
<?php
$webhookBody = '{"eshopId":315185,"event":"addon:uninstall","eventCreated":"2019-09-23T22:01:36+0200","eventInstance":"315185"}';
$signatureKey = '61d1175f54c47dd67df14c17002a17b2';
$calculated = hash_hmac('sha1', $webhookBody, $signatureKey);
$expected = 'a0e0a3e7689bd4c80e4d6ffcccb05235b864e1d0';
printf('calculated: %s %s', $calculated, PHP_EOL);
printf('expected: %s %s', $expected, PHP_EOL);
printf('is equal: %s %s', $calculated === $expected ? 'yes' : 'no', PHP_EOL);
Example of verification in Python:
import base64
import hmac
import hashlib
key = '61d1175f54c47dd67df14c17002a17b2'
message = '{"eshopId":315185,"event":"addon:uninstall","eventCreated":"2019-09-23T22:01:36+0200","eventInstance":"315185"}'
digest = hmac.new(key.encode('UTF-8'), message.encode('UTF-8'), hashlib.sha1).hexdigest();
expected = 'a0e0a3e7689bd4c80e4d6ffcccb05235b864e1d0'
print "calculated: {}".format(digest)
print "expected: {}".format(expected)
print "is equal: {}".format(digest == expected)