chimpmatic / mailchimp-webhook-handler
Parse and handle Mailchimp webhook payloads. Typed events, signature verification, zero dependencies, PHP 8.5+.
Package info
github.com/chimpmatic/mailchimp-webhook-handler
pkg:composer/chimpmatic/mailchimp-webhook-handler
Requires
- php: >=8.5
Requires (Dev)
- phpunit/phpunit: ^11.0 || ^12.0
README
Parse and handle Mailchimp webhook payloads. Typed events, secret verification, event listeners, zero dependencies, PHP 8.5+.
Author: Chimpmatic
Why This Exists
Mailchimp sends webhook notifications when subscribers join, leave, update their profile, change their email, or get cleaned from your audience. Parsing these payloads means dealing with nested form data, extracting merge fields, and routing events to the right handler.
This library turns raw $_POST data into typed, readonly objects with a clean event listener API.
Built for Contact Form 7 to Mailchimp integrations, but works with any PHP application.
Requirements
- PHP 8.5 or higher (uses
readonlyclasses and enums) - No extensions required (zero dependencies)
A fatal error (E_USER_ERROR) is triggered if loaded on PHP < 8.5. The library will not run on older versions.
Installation
composer require chimpmatic/mailchimp-webhook-handler
Quick Start
use Chimpmatic\WebhookHandler\WebhookHandler; use Chimpmatic\WebhookHandler\WebhookEvent; use Chimpmatic\WebhookHandler\WebhookPayload; $handler = new WebhookHandler(); // Register listeners $handler->on(WebhookEvent::Subscribe, function (WebhookPayload $payload): void { echo "New subscriber: {$payload->email}"; echo "Name: {$payload->getMergeField('FNAME')} {$payload->getMergeField('LNAME')}"; }); $handler->on(WebhookEvent::Unsubscribe, function (WebhookPayload $payload): void { echo "Unsubscribed: {$payload->email} — reason: {$payload->getReason()}"; }); // Handle the incoming webhook $payload = $handler->handle($_POST); echo $payload->getSummary();
Supported Events
| Event | Mailchimp Type | Description |
|---|---|---|
Subscribe |
subscribe |
New subscriber added |
Unsubscribe |
unsubscribe |
Subscriber removed |
ProfileUpdate |
profile |
Subscriber updated their profile |
EmailChanged |
upemail |
Subscriber changed their email |
Cleaned |
cleaned |
Email bounced (hard/soft) |
Campaign |
campaign |
Campaign sent to list |
Webhook Endpoint
use Chimpmatic\WebhookHandler\WebhookHandler; use Chimpmatic\WebhookHandler\WebhookException; $handler = new WebhookHandler('your-webhook-secret'); // Mailchimp sends a GET request to validate the URL if ($handler->isValidationRequest($_SERVER['REQUEST_METHOD'])) { http_response_code(200); exit; } // Verify the secret (Mailchimp appends ?secret=... to the URL) if (!$handler->verifySecret($_GET['secret'] ?? '')) { http_response_code(403); exit; } try { $payload = $handler->handle($_POST); http_response_code(200); } catch (WebhookException $e) { http_response_code(400); echo $e->getMessage(); }
Working with Payloads
$handler->on(WebhookEvent::Subscribe, function (WebhookPayload $payload): void { // Basic info echo $payload->email; // "john@example.com" echo $payload->audienceId; // "abc123def4" echo $payload->firedAt; // "2026-03-16 21:00:00" echo $payload->event->value; // "subscribe" // Merge fields echo $payload->getMergeField('FNAME'); // "John" echo $payload->getMergeField('LNAME'); // "Doe" // Full summary echo $payload->getSummary(); // "[2026-03-16 21:00:00] subscribe — john@example.com (audience: abc123def4)" });
Email Changed Events
$handler->on(WebhookEvent::EmailChanged, function (WebhookPayload $payload): void { echo "Old: {$payload->getOldEmail()}"; // "old@example.com" echo "New: {$payload->getNewEmail()}"; // "new@example.com" });
Listen to All Events
$handler->onAny(function (WebhookPayload $payload): void { // Log every webhook error_log($payload->getSummary()); });
Parse Without Dispatching
// Just parse, don't trigger listeners $payload = $handler->parse($_POST); if ($payload->isSubscribe()) { // ... }
Error Handling
use Chimpmatic\WebhookHandler\WebhookException; try { $handler->parse($_POST); } catch (WebhookException $e) { // Empty payload, missing type, unknown event type, invalid data }
Related Packages
- mailchimp-api-key-validator — Validate API key format and connectivity
- mailchimp-audience-finder — Find Audience IDs and merge fields
- mailchimp-subscriber — Subscribe contacts with merge fields
Links
- Packagist
- GitHub
- Issues
- Connect Contact Form 7 with Mailchimp
- How to Get Your Mailchimp API Key
- Mailchimp Audience Fields and Merge Tags
- Chimpmatic — Contact Form 7 to Mailchimp
License
MIT License. Copyright (c) 2026 Chimpmatic.