TYPO3 Webhooks 

Extension key

webhooks

Package name

typo3/cms-webhooks

Version

13.4

Language

en

Author

TYPO3 contributors

License

This document is published under the Creative Commons BY-NC-SA 4.0 license.

Rendered

Tue, 14 Apr 2026 11:04:06 +0000


This extension handles outgoing webhooks to TYPO3. It also provides a corresponding backend module to manage reaction records in the TYPO3 backend System > Webhooks.


Table of Contents:

Introduction 

A webhook is an automated message sent from one application to another via HTTP.

This extension adds the possibility to configure webhooks in TYPO3.

The backend module System > Webhooks provides the possibility to configure webhooks. The module is available in the TYPO3 backend for users with administrative rights.

A webhook is defined as an authorized POST or GET request to a defined URL. For example, a webhook can be used to send a notification to a Slack channel when a new page is created in TYPO3.

Any webhook record is defined by a unique uid (UUID), a speaking name, an optional description, a trigger, the target URL and a signing-secret. Both the unique identifier and the signing-secret are generated in the backend when a new webhook is created.

Installation 

This extension is part of the TYPO3 Core, but not installed by default.

Table of contents

Installation with Composer 

Check whether you are already using the extension with:

composer show | grep webhooks
Copied!

This should either give you no result or something similar to:

typo3/cms-webhooks       v12.4.11
Copied!

If it is not installed yet, use the composer require command to install the extension:

composer require typo3/cms-webhooks
Copied!

The given version depends on the version of the TYPO3 Core you are using.

Installation without Composer 

In an installation without Composer, the extension is already shipped but might not be activated yet. Activate it as follows:

  1. In the backend, navigate to the Admin Tools > Extensions module.
  2. Click the Activate icon for the Webhooks extension.

Triggers 

The TYPO3 Core currently provides the following triggers for webhooks:

Page Modification
Triggers when a page is created, updated or deleted
File Added
Triggers when a file is added
File Updated
Triggers when a file is updated
File Removed
Triggers when a file is removed
Login Error Occurred
Triggers when a login error occurred

These triggers are meant as a first set of triggers that can be used to send webhooks. In most projects however, it is likely that custom triggers are required.

Custom triggers 

Trigger by PSR-14 events 

Custom triggers can be added by creating a Message for a specific PSR-14 event and by tagging that message as a webhook message.

The following example shows how to create a simple webhook message for the \TYPO3\CMS\Core\Resource\Event\AfterFolderAddedEvent :

EXT:my_extension/Webhooks/Message/FolderAddedMessage.php
<?php

declare(strict_types=1);

namespace MyVendor\MyExtension\Webhooks\Message;

use TYPO3\CMS\Core\Attribute\WebhookMessage;
use TYPO3\CMS\Core\Messaging\WebhookMessageInterface;
use TYPO3\CMS\Core\Resource\Event\AfterFolderAddedEvent;

#[WebhookMessage(
    identifier: 'typo3/folder-added',
    description: 'LLL:EXT:webhooks/Resources/Private/Language/locallang_db.xlf:sys_webhook.webhook_type.typo3-folder-added'
)]
final class FolderAddedMessage implements WebhookMessageInterface
{
    public function __construct(
        private readonly int $storageUid,
        private readonly string $identifier,
        private readonly string $publicUrl
    ) {}

    public static function createFromEvent(AfterFolderAddedEvent $event): self
    {
        $folder = $event->getFolder();
        return new self($folder->getStorage()->getUid(), $folder->getIdentifier(), $folder->getPublicUrl());
    }

    public function jsonSerialize(): array
    {
        return [
            'storage' => $this->storageUid,
            'identifier' => $this->identifier,
            'url' => $this->publicUrl,
        ];
    }
}
Copied!
  1. Create a final class implementing the WebhookMessageInterface .
  2. Add the WebhookMessage attribute to the class. The attribute requires the following information:

    • identifier: The identifier of the webhook message.
    • description: The description of the webhook message. This description is used to describe the trigger in the TYPO3 backend.
  3. Add a static method createFromEvent() that creates a new instance of the message from the event you want to use as a trigger.
  4. Add a method jsonSerialize() that returns an array with the data that should be send with the webhook.

