Guide to Akeneo Webhooks: Features and Best Practices
Akeneo webhooks notify your systems when product data changes in the PIM: a product or product model is created, updated, or removed. If you're syncing Akeneo to downstream systems, webhooks are how you react to catalog changes without polling.
This guide covers how Akeneo's Events API webhooks work, the events you'll handle, how to verify the x-akeneo-request-signature, the demanding delivery model (fast ack, no retries), and the best practices for production.
What are Akeneo webhooks?
Akeneo PIM's Events API delivers HTTP POSTs to a single Request URL per connection, that one URL receives all event types, so you route server-side. Each delivery batches events in an events array and is signed with an x-akeneo-request-signature header.
This is the Events API (marked deprecated in favor of the newer Event Platform, but still the webhook scheme this source targets). It's a demanding delivery model: acknowledge in under 500 ms, and there are no retries.
Akeneo webhook features
| Feature | Details |
|---|---|
| Configuration | Per connection in PIM settings (one Request URL receives all events) |
| Signature headers | x-akeneo-request-signature, x-akeneo-request-timestamp (unix seconds) |
| Signature scheme | hex HMAC-SHA256 over {timestamp}.{body}, keyed with the connection secret |
| Freshness | Reject if now - timestamp > 300 (5 minutes) |
| Payload | Batched events array (action, event_id, event_datetime, author, data.resource) |
| Acknowledgement | 2xx in under 500 ms |
| Retries | None, events dropped after ~2h; up to ~40k events/hr; order not guaranteed |
| SDK | None |
Common events
Only product and product-model events exist in the Events API:
| Event | Fires when |
|---|---|
product.created | A product is created |
product.updated | A product is updated |
product.removed | A product is removed |
product_model.created | A product model is created |
product_model.updated | A product model is updated |
Note: category events are not in this API, they exist only in the newer CloudEvents-based Event Platform. Route on each event's action in the batch.
Setting up Akeneo webhooks
Enable the Events API per connection in the PIM connection settings and set the single Request URL. The connection secret is the HMAC key. Because one URL receives all events, dispatch by action server-side.
Securing Akeneo webhooks
Each delivery carries x-akeneo-request-signature and x-akeneo-request-timestamp. To verify, build {timestamp}.{body}, compute an HMAC-SHA256 with the connection secret, hex-encode it, and compare against the signature. Also reject deliveries where now - timestamp > 300 seconds. Verify against the raw body.
const crypto = require("crypto");
const SECRET = process.env.AKENEO_CONNECTION_SECRET;
function verify(rawBody, timestamp, signature) {
// 5-minute freshness (timestamp is unix seconds)
if (Math.floor(Date.now() / 1000) - Number(timestamp) > 300) return false;
const message = `${timestamp}.${rawBody.toString()}`;
const expected = crypto.createHmac("sha256", SECRET).update(message).digest("hex");
const a = Buffer.from(expected);
const b = Buffer.from(signature || "");
return a.length === b.length && crypto.timingSafeEqual(a, b);
}
app.post("/webhook", express.raw({ type: "application/json" }), (req, res) => {
const timestamp = req.headers["x-akeneo-request-timestamp"];
if (!verify(req.body, timestamp, req.headers["x-akeneo-request-signature"])) {
return res.sendStatus(401);
}
res.sendStatus(200); // MUST be under 500ms -- do not process here
const { events } = JSON.parse(req.body);
for (const event of events) processQueue.add(event); // route by event.action
});
The same check in Python:
import hashlib
import hmac
import os
import time
SECRET = os.environ["AKENEO_CONNECTION_SECRET"].encode()
def verify(raw_body: bytes, timestamp: str, signature: str) -> bool:
if int(time.time()) - int(timestamp) > 300:
return False
message = (timestamp + "." + raw_body.decode()).encode()
expected = hmac.new(SECRET, message, hashlib.sha256).hexdigest()
return hmac.compare_digest(expected, signature or "")
Akeneo webhook limitations and pain points
No retries, and a sub-500ms ack
The Problem: You must return 2xx in under 500 ms, and there are no retries, events are dropped after ~2 hours if not accepted. Any slow processing in the handler loses events.
Why It Happens: The Events API prioritizes high throughput (up to ~40k events/hr) over retry guarantees.
Workarounds:
- Verify, enqueue, and return 2xx immediately, do zero processing in the request path.
- Reconcile via the API for anything you can't afford to miss, since there are no retries.
How Hookdeck Can Help: Hookdeck accepts deliveries in milliseconds and durably queues them, so the sub-500ms window and the no-retry model stop being a risk, your worker processes at its own pace with retries you control.
One URL for all events
The Problem: A single Request URL per connection receives every event type, so you must dispatch server-side. A handler expecting one event type gets everything.
Why It Happens: Akeneo delivers all events to one endpoint per connection.
Workarounds:
- Route by each event's
actionin the batch.
How Hookdeck Can Help: Hookdeck's filters route by action, so each downstream handler receives only the events it cares about.
Batched, unordered events
The Problem: Events arrive batched in events[] and delivery order is not guaranteed, so per-event and ordering assumptions break.
Why It Happens: The Events API batches and parallelizes for throughput.
Workarounds:
- Iterate the batch, treat each event independently, and order by
event_datetimeif needed.
How Hookdeck Can Help: Hookdeck can split batches and replay events in a controlled order during recovery.
Only product/product_model events
The Problem: Category (and other) events aren't in this API; expecting them here means they never arrive.
Why It Happens: The Events API covers only product and product-model events; the rest are in the newer Event Platform.
Workarounds:
- Use this API for product events and the Event Platform for others.
How Hookdeck Can Help: Hookdeck can ingest both APIs and normalize them into one stream.
Best practices
Verify over timestamp.body with a 5-minute window
Build {timestamp}.{body}, HMAC-SHA256 with the connection secret, hex, compare in constant time, and reject stale timestamps (>300s).
Acknowledge in under 500ms, process asynchronously
Verify, enqueue, and return 2xx immediately, no processing in the request path. See why to process webhooks asynchronously.
Route by action and reconcile
Dispatch by each event's action, and reconcile via the API since there are no retries.
Make Akeneo webhooks production-ready
Hookdeck absorbs the sub-500ms window, adds the retries Akeneo lacks, and durably queues every product event
Conclusion
Akeneo's Events API webhooks are signed with an x-akeneo-request-signature HMAC over {timestamp}.{body} (5-minute freshness), delivered as batched product/product_model events to one URL per connection, with a sub-500ms ack and no retries. Verify fast, acknowledge immediately, route by action, and reconcile since dropped events aren't retried.
Hookdeck absorbs the sub-500ms window, adds the retries and durability Akeneo's Events API lacks, and verifies signatures at the edge, so your app processes verified product events without losing any.
Get started with Hookdeck for free and handle Akeneo webhooks reliably in minutes.