Skip to content
MAGENTO EXTENSIONS

Magento 2 Webhooks: The Complete Integration Guide

How webhooks fit Magento 2 API integration: REST polling vs push, what core ships, a DIY observer with its failure modes, and a queue-based module.

Shane Blandford
Shane Blandford · FOUNDERPUBLISHED · 9 MIN READ

Magento 2 Open Source has no built-in outbound webhooks. Nothing in core will POST to an external URL when an order is placed, so every Magento 2 API integration ends up choosing between polling the REST API, wiring a custom observer to an HTTP client, or installing an extension such as the OCM Labs Webhooks module for Magento 2. We build and sell that module, so weigh our advice with that in mind. This guide walks through all three paths, including the code and the ways each one fails.

What is a webhook in Magento 2?

A webhook is an HTTP request your store sends to an external system the moment something happens: an order lands, a shipment goes out, stock drops. The receiving system gets a JSON payload describing the event within seconds, instead of discovering it on its next scheduled API poll.

That direction matters. The Magento 2 REST API is pull: the external system asks Magento what changed. A webhook is push: Magento tells the external system. Most real Magento integration projects need both. The REST API is the right tool when the other system initiates (an ERP writing tracking numbers back, a PIM pushing product data in). Webhooks are the right tool when Magento initiates (new order to fulfillment, new customer to the CRM, stock alert to Slack).

Webhooks vs the Magento 2 REST API: why not just poll?

Polling works, and for some integrations it is fine. A cron on the other side calls GET /rest/V1/orders with a searchCriteria filter on updated_at, processes what came back, stores a cursor, repeats. If a 15 minute delay is acceptable and the other system can hold state, stop reading and go build that.

Polling starts to hurt in four specific places:

  • Latency is your poll interval. Poll every 15 minutes and your average notification delay is 7.5 minutes. Tightening the interval trades latency for load.
  • Most polls return nothing. A store doing 200 orders a day polled every minute makes about 1,440 API calls to learn something about 200 of them. Each call authenticates, hits the database, and serializes a response.
  • Intermediate states disappear. Poll on updated_at and an order that went pending, then processing, then complete between two polls shows you only the final state. If your integration cares about the transition, it never sees it.
  • You maintain a poller. Cursor storage, overlap windows so edits on the boundary are not missed, backoff when Magento is slow. It is not hard, but it is code that exists forever.

A webhook flips the cost. The store does one HTTP POST per event that actually happened, the receiver holds no polling state, and latency is measured in seconds. The price is that now delivery is your problem: what happens when the endpoint is down, how do you retry, how does the receiver trust the request. The rest of this guide is about paying that price properly.

Does Magento 2 have built-in webhooks?

No. Magento 2 Open Source through 2.4.x ships a REST API, a GraphQL API, an event and observer system, and a message queue framework, but no facility to register an outbound webhook URL. There is no admin screen for it and no core module that does it.

Adobe's answer to this lives outside Open Source. Adobe I/O Events for Adobe Commerce forwards Commerce events to Adobe's event infrastructure, where App Builder applications consume them. It requires Adobe Commerce 2.4.4 or higher, and Adobe's documentation is explicit that Magento Open Source is not supported. It also requires an App Builder project in the Adobe developer console before the Commerce-side modules do anything. Adobe Commerce additionally has a separate "webhooks" feature in its extensibility framework, but those are synchronous calls made during a Commerce operation so an external system can validate or modify it. Different tool, different job, and also not part of Open Source.

So on Open Source, outbound webhooks are something you add. We compare all three approaches in more depth in webhooks vs Adobe I/O Events vs custom observers; here we will take the two Open Source paths in turn.

Can you build Magento 2 webhooks with a custom observer?

Yes, in about 30 lines, and that is exactly the problem: the 30 lines work in a demo and misbehave in production. Here is the naive version. First, etc/events.xml:

<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:noNamespaceSchemaLocation="urn:magento:framework:Event/etc/events.xsd">
    <event name="sales_order_place_after">
        <observer name="acme_order_webhook"
                  instance="Acme\Integration\Observer\SendOrderWebhook"/>
    </event>
</config>

Then the observer:

<?php
namespace Acme\Integration\Observer;

use GuzzleHttp\Client;
use Magento\Framework\Event\Observer;
use Magento\Framework\Event\ObserverInterface;

class SendOrderWebhook implements ObserverInterface
{
    public function __construct(private readonly Client $client) {}

    public function execute(Observer $observer): void
    {
        $order = $observer->getEvent()->getOrder();
        $this->client->post('https://example.com/hooks/order', [
            'json' => ['increment_id' => $order->getIncrementId()],
            'timeout' => 5,
        ]);
    }
}

This delivers a webhook. It also has five production problems you will meet in roughly this order:

  1. It blocks checkout. Magento 2 dispatches observers synchronously, and sales_order_place_after fires inside the order placement request. Every millisecond your endpoint takes is added to the shopper's checkout. Forget the timeout option (Guzzle's default is to wait indefinitely) and a hung endpoint holds the checkout request until PHP's own limits kill it.
  2. A failed delivery can fail the order. An uncaught Guzzle exception propagates out of the observer and aborts order placement. So you wrap it in try/catch, and now failures are silent instead of fatal. Pick your poison.
  3. There are no retries. Endpoint down for a two minute deploy? Every event in that window is gone. Rebuilding lost events after the fact means writing the exact REST API poller you were trying to avoid.
  4. There is no signing. Your receiver has no way to verify the POST came from your store rather than anyone who found the URL.
  5. There is no log. When the ERP team says "we never got order 100004521", you have nothing to show them.

