Skip to main content

Webhooks

The Centra Webhook plugin lets you create webhooks for specific events whenever data changes in Centra, so you’re notified and can fetch data only when it’s actually added or updated. Centra also offers an event system through the Integration API. Using events provides more control and flexibility compared to webhooks.

How do webhooks work in Centra

Webhooks in Centra are triggered by events. An event is any change happening in Centra - a new order comes in, a product description is changed, new product displays are added to a category - those are all events. If your webhook plugin is active and registers to those types of events (Order, Product, Category), Centra will generate an apropriate webhook and send it to your URL defined in the plugin. This way different webhook plugins can be used to handle different functions, and be used by different integrations.

Technically speaking, webhooks are simple HTTPS POST messages, containing info about a number of IDs and their types. By default, Centra will attempt to send the webhook for 5 seconds before timing out and re-trying. You can configure your webhooks to try re-sending that webhook up to 3 times, each time with increasing delay. If that still fails, Centra will assume your server or network is down, give up on sending that webhook and move to the next one in queue.

This is why, in addition to relying on webhooks to fetch resources from Centra only when necessary, you should also build a "fetch everything" function meant to restore the data after a network or application failure. After the data is synced, you can switch back to only fetching new or updated resources when receiving webhooks.

Webhook versions

Storefront API

Storefront API webhooks currently support events of the following types:

  • Display Items (DisplayItems): when product data is modified, such as stock, descriptions or variant changes, contains ID for each Product Display Item ID.
  • Categories (Categories): when category data is modified, contains ID for each Category ID.
  • Pricelists (Pricelists): when pricelist or shipping data is modified, contains ID for each Pricelist ID.
  • Markets (Markets): when market data is modified, contains ID for each Market ID.
  • Collections (Collections): when collection data is modified, contains ID for each Collection ID.
  • Brand (Brands): when brand data is modified, contains ID for each Brand ID.
  • Languages (Languages): when language data is modified, contains ID for each Language ID.
  • Campaign sites (CampaignSites): when campaign sites data is modified, contains ID for each Campaign Site ID.
  • Affiliates (Affiliates): when affiliate data is modified, contains ID for each Affiliate ID.
  • Brick and mortars (BrickAndMortars): when Brick and Mortar data is modified, contains ID for each Brick and Mortar ID.
warning

Data in the Storefront API is cached and it will only send a webhook once the data is in the cache. Using Integration API webhooks to fetch data from Storefront API will lead to errors as the data may not yet have been updated.

Example 1: Product Update

Triggered when a product or variant changes (e.g., price, image, or stock)

{ "DisplayItems": ["10123", "10124"] }

Example 2: Brand Update

Triggered when a brand connected to multiple products is updated.

{ "Brands": ["7"], "DisplayItems": ["10123", "10124", "10125"] }

Example 3: Category Update

Triggered when a display item is added to category.

{ "Categories": ["12"], "DisplayItems": ["10100", "10101", "10102"] }

Example 4: Pricelist Update

Triggered when a price list changes.

{ "Pricelists": ["5"] }

Checkout API

Checkout API webhooks currently support events of the following types:

  • Product (products): when product data is modified, such as stock, descriptions or variant changes, contains ID for each Product Display Item ID.
  • Inactive Product (products): also send updates for products with inactive displays. This allows support for previewing displays before they go live. Contains ID for each Product Display Item ID and will be sent in the same list as regular Product Display Item IDs.
  • Category (categories): when category data is modified, contains ID for each Category ID.
  • Pricelist (pricelists): when pricelist or shipping data is modified, contains ID for each Pricelist ID.
  • Warehouse (warehouses): when warehouse data is modified, contains ID for each Warehouse ID.
  • Allocation rule (warehouseGroups): when allocation rule data is modified, contains ID for each Allocation Rule ID.
  • Brand (brands): when brand data is modified, contains ID for each Brand ID.
  • Market (markets): when market data is modified, contains ID for each Market ID.
  • Campaign (campaigns): when campaign data is modified, for example when campaign starts or ends, contains ID for each Campaign ID.
  • Campaign Site (campaignSites): when campaign sites data is modified, contains ID for each Campaign Site ID.
  • Affiliate (affiliates): when affiliate data is modified, contains ID for each Affiliate ID.
  • Gift Certificate (giftCertificates): When gift certificate data is modified, contains ID for each Gift Certificate ID.
  • Static (statics): When static data is modified, contains ID for each static ID.
  • Maps Location (mapsLocations): When map location data is modified, contains ID for each Maps Location ID.
  • Maps Region (mapsRegion): When map region data is modified, contains ID for each Maps Region ID.

Example 1: Product Update

Triggered when a product or variant changes (e.g., price, image, or stock)

{ "products": ["10123", "10124"] }
note

If a product is not available or used in the store the plugin is installed on, there will be no webhook call. This makes it possible to use multiple stores and only get webhook events for the products in the store the plugin is installed in.

Example 2: Brand Update

Triggered when a brand connected to multiple products is updated.

{ "brands": ["7"], "products": ["10123", "10124", "10125"] }