Use Services.yaml instead of the PHP attribute 

Instead of the PHP attribute the Services.yaml can be used to define the webhook message. The following example shows how to define the webhook message from the example above in the Services.yaml:

EXT: my_extension/Configuration/Services.yaml
# ...

TYPO3\CMS\Webhooks\Message\FolderAddedMessage:
  tags:
    - name: 'core.webhook_message'
      identifier: 'typo3/folder-added'
      description: 'LLL:EXT:webhooks/Resources/Private/Language/locallang_db.xlf:sys_webhook.webhook_type.typo3-folder-added'
Copied!

Trigger by hooks or custom code 

In case a trigger is not provided by the TYPO3 Core or a PSR-14 event is not available, it is possible to create a custom trigger - for example by using a TYPO3 hook.

The message itself should look similar to the example above, but does not need the createFromEvent() method.

Instead, the custom code (hook implementation) will create the message and dispatch it.

Example hook implementation for a datahandler hook (see \TYPO3\CMS\Webhooks\Listener\PageModificationListener ):

EXT:my_extension/Webhooks/Message/PageModificationListener.php
<?php

declare(strict_types=1);

namespace MyVendor\MyExtension\Webhooks\Hook;

use Symfony\Component\Messenger\MessageBusInterface;
use TYPO3\CMS\Core\DataHandling\DataHandler;
use TYPO3\CMS\Core\Site\SiteFinder;
use TYPO3\CMS\Webhooks\Message\PageModificationMessage;

final class PageModificationListener
{
    public function __construct(
        private readonly MessageBusInterface $bus,
        private readonly SiteFinder $siteFinder,
    ) {}

    public function processDatamap_afterDatabaseOperations($status, $table, $id, $fieldArray, DataHandler $dataHandler)
    {
        if ($table !== 'pages') {
            return;
        }
        // ...
        $site = $this->siteFinder->getSiteByPageId($id);
        $message = new PageModificationMessage(
            'new',
            $id,
            $fieldArray,
            $site->getIdentifier(),
            (string)$site->getRouter()->generateUri($id),
            $dataHandler->BE_USER,
        );
        // ...
        $this->bus->dispatch($message);
    }
}
Copied!

Hash calculation 

With every webhook request, the following HTTP headers are sent:

HTTP Header of a webhooks
Content-Type: application/json
Webhook-Signature-Algo: sha256
Webhook-Signature: <hash>
Copied!

The hash is calculated with the secret of the webhook and the JSON encoded data of the request. The hash is created with the PHP function hash_hmac().

The hash is calculated with the following PHP code:

$hash = hash_hmac('sha256', sprintf(
    '%s:%s',
    $identifier, // The identifier of the webhook (uuid)
    $body // The JSON encoded body of the request
), $secret); // The secret of the webhook
Copied!

The hash is sent as HTTP header Webhook-Signature and should be used to validate that the request was sent from the TYPO3 instance and has not been manipulated. To verify this on the receiving end, build the hash with the same algorithm and secret and compare it with the hash that was sent with the request.

The hash is not meant to be used as a security mechanism, but as a way to verify that the request was sent from the TYPO3 instance.

Technical background and advanced usage 

The webhook system is based on the Symfony Messenger component. The messages are simple PHP objects that implement an interface that denotes them as Webhook messages.

That message is then dispatched to the Symfony Messenger bus. The TYPO3 Core provides a WebhookMessageHandler that is responsible for sending the webhook requests to the third-party system if configured to do so. The handler looks up the webhook configuration and sends the request to the configured URL.

Messages are sent to the bus in any case. The handler is then responsible for checking whether or not an external request (webhook) should be sent.

If advanced request handling is necessary or a custom implementation should be used, a custom handler can be created that handles WebhookMessageInterface messages. See the Message bus for more information on messages and their handlers.

Sitemap