Appearance
MailerLite Technical Integration
Technical reference for IxDF's MailerLite integration. For business context, see mailerlite-overview.md.
Architecture
Data Flow
Outbound: App → MailerLite
Payload: email, name, country, member_status, membership_plan_category, membership_expire_at
Inbound: MailerLite → App
Payload Fields
Fields sent to MailerLite (see overview for field descriptions):
php
// Subscriber::getMembershipStatus()
if (no membership found) → "non-member"
if (membership.canceled) → "canceled"
else → "active-or-expired" // Grouped to avoid daily sync churnWhy "active-or-expired"? Separating active from expired would cause daily sync churn as memberships expire.
Key Files
| Component | Path |
|---|---|
| Configuration | config/ixdf_mailerlite.php |
| Service Provider | Subscription/SubscriptionServiceProvider.php |
| API Manager | Subscription/Services/MailerLite/MailerLiteSubscriberDataManager.php |
| Sync Job | Subscription/Jobs/MailerLite/SendSubscriberData.php |
| Payload DTO | Subscription/Services/MailerLite/SubscriberPayload.php |
| Subscriber Event | Subscription/Listeners/UpdateSubscriberInExternalList.php |
| Membership Event | Subscription/Listeners/UpdateMembershipInExternalList.php |
| Webhook Handler | Subscription/Http/Controllers/Webhooks/MailerLite/UpdateSubscriberStatusController.php |
| Verification | Subscription/Actions/VerifySubscriberInMailerLiteAction.php |
Error Handling
Retryable Errors (auto-retry for 12h)
- HTTP 408 Request Timeout
- HTTP 429 Too Many Requests
- HTTP 5xx Server Errors
Non-Retryable Errors (logged, job fails)
- HTTP 4xx Client Errors (validation failures)
- Invalid API key
- Malformed payload
Exception Classes
text
MailerLiteRetryableIssue → Transient failures, will retry
MailerLiteNotRetryableIssue → Permanent failures, logged
MailerLiteUnclassifiedApiResponse → Unknown status, logged for investigationRate Limiting
By early 2026, MailerLite has a limit of 60 req/min.
php
// Configured in SubscriptionServiceProvider
RateLimiter::for('api:mailerlite', fn() => [
Limit::perMinute(60),
Limit::perSecond(1),
]);
// Applied via job middleware
public function middleware(): array
{
return [new RateLimited('api:mailerlite')];
}Testing & Debugging
Verify Sync Status
php
// Via Nova action or tinker
$action = new VerifySubscriberInMailerLiteAction();
$result = $action->execute($subscriber);
// Returns: ['found' => bool, 'synced' => bool, 'issues' => [...]]Manual Sync
php
// Force sync a subscriber
dispatch(new SendSubscriberData($subscriber));Health Check
bash
# Module-level health:check contains mailerlite part:
php artisan subscription:health:check --mailerlite-sample=10
# Check whether MailerLite webhooks integration is enabled:
php artisan subscription:mailerlite:check-webhookCommon Issues
| Symptom | Cause | Solution |
|---|---|---|
| Subscriber not in MailerLite | Job failed or still queued | Check Horizon; re-dispatch job |
| Wrong segment membership | member_status out of sync | Trigger membership update event |
| Webhook not processing | Signature mismatch | Verify secret in .env |
| Rate limit errors | Too many concurrent syncs | Jobs auto-retry; wait for backlog |
Related Documentation
- MailerLite Overview — Account structure, segments, automations (read this first)
- MailerLite API Docs — External API reference