Example 3: Category Update

Triggered when a display item is added to category.

{ "categories": ["12"], "products": ["10100", "10101", "10102"] }

Example 4: Pricelist Update

Triggered when a price list changes.

{ "pricelists": ["5"] }

Integration API

Integration API webhooks currently support events of the following types:

  • Order (order): When order data is modified, id is the Order ID.
  • Shipment (shipment): When shipment data is modified, id is the Shipment ID.
  • Customer (customer): When customer data is modified, id is the Customer ID. For B2C only, in B2B, accounts are sent instead of customers.
  • Account (account): When account data is modified, id is the Account ID. Only triggers for B2B.
  • Check first (check_first): When order check first changes status, id is the order number.
  • Allocation request (allocation_request): When order allocated from "Direct, then confirm" changes status, id is Allocation request ID.
  • Return (return): When return is created, updated or deleted, id is the Return ID.

New order created:

{
"events": [
{
"type": "order",
"action": "insert",
"date": "2025-01-24 09:40:48.735992",
"id": 78
}
]
}

If you are also getting customer web hooks and it is a new customer:

{
"events": [
{
"type": "customer",
"action": "insert",
"date": "2025-01-24 09:37:25.753541",
"id": 20
},
{
"type": "order",
"action": "insert",
"date": "2025-01-24 09:37:25.754834",
"id": 78
}
]
}

Confirming order:

{
"events": [
{
"type": "order",
"action": "update",
"date": "2025-01-24 09:44:00.488430",
"id": 78
}
]
}

Expedite order and Create Shipment:

When creating a shipment you will also get an “action": "update" on order as the status will be updated from confirmed to processing, while the shipments action is create.

{
"events": [
{
"type": "shipment",
"action": "create",
"date": "2025-01-24 09:48:36.845079",
"id": 1137
},
{
"type": "order",
"action": "update",
"date": "2025-01-24 09:48:36.845869",
"id": 78
}
]
}

Shipment “Good to Go”

{
"events": [
{
"type": "shipment",
"action": "good_to_go",
"date": "2025-01-24 09:53:51.392528",
"id": 1137
}
]
}

Shipment marked as Paid

{
"events": [
{
"type": "shipment",
"action": "update",
"date": "2025-01-24 09:55:16.360515",
"id": 1137
},
{
"type": "order",
"action": "update",
"date": "2025-01-24 09:55:16.360864",
"id": 78
}
]
}

Shipment info added and shipment completed

Now the shipment has been updated and completed. The order status has changed to Completed, as shown in the action field.

{
"events": [
{
"type": "shipment",
"action": "complete",
"date": "2025-01-24 09:57:39.143979",
"id": 1137
},
{
"type": "order",
"action": "update",
"date": "2025-01-24 09:57:39.144447",
"id": 78
},
{
"type": "shipment",
"action": "update",
"date": "2025-01-24 09:57:39.144635",
"id": 1137
}
]
}

Reset Password

Integration API also includes a webhook for triggering forgotten passwords, but for the flow to work you need some additional steps.

  1. Enable the Webhook plugin and choose Integration API in the version field.
  2. The Forgotten password needs to be triggered. This can be done either via the API or in Centra.
  3. An additional store option has been added to mute Centra's Forgotten password email, if a mailing plugin is not used.

Example:

{
"list": {
"events": [
{
"type": "customer",
"action": "forgot_password",
"date": "2024-12-16 15:39:32.278106",
"id": 1, // customer id
"data": {
"email": "customer@example.com",
"passwordResetToken": "123456789abcde" // example token, do not rely on exact format or length
}
}
]
},
"url": "https:\/\/example.com\/webhook_endpoint"
}

Setup

You can find the Webhook plugin under Webhooks in the plugin list.

Centra webhooks

Centra sends event notifications to your external systems via webhooks using HTTP or HTTPS. Only ports 80 and 443 are supported, and IPv6 addresses without a domain name are not allowed.

  • Webhook URL Enter the public URL where Centra should deliver webhook events.

  • Endpoint Secret an optional shared secret used to verify that webhook requests come from Centra.
    Each request is signed using HMAC-SHA256, and the signature is sent in the header:

    X-Centra-Signature: t=TIMESTAMP,v1=SIGNATURE

    Use this value to validate incoming requests and confirm their authenticity.

  • Validate SSL Enable this option if you want Centra to verify the SSL certificate of your webhook endpoint. When active, Centra checks the full certificate chain for validity.

  • Max Number of Events per Webhook Call specifies how many separate Centra events can be combined into a single webhook request.
    Range: 1–100, default: 100

  • Timeout in Seconds Defines how long Centra waits for a response before timing out and aborting the delivery.
    Range: 1–60, default: 5 seconds

  • Number of Retries after Failure Determines how many times Centra should retry sending a webhook if a delivery fails. Each retry doubles the delay between attempts, starting from 1 second.
    Range: 0–3, default: 0

  • Version Specifies which API version (and event taxonomy) the webhook follows.
    Each version provides a different set of event triggers depending on your integration needs:

    • Storefront API/Checkout API these webhook types correspond to the Storefront and Checkout APIs.
      Events are triggered when objects related to Product Display Items change — for example, when a connected brand, category, or attribute is modified.
      Centra automatically includes the affected Product Display Item IDs in the webhook payload, making it easy to invalidate product caches or update search indexes in real time.
    • Integration API includes broad integration events used to connect Centra with external business systems like ERP or CRM.
    • Subscription API includes triggers for all subscription lifecycle events.
      Webhooks are sent when subscriptions are created, modified, renewed, or canceled, along with the affected Subscription IDs.
  • Max number of events per webhook call: 10
  • Timeout in seconds: 5
  • Number of retries after failure: 2

This configuration offers a reliable balance between performance, delivery speed, and fault tolerance for most webhook integrations.

Event triggers

In the webhook plugin set up, there's a list with event triggers that you can select. We will only send webhook notifications for the events you have subscribed to.

For each event trigger there's a "Field Name", this is the key used in the payload.

Format

A webhook is sent as a regular POST-request using a urlencoded payload-parameter containing the JSON:

POST /url HTTP/1.1 Host: example.com X-Centra-Signature: t=15798... Content-Type: application/x-www-form-urlencoded payload=%7B%22products%22%3A...

The format of the webhook:

{ "products": ["52"], "categories": ["14", "16"], "anotherType": ["1"] }

A webhook can send multiple updates for multiple types at the same time. It will always send an array of ID for each type. The key inside the JSON correlates with the "Field Name" in each event trigger in the webhook set up to receive.

Some modifications in Centra will trigger multiple types at the same time. If you for example sort products inside a category, when the new order is saved, the webhook will contain both the products that got their sorting changed, but also the category the sorting was changed in, like this:

{ "products": ["1", "6", "7"], "categories": ["1"] }

This allows you to write logic in your end depending on how you cache your data. In this case, you might want to recache the whole category, by fetching all products inside the category:

curl -X POST -H "Content-type: application/json" \ -d '{"categories":["1"]}' \ "https://example.centra.com/api/checkout/products"

Signature verification

The endpoint secret inside the webhook plugin settings is used to generate a signature header called X-Centra-Signature. This signature can be used to validate that the webhook is actually sent by Centra and no one else.

This signature header contains two parameters, like this:

t=1579866370,v1=340a5be9321ad1b83dec05455650b6e174797a7267f48703ccdb7f251a8ba6c9

The timestamp is used to make sure a replay attack cannot be done, if someone would be able to get a valid signature. The v1 contains a HMAC-SHA256 based on the timestamp and the request body separated with a dot ..

You can parse this header value by splitting it on , and then splitting each value with =. The key v1 contains the signature of the following values (with a dot . as the separator):

{timestamp}.{requestBody}

This means, if your endpoint signature was: test123, the timestamp inside t was 12345678 and the request body would look like this:

payload=%7B%22x%22%3A%22test%22%7D

The signature would be made of:

12345678.payload=%7B%22x%22%3A%22test%22%7D

The header:

X-Centra-Signature: t=12345678, v1=0b9cd84f5d583e5e1aadfb9f160aa8080b51d5b85ff85808d6b75bdac356c549

Example signature verification code

PHP:

$ php -a echo hash_hmac('sha256', '12345678.payload=%7B%22x%22%3A%22test%22%7D', 'test123');0b9cd84f5d583e5e1aadfb9f160aa8080b51d5b85ff85808d6b75bdac356c549

Python:

$ python3 import hashlib, hmac print(hmac.new("test123".encode("UTF-8"), '12345678.payload=%7B%22x%22%3A%22test%22%7D'.encode("UTF-8"), hashlib.sha256).hexdigest()) 0b9cd84f5d583e5e1aadfb9f160aa8080b51d5b85ff85808d6b75bdac356c549

Troubleshooting Delivery Issues

Testing with a parallel webhook plugin can help identify whether the issue lies with the sender, the webhook system or the recipient (e.g., the integration, server, or network). It's important to confirm that the webhook was sent and isolate potential problems with external systems.

Some important concepts related to their configuration and functionality:

Max Events per Webhook

This setting determines how many events are included in a single HTTP POST message. For example:

  • 1 Event per Webhook: Multiple webhooks are sent, each containing only one event.
  • Many Events per Webhook: Fewer webhooks are sent, but each contains multiple events.

Regardless of this setting, all events will be delivered—it's just a matter of grouping.

Retries and Timeouts

For every batch of events sent:

  • Retry Attempts: We will try sending the webhook a specified number of times if it fails to reach the endpoint.
  • Timeout: If the webhook is not picked up within the defined timeout period (in seconds), it is considered a failure, and a retry is attempted.
    • If the retries fail repeatedly, we stop attempting to deliver that batch.

Troubleshooting Delays or Failures

If a webhook is not received:

  • It's essential to check the integration or network performance on the receiving side, as delays or failures might be caused by external factors such as slow servers or network congestion.
  • Testing with parallel webhook plugins can help identify whether the issue lies with the receiving system or network.
note

Even if a webhook is not received due to such issues, this does not mean the webhook was not sent.