PHPackages                             ytec/module-webhook - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. ytec/module-webhook

ActiveMagento2-module

ytec/module-webhook
===================

Configurable outgoing webhooks for Magento 2 with Liquid payload templating, conditions, authorization, retries and delivery logs.

1.0.0(1w ago)00MITPHPPHP ~8.1.0||~8.2.0||~8.3.0

Since Jul 22Pushed 1w agoCompare

[ Source](https://github.com/matheusmarqui1/magento2-ytec-webhook)[ Packagist](https://packagist.org/packages/ytec/module-webhook)[ RSS](/packages/ytec-module-webhook/feed)WikiDiscussions main Synced today

READMEChangelogDependencies (2)Versions (2)Used By (0)

Ytec\_Webhook
=============

[](#ytec_webhook)

Configurable outgoing webhooks for Magento 2.

Ytec\_Webhook lets a store define, from the admin panel, HTTP callbacks that fire when sales events happen. Each webhook has its own target URL, method, headers, authorization scheme, Liquid-templated payload, trigger conditions, store scoping and retry policy. Deliveries are queued, retried with configurable backoff, and every attempt is logged with the full request/response for auditing.

- **Vendor:** `ytec/module-webhook`
- **Version:** 1.0.0
- **Magento:** 2.4.x (Open Source &amp; Commerce)
- **PHP:** 8.1 / 8.2 / 8.3
- **License:** MIT

---

Table of contents
-----------------

[](#table-of-contents)

- [Features](#features)
- [Requirements](#requirements)
- [Installation](#installation)
- [Configuration](#configuration)
- [Triggers](#triggers)
- [Delivery lifecycle](#delivery-lifecycle)
- [Payload templating](#payload-templating)
- [Conditions](#conditions)
- [Authorization](#authorization)
- [Retries](#retries)
- [Logging and retention](#logging-and-retention)
- [Health dashboard](#health-dashboard)
- [Test endpoint](#test-endpoint)
- [CLI commands](#cli-commands)
- [Cron jobs](#cron-jobs)
- [Message queue](#message-queue)
- [ACL resources](#acl-resources)
- [Database schema](#database-schema)
- [Extending the module](#extending-the-module)

---

Features
--------

[](#features)

- **Admin-managed webhooks.** Create, duplicate, enable/disable and delete webhook configurations from a grid + form UI, no code or deployment required.
- **Liquid payload templating.** Bodies and URLs are [Liquid](https://shopify.github.io/liquid/) templates rendered against the triggering entity, with an in-form variable suggestion panel built by reflecting the Magento sales API interfaces and the entity's database columns.
- **Condition builder.** Nested AND/OR condition groups with 21 operators decide whether a given entity actually fires the webhook.
- **Six authorization schemes.** None, Basic, Bearer, API key, OAuth 1.0a (signed) and OAuth 2.0 (client credentials, with token fetching).
- **Asynchronous delivery.** Messages are published to a queue and delivered by a consumer, so the checkout/admin request is never blocked. A per-webhook "send immediately" flag is available when synchronous delivery is required.
- **Configurable retries.** Per-webhook retry toggle, max attempts, explicit interval sequence and the list of HTTP status codes considered retryable.
- **Full delivery log.** Every attempt stores URL, method, headers, body, response status, response headers, response body, duration in milliseconds and any error, with a fulltext index for searching.
- **Health dashboard.** Success/failure rates and delivery trends over time.
- **Manual retry.** Retry a failed message from the admin grid, individually or in bulk.
- **Store scoping.** Each webhook can be limited to specific store views.
- **Built-in test endpoint.** A REST endpoint that answers 200 most of the time and 500/504 occasionally, so retry behaviour can be exercised without a third-party server.
- **Simulation command.** Generate real webhook messages in bulk from the CLI to load-test a configuration.

---

Requirements
------------

[](#requirements)

- Magento 2.4.x (Open Source or Commerce)
- PHP 8.1, 8.2 or 8.3
- `ext-curl`
- [`ytec/base`](https://github.com/matheusmarqui1/magento2-ytec-base) (provides the shared `ModuleConfiguration` and the admin menu/ACL root)
- [`liquid/liquid`](https://packagist.org/packages/liquid/liquid) `^1.4.8`
- A running message-queue consumer (AMQP/RabbitMQ or the DB queue) for asynchronous delivery
- Magento cron running, for retries and log cleanup

---

Installation
------------

[](#installation)

### Composer (from this repository)

[](#composer-from-this-repository)

```
composer config repositories.ytec-webhook vcs https://github.com/matheusmarqui1/magento2-ytec-webhook
composer require ytec/module-webhook
```

### Manual

[](#manual)

Copy the module to `app/code/Ytec/Webhook`, then install the `ytec/base` and `liquid/liquid` dependencies with Composer.

### Enable

[](#enable)

```
bin/magento module:enable Ytec_Base Ytec_Webhook
bin/magento setup:upgrade
bin/magento setup:di:compile
bin/magento setup:static-content:deploy
bin/magento cache:flush
```

Start the queue consumer (or let `consumers_runner` do it via cron):

```
bin/magento queue:consumers:start ytec.webhook.message.send
```

---

Configuration
-------------

[](#configuration)

**Stores → Configuration → Ytec → Webhook** (`ytec_webhook`):

PathDefaultScopeDescription`ytec_webhook/general/enabled``0`Store viewMaster switch for the module.`ytec_webhook/logs/enabled``1`DefaultRecord a log row per delivery attempt.`ytec_webhook/logs/retention_hours``730`DefaultHours to keep logs before the cleanup cron deletes them (~30 days).Webhooks themselves are managed under **Ytec → Webhook → Webhook Configurations**. Each configuration holds:

- name, enabled flag and target store views
- the trigger event
- request configuration: URL, HTTP method, headers, body template and authorization
- payload parsing timing
- trigger conditions
- retry policy: enabled, max retries, interval sequence, retryable status codes

---

Triggers
--------

[](#triggers)

Webhooks are bound to one sales event each:

TriggerMagento eventFires whenInvoice creation`sales_order_invoice_save_after`An invoice is savedInvoice pay`sales_order_invoice_pay`An invoice is paidInvoice register`sales_order_invoice_register`An invoice is registered against the orderCredit memo creation`sales_order_creditmemo_save_after`A credit memo is savedCredit memo refund`sales_order_creditmemo_refund`A credit memo is refundedEntity types understood by the payload/entity loader are `invoice`, `order`, `shipment` and `credit_memo`.

---

Delivery lifecycle
------------------

[](#delivery-lifecycle)

1. An observer catches the sales event and hands the entity to `WebhookTriggerHandler`.
2. The handler loads every **enabled** webhook configuration bound to that trigger and applicable to the entity's store, deduplicating within the request.
3. Conditions are evaluated against the entity. A webhook whose conditions do not match is skipped.
4. A `ytec_webhook_message` row is created with status `pending`.
5. The message is published to the `ytec.webhook.message.send` queue, unless the configuration has **send immediately** enabled, in which case it is sent inline.
6. The consumer renders the payload (if the parsing timing is *at sending*), applies authorization, performs the request and writes a log row.
7. On success the message becomes `processed` and `delivered_at` is stamped. On a retryable failure it becomes `failed` with a `next_retry_at`. Once the attempts are used up it becomes `exhausted`.

Message statuses: `pending`, `processing`, `processed`, `failed`, `exhausted`, `error`.

---

Payload templating
------------------

[](#payload-templating)

Bodies and URLs are Liquid templates. The admin form ships a payload editor and a URL editor with a variable-suggestion panel; suggestions are derived at runtime from the relevant Magento interface (`OrderInterface`, `InvoiceInterface`, `CreditmemoInterface`, `ShipmentInterface`, their item and address interfaces) plus the entity table columns, so they stay accurate even with custom attributes.

```
{
  "invoice": "{{ invoice.increment_id }}",
  "order": "{{ invoice.order.increment_id }}",
  "grand_total": {{ invoice.grand_total }},
  "customer_email": "{{ invoice.order.customer_email }}",
  "items": [
    {% for item in invoice.items %}
      { "sku": "{{ item.sku }}", "qty": {{ item.qty }} }{% unless forloop.last %},{% endunless %}
    {% endfor %}
  ]
}
```

URLs are templated too, so a webhook can post to a per-entity path:

```
https://api.example.com/webhook/{{ invoice.increment_id }}

```

### Parsing timing

[](#parsing-timing)

ValueBehaviour`webhook_trigger`Render the body when the event fires and store the rendered payload on the message. The payload reflects the entity exactly as it was at trigger time.`at_sending`Render the body when the message is actually delivered. The payload reflects the entity's current state, which matters for delayed or retried deliveries.---

Conditions
----------

[](#conditions)

Conditions are nested groups combined with `AND` / `OR`, each leaf comparing a resolved entity field against a value.

Available operators: `eq`, `neq`, `gt`, `gte`, `lt`, `lte`, `contains`, `not_contains`, `starts_with`, `ends_with`, `regex`, `in`, `not_in`, `is_null`, `is_not_null`, `is_empty`, `is_not_empty`, `is_true`, `is_false`.

Field paths use the same dotted notation as the payload templates, for example `invoice.order.customer_group_id` or `invoice.grand_total`.

---

Authorization
-------------

[](#authorization)

Selected per webhook in the authorization editor. Secret values are stored encrypted.

TypeWhat it does`none`No authorization header.`basic`HTTP Basic with username/password.`bearer``Authorization: Bearer `.`api_key`Key/value pair sent as a header or query parameter.`oauth1`OAuth 1.0a request signing ([RFC 5849](https://datatracker.ietf.org/doc/html/rfc5849)).`oauth2`OAuth 2.0 client credentials: fetches an access token from the token endpoint and attaches it.New schemes are added by implementing `AuthorizationApplierInterface` and registering the class in the `AuthorizationApplierFactory` DI pool.

---

Retries
-------

[](#retries)

Retries are configured per webhook:

- **Retry enabled** toggles the whole mechanism.
- **Max retries** caps the number of automatic attempts (default 5).
- **Retry intervals** is a comma-separated list of delays in seconds. Attempt *n* uses interval *n*; once the list is exhausted, the last value repeats. For example `60,300,900` means retry after 1 minute, then 5 minutes, then every 15 minutes. Left empty it falls back to `60,300,900,3600,14400`.
- **Retryable status codes** is a comma-separated list of HTTP status codes that count as retryable; anything else is a permanent failure. Left empty it falls back to `408,429,500,502,503,504`.

The `ytec_webhook_retry_scheduler` cron runs every minute and re-queues messages whose `next_retry_at` has passed. Manual retries from the admin grid are counted separately from automatic ones.

---

Logging and retention
---------------------

[](#logging-and-retention)

Every attempt writes a `ytec_webhook_message_log` row containing the request URL, method, headers and body, the response status, headers and body, the round-trip duration in milliseconds, a success flag and any error message. A fulltext index over the URL, bodies and error message makes the log grid searchable.

Logs older than `ytec_webhook/logs/retention_hours` are deleted daily at 03:00 by the `ytec_webhook_log_cleanup` cron. Logging can be turned off entirely.

---

Health dashboard
----------------

[](#health-dashboard)

**Ytec → Webhook → Health Dashboard** charts delivery volume and success/failure rates over time, per webhook configuration. The chart library is loaded from a CDN; on a store with a strict CSP or no outbound access, either allow the CDN or bundle the library locally.

---

Test endpoint
-------------

[](#test-endpoint)

The module exposes a REST endpoint that simulates a flaky third party, useful for exercising retry configuration end to end:

```
POST /rest/V1/ytec-webhook/test
GET  /rest/V1/ytec-webhook/test

```

It answers `200` roughly 98% of the time and `500` or `504` the rest of the time. It is protected by the `Ytec_Webhook::webhook_test` ACL resource.

---

CLI commands
------------

[](#cli-commands)

```
# Run the retry scheduler on demand (processes messages due for retry)
bin/magento ytec:webhook:retry-scheduler

# Create real webhook messages for a configuration, to load-test it
bin/magento ytec:webhook:simulate \
    --id=1 \            # -i  webhook configuration ID (required)
    --count=50 \        # -c  number of messages to create
    --delay=100 \       # -d  delay between creations, in milliseconds
    --start=1000 \      # -s  starting entity ID for the simulated entities
    --entity=invoice \  # -e  invoice | order | shipment | credit_memo
    --immediate         #     send inline instead of publishing to the queue
```

---

Cron jobs
---------

[](#cron-jobs)

JobSchedulePurpose`ytec_webhook_retry_scheduler``* * * * *`Re-queue messages whose retry time has come.`ytec_webhook_log_cleanup``0 3 * * *`Delete logs past the retention window.---

Message queue
-------------

[](#message-queue)

TopicExchangeQueueConsumer`ytec.webhook.message.send``magento``ytec.webhook.message.send``ytec.webhook.message.send`---

ACL resources
-------------

[](#acl-resources)

Nested under `Ytec_Base::base_module`:

```
Ytec_Webhook::webhook
├── Ytec_Webhook::webhook_config
│   ├── Ytec_Webhook::webhook_config_save
│   └── Ytec_Webhook::webhook_config_delete
├── Ytec_Webhook::webhook_dashboard
├── Ytec_Webhook::webhook_messages
├── Ytec_Webhook::webhook_logs
├── Ytec_Webhook::webhook_test
└── Ytec_Webhook::webhook_alerting
    ├── Ytec_Webhook::webhook_alerting_manage
    └── Ytec_Webhook::webhook_alerting_config

```

The `webhook_alerting` branch is declared here as an extension point for a companion alerting module; it is inert without one.

---

Database schema
---------------

[](#database-schema)

TablePurpose`ytec_webhook_config`Webhook definitions: name, enabled, store IDs, trigger, send-immediately flag, parsing timing, request config (JSON), conditions (JSON) and retry policy.`ytec_webhook_message`One row per triggered delivery: config, trigger, entity reference, status, rendered body, automatic/manual retry counters, next retry and delivery timestamps. Cascades on config delete.`ytec_webhook_message_log`One row per attempt: attempt number, request URL/method/headers/body, response status/headers/body, duration, success flag and error message. Cascades on message and config delete.---

Extending the module
--------------------

[](#extending-the-module)

The module is built around interfaces in `Ytec\Webhook\Api`, all wired through `etc/di.xml` preferences, so behaviour can be replaced without touching the module:

InterfaceResponsibility`WebhookTriggerHandlerInterface`Turn an event + entity into webhook messages.`BodyResolverInterface` / `BodyParserInterface`Build the template context for an entity type.`ConditionEvaluatorInterface` / `FieldResolverInterface`Evaluate conditions and resolve field paths.`AuthorizationApplierInterface`Apply an authorization scheme to an outgoing request.`WebhookSenderInterface`Perform the HTTP request and log the attempt.`BackoffCalculatorInterface`Decide whether and when to retry.`EntityLoaderInterface`Reload an entity by type and ID at send time.`DashboardDataProviderInterface`Feed the health dashboard.To support a new entity type, add a `BodyParserInterface` implementation and register it in the `BodyParserFactory` DI pool; to support a new event, add an observer that calls `WebhookTriggerHandlerInterface::handle()` and a case on the `WebhookTrigger` enum.

---

License
-------

[](#license)

MIT. See [LICENSE](LICENSE).

###  Health Score

40

—

FairBetter than 86% of packages

Maintenance98

Actively maintained with recent releases

Popularity0

Limited adoption so far

Community6

Small or concentrated contributor base

Maturity48

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 100% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Unknown

Total

1

Last Release

8d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/aec6ca9769695ebf3a2908a7e174b6d4066819d807794fdf54ee73f4a6d90c79?d=identicon)[matheus.marqui](/maintainers/matheus.marqui)

---

Top Contributors

[![matheusmarqui1](https://avatars.githubusercontent.com/u/97516243?v=4)](https://github.com/matheusmarqui1 "matheusmarqui1 (1 commits)")

---

Tags

magentowebhookswebhookintegrationmagento2liquidmagento2 modulemagento 2 modulemagento2 extension

### Embed Badge

![Health badge](/badges/ytec-module-webhook/health.svg)

```
[![Health](https://phpackages.com/badges/ytec-module-webhook/health.svg)](https://phpackages.com/packages/ytec-module-webhook)
```

###  Alternatives

[olegkoval/magento2-regenerate-url-rewrites

Add into Magento 2 a CLI feature which allow to regenerate a Url Rewrites of products and categories

4483.9M2](/packages/olegkoval-magento2-regenerate-url-rewrites)[magepsycho/magento2-custom-shipping

Magento 2 Custom Shipping

708.4k](/packages/magepsycho-magento2-custom-shipping)[run-as-root/magento2-prometheus-exporter

Magento2 Prometheus Exporter

68357.9k](/packages/run-as-root-magento2-prometheus-exporter)[magepsycho/magento2-storepricing

Magento 2 Store View Pricing

2624.4k](/packages/magepsycho-magento2-storepricing)[magepsycho/magento2-easy-template-path-hints

Easy Template Path Hints for Magento 2

441.0k](/packages/magepsycho-magento2-easy-template-path-hints)[magepsycho/magento2-discountlimit

Magento 2 Discount Amount Limiter

1012.3k](/packages/magepsycho-magento2-discountlimit)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