The correct DIY fix for problem 1 and 2 is to stop doing HTTP in the observer: snapshot the data, publish it to a Magento message queue (the db connection works without RabbitMQ), and do the delivery in a consumer. That is genuinely the right architecture. It is also the point where the weekend project becomes a real module, because you still owe yourself retries with backoff, HMAC signing, an idempotency key, a delivery log, and payload templating. We know because we wrote that module.

How does the OCM Labs Webhooks module handle delivery?

Disclosure again: this is our product. The OCM Labs Webhooks module for Magento 2 ($250, Magento Open Source and Adobe Commerce 2.4.7 to 2.4.8, PHP 8.2 to 8.4) is the queue-based architecture above, finished:

  • Events. Subscribe a URL to any of ten curated events covering orders, shipments, invoices, credit memos, customers, products, and stock, or flip on custom events and subscribe to any Magento event by name, like checkout_cart_product_add_after. Each webhook can be scoped to specific store views.
  • Non-blocking capture. When an event fires, a lightweight observer snapshots the entity data and publishes to the ocmlabs.webhook.trigger queue on Magento's built-in db connection. Checkout never waits on template rendering or HTTP. Snapshotting also means a Product Deleted webhook still carries full product data even though the row is gone by delivery time.
  • Payload shaping. Each webhook's body is a Smarty template you edit in the admin, so you send the JSON your receiver expects instead of transforming a fixed blob on the other side. A live variables panel shows the real fields for your selected event, and a Send Test button delivers a sample synchronously before you save.
  • Delivery you can prove. Delivery is at-least-once with automatic retries on exponential backoff (defaults: 60 second base, 3 attempts, both configurable). Every attempt of a delivery shares an idempotency UUID sent as X-Webhook-Delivery-Id, and every attempt is logged in the admin with status, HTTP code, duration, and the response body your endpoint returned.
  • Security. Set a secret and every request carries an X-Webhook-Signature HMAC-SHA256 header computed over the exact bytes on the wire. Verify it on your receiver with hash_equals(). Bearer and Basic auth are supported per webhook, credentials are encrypted at rest, destination URLs pass an SSRF guard, and templates run in a locked-down sandbox.

How do you set up a webhook in Magento 2?

With the module, the whole path from install to first delivery looks like this:

composer require ocmlabs/module-webhook
bin/magento module:enable OCMLabs_Webhook
bin/magento setup:upgrade
bin/magento setup:di:compile
bin/magento cache:flush

Then:

  1. Make sure the queue consumer runs. This is the step people miss: on the db queue connection nothing delivers until the ocmlabs.webhook.trigger consumer is running, either via Magento cron (the default when cron_consumers_runner is absent from env.php) or under a process supervisor.
  2. Go to System > OCM Labs > Webhooks. Ten disabled sample webhooks ship with the module, one per curated event, each with a working default template. Open one or click Add New Webhook.
  3. Pick the event, enter your destination URL, optionally set a secret and auth, and adjust the prefilled payload template.
  4. Click Send Test, check the response, save, and enable.
  5. Trigger the real event and watch it land in System > OCM Labs > Delivery Log.

If you are wiring the webhook into a no-code platform rather than your own endpoint, we wrote up the specifics in connecting Magento 2 to Zapier, Make, or n8n. And if you are evaluating the wider category, our Magento extensions page lists everything we ship.

FAQ

Does Magento 2 Open Source have native webhooks?+
No. Open Source 2.4.x has REST and GraphQL APIs, observers, and message queues, but no outbound webhook facility. Adobe I/O Events requires Adobe Commerce 2.4.4 or higher and does not support Magento Open Source, so on Open Source you either poll, write a custom module, or install one.
Are webhooks a replacement for the Magento 2 REST API?+
No, they cover the other direction. Use the REST API when an external system needs to read from or write to Magento on its own schedule. Use webhooks when Magento should notify the external system the moment an event happens. Most complete integrations use both.
Do webhooks slow down checkout?+
A naive observer that makes an HTTP call does, because Magento runs observers synchronously inside the checkout request. A queue-based pipeline does not: the request path only snapshots data and publishes a message, and a separate consumer does the rendering, signing, and HTTP.
What happens when the receiving endpoint is down?+
With the OCM Labs module, the delivery is rescheduled with exponential backoff (1 minute, then 2, with the defaults) until the configured attempt limit, and every attempt is visible in the delivery log. Delivery is at-least-once, so receivers should dedupe on the X-Webhook-Delivery-Id header.
How does the receiver know a webhook really came from my store?+
Configure a secret on the webhook and verify the X-Webhook-Signature header: compute sha256= plus the HMAC-SHA256 of the raw request body with your shared secret, and compare using a constant-time function like PHP's hash_equals().
Can I send a webhook for an event that is not in the curated list?+
Yes. Enable custom events under Stores > Configuration > OCM Labs > Webhooks > Advanced, then subscribe a webhook to any Magento event by name. The payload exposes whatever data that event carries, and Send Test shows you the exact shape before you go live.
Shane Blandford

Shane Blandford

FOUNDER

Founder of Orange Collar Media, a Denver ecommerce agency behind 800+ Magento and Shopify builds. In Magento since version 1.x - building, rescuing, and supporting revenue-critical stores since 2008.

All posts by Shane Blandford

KEEP READING

Related from the Journal.

Your store can sell more. Let's find out how much.

Start a project