PHPackages                             susheelhbti/reachhub - 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. [API Development](/categories/api)
4. /
5. susheelhbti/reachhub

ActiveLibrary[API Development](/categories/api)

susheelhbti/reachhub
====================

ReachHub — Multi-channel marketing automation for Laravel. Email, WhatsApp, SMS, Push, AI, Workflows, GDPR &amp; more via REST API.

00PHP

Since May 17Pushed 3w agoCompare

[ Source](https://github.com/susheelhbti/ReachHub)[ Packagist](https://packagist.org/packages/susheelhbti/reachhub)[ RSS](/packages/susheelhbti-reachhub/feed)WikiDiscussions main Synced 1w ago

READMEChangelogDependenciesVersions (1)Used By (0)

📣 ReachHub v4 — Laravel Multi-Channel Marketing Automation
==========================================================

[](#-reachhub-v4--laravel-multi-channel-marketing-automation)

> The only open-source marketing automation package that gives you AI-powered content generation, multi-channel campaigns, GDPR compliance, and enterprise webhooks — completely free. Self-hosted. Zero per-contact pricing. Ever.

---

✨ Feature Overview
------------------

[](#-feature-overview)

CategoryFeatures📡 **Channels**Email (Laravel Mail), WhatsApp (Meta Cloud API), SMS (Twilio / Vonage), Push (Firebase FCM)🤖 **AI**Subject line generation, channel adaptation, spam analysis, send-time optimisation — local Ollama (free) or OpenAI🔄 **Workflows**Multi-step drip sequences, conditional branching, delays, tag/list actions, outbound webhooks🔐 **Privacy / GDPR**AES-256-GCM field encryption, right to erasure, consent tracking with cryptographic proof, data export🚫 **Suppression**Global per-channel suppression list, auto-suppress hard bounces, bulk import🔑 **API Auth**Single token (simple) or multi-key with resource-level permission scopes📦 **Templates**Email template library with 6 built-in presets + custom templates✅ **QA Tools**Campaign preview, pre-send validation (spam, broken links, length), test sends🔌 **Webhooks (outbound)**19 events, HMAC-signed, bearer/basic/header auth, auto-retry, attempt logging📥 **Import / Migration**Mailchimp API, CSV (with column-mapping preview), JSON bulk import📊 **Analytics**Per-campaign stats, open/click/failure rates, contact timeline, calendar view⚙️ **Background Jobs**Chunked queue delivery, exponential backoff retries, campaign archiving, GDPR cleanup---

🚀 Installation
--------------

[](#-installation)

### 1. Install the package

[](#1-install-the-package)

```
composer require susheelhbti/reachhub
```

Optional extras:

```
composer require league/csv          # advanced CSV import preview
```

### 2. Publish config &amp; migrate

[](#2-publish-config--migrate)

```
php artisan vendor:publish --tag=reachhub-config
php artisan migrate
```

### 3. Configure `.env`

[](#3-configure-env)

```
# ── Auth ───────────────────────────────────────────────
REACHHUB_API_TOKEN=your-secret-token   # simple mode
# REACHHUB_AUTH_MODE=api_keys          # switch to multi-key mode

# ── Queue ──────────────────────────────────────────────
REACHHUB_QUEUE=campaigns
REACHHUB_QUEUE_CONNECTION=redis

# ── AI (pick one) ──────────────────────────────────────
REACHHUB_AI_DRIVER=ollama              # local, free, private
OLLAMA_URL=http://localhost:11434
OLLAMA_MODEL=mistral

# REACHHUB_AI_DRIVER=openai
# OPENAI_API_KEY=sk-...

# ── Email ───────────────────────────────────────────────
REACHHUB_EMAIL_ENABLED=true
MAIL_FROM_ADDRESS=hello@example.com
MAIL_FROM_NAME="My App"

# ── WhatsApp (Meta Cloud API) ───────────────────────────
REACHHUB_WHATSAPP_ENABLED=true
WHATSAPP_PHONE_NUMBER_ID=xxx
WHATSAPP_ACCESS_TOKEN=xxx
WHATSAPP_WEBHOOK_VERIFY_TOKEN=my-verify-secret

# ── SMS ─────────────────────────────────────────────────
REACHHUB_SMS_ENABLED=true
REACHHUB_SMS_PROVIDER=twilio           # or vonage
TWILIO_ACCOUNT_SID=ACxxxxxxxx
TWILIO_AUTH_TOKEN=xxxxxxxx
TWILIO_FROM_NUMBER=+1xxxxxxxxxx

# ── Push (FCM) ──────────────────────────────────────────
REACHHUB_PUSH_ENABLED=true
FCM_SERVER_KEY=xxx

# ── Privacy ─────────────────────────────────────────────
REACHHUB_GDPR_YEARS=2                  # auto-erase after N years inactive
REACHHUB_ENCRYPT_PII=false             # set true to encrypt email/phone at rest
```

### 4. Register the scheduler (required for automation)

[](#4-register-the-scheduler-required-for-automation)

**Laravel 11+** — `routes/console.php`:

```
use Illuminate\Support\Facades\Schedule;

Schedule::command('reachhub:dispatch-scheduled')->everyMinute();
Schedule::command('reachhub:workflow-tick')->everyMinute();
Schedule::command('reachhub:retry-failed')->everyFiveMinutes();
Schedule::command('reachhub:gdpr-cleanup')->daily();
Schedule::command('reachhub:archive-campaigns --days=90')->weekly();
```

**Laravel 10** — `app/Console/Kernel.php`:

```
protected function schedule(Schedule $schedule): void
{
    $schedule->command('reachhub:dispatch-scheduled')->everyMinute();
    $schedule->command('reachhub:workflow-tick')->everyMinute();
    $schedule->command('reachhub:retry-failed')->everyFiveMinutes();
    $schedule->command('reachhub:gdpr-cleanup')->daily();
    $schedule->command('reachhub:archive-campaigns')->weekly();
}
```

Then enable the cron:

```
* * * * * cd /path/to/project && php artisan schedule:run >> /dev/null 2>&1

```

---

📡 API Reference
---------------

[](#-api-reference)

All endpoints require:

```
Authorization: Bearer
Content-Type: application/json

```

Base URL: `https://your-app.com/api/reachhub`

---

### 👥 Contacts

[](#-contacts)

MethodEndpointDescriptionGET`/contacts`List contacts (`?search=&subscribed=`)POST`/contacts`Create contactGET`/contacts/{id}`Get contactPUT`/contacts/{id}`Update contactDELETE`/contacts/{id}`Delete contactPOST`/contacts/import`Bulk import (up to 5 000)POST`/contacts/import/preview`Preview CSV + auto-map columnsPOST`/contacts/import/validate-mapping`Validate mapping before importPOST`/contacts/{id}/unsubscribe`Unsubscribe (adds to suppression)GET`/contacts/{id}/timeline`Full activity timeline**Create contact**

```
{
  "name": "Ravi Kumar",
  "email": "ravi@example.com",
  "phone": "+919876543210",
  "whatsapp": "+919876543210",
  "fcm_token": "firebase-token",
  "tags": ["vip", "india"],
  "custom_fields": { "city": "Gorakhpur" }
}
```

---

### 📋 Contact Lists

[](#-contact-lists)

MethodEndpointDescriptionGET/POST`/lists`CRUDGET/PUT/DELETE`/lists/{id}`Single listPOST`/lists/{id}/contacts/attach`Attach contactsPOST`/lists/{id}/contacts/detach`Detach contacts---

### 📣 Campaigns

[](#-campaigns)

MethodEndpointDescriptionGET`/campaigns`List (`?channel=&status=&search=`)POST`/campaigns`Create campaignGET`/campaigns/{id}`Get campaignPUT`/campaigns/{id}`Update campaignDELETE`/campaigns/{id}`Delete campaignPOST`/campaigns/{id}/send`Dispatch immediatelyPOST`/campaigns/{id}/schedule`Schedule for laterPOST`/campaigns/{id}/cancel`CancelPOST`/campaigns/{id}/pause`Pause active sendPOST`/campaigns/{id}/resume`Resume from where pausedPOST`/campaigns/{id}/duplicate`Duplicate as draftPOST`/campaigns/{id}/submit-approval`Submit for reviewPOST`/campaigns/{id}/approve`Approve campaignPOST`/campaigns/{id}/reject`Reject with notesGET`/campaigns/{id}/preview`Rendered previewPOST`/campaigns/{id}/validate`Pre-send QA checkPOST`/campaigns/{id}/test-send`Send test to email(s)POST`/campaigns/{id}/apply-template/{tid}`Apply email templateGET`/campaigns/calendar`Month calendar view**Create Email campaign**

```
{
  "name": "May Newsletter",
  "channel": "email",
  "subject": "Hello {{name}}, here's what's new!",
  "body": "Hi {{name}}Exclusive offers inside.",
  "from_name": "My Brand",
  "from_address": "news@mybrand.com",
  "contact_list_ids": [1, 2],
  "tags": ["newsletter", "may-2024"],
  "category": "newsletter",
  "template_vars": { "{{promo_code}}": "MAY20" }
}
```

**Create WhatsApp campaign (approved template)**

```
{
  "name": "Diwali Offer",
  "channel": "whatsapp",
  "body": "",
  "contact_list_ids": [1],
  "metadata": {
    "whatsapp_template": "diwali_offer",
    "whatsapp_language": "en",
    "whatsapp_body_params": ["{{name}}", "DIWALI30"]
  }
}
```

**Create SMS campaign**

```
{
  "name": "Flash Sale SMS",
  "channel": "sms",
  "body": "Hi {{name}}! 50% off today. Shop: https://example.com",
  "contact_list_ids": [1],
  "rate_limit_per_minute": 60
}
```

**Schedule a campaign**

```
{ "scheduled_at": "2024-12-25 10:00:00" }
```

**Pre-send validation response**

```
{
  "valid": true,
  "errors": [],
  "warnings": ["Unresolved template variable: {{promo_code}}"],
  "ai_analysis": {
    "spam_score": 0.08,
    "readability_score": 0.82,
    "sentiment": "positive",
    "estimated_open_rate": "22-28%",
    "improvements": ["Add more urgency in subject", "Include a clear CTA button"]
  }
}
```

---

### 🤖 AI Endpoints

[](#-ai-endpoints)

MethodEndpointDescriptionPOST`/ai/subject-lines`Generate subject line variantsPOST`/ai/adapt-channel`Rewrite content for another channelPOST`/ai/analyse`Spam/quality analysisGET`/ai/send-time/{contact_id}`Optimal send time for a contact**Generate subject lines**

```
{
  "topic": "50% off summer sale, ends Friday",
  "tone": "urgent",
  "count": 5,
  "audience": "e-commerce shoppers"
}
```

Response:

```
{
  "data": [
    "⏰ 48 hours left — 50% off everything",
    "Your summer sale access expires Friday",
    "Last chance: half price ends at midnight",
    "Summer sale closing — grab yours now",
    "Friday deadline: 50% off still available"
  ]
}
```

**Adapt content for SMS**

```
{
  "content": "Big summer saleGet 50% off all products this weekend only. Click the button below to shop now and save big on your favourite items.",
  "from_channel": "email",
  "to_channel": "sms"
}
```

---

### 🔄 Workflows

[](#-workflows)

MethodEndpointDescriptionGET`/workflows`List workflowsPOST`/workflows`Create workflowGET`/workflows/{id}`Get workflow + enrolled countPOST`/workflows/{id}/enrol`Enrol contactsPOST`/workflows/{id}/unenrol`Remove contacts**Create a drip workflow**

```
{
  "name": "Welcome Sequence",
  "trigger": "manual",
  "steps": [
    { "id": "s1", "type": "email",     "campaign_id": 5,  "delay_hours": 0 },
    { "id": "s2", "type": "wait",      "delay_hours": 48 },
    { "id": "s3", "type": "condition", "field": "opened_campaign", "value": 5,
      "yes": "s4", "no": "s5" },
    { "id": "s4", "type": "email",     "campaign_id": 6,  "delay_hours": 0 },
    { "id": "s5", "type": "sms",       "campaign_id": 7,  "delay_hours": 0 },
    { "id": "s6", "type": "tag",       "tag": "engaged" },
    { "id": "s7", "type": "end" }
  ]
}
```

**Supported step types:** `email`, `sms`, `whatsapp`, `push`, `wait`, `condition`, `tag`, `untag`, `list_add`, `list_remove`, `webhook`, `end`

**Condition fields:** `opened_campaign`, `clicked_campaign`, `has_tag`, `custom_field`

---

### 🔐 Privacy / GDPR

[](#-privacy--gdpr)

MethodEndpointDescriptionDELETE`/privacy/contacts/{id}/erase`Right to erasure (Art. 17)GET`/privacy/contacts/{id}/export`Data export (Art. 15)POST`/privacy/contacts/{id}/consent`Record consent with proofDELETE`/privacy/contacts/{id}/consent`Withdraw consentGET`/privacy/contacts/{id}/consent`Check consent status**Record consent**

```
{
  "channel": "email",
  "purpose": "marketing",
  "source_url": "https://example.com/signup"
}
```

---

### 🚫 Suppression List

[](#-suppression-list)

MethodEndpointDescriptionGET`/suppression`List suppressionsPOST`/suppression`Add single entryPOST`/suppression/bulk`Bulk suppress (e.g. bounce list)GET`/suppression/check`Check if recipient is suppressedDELETE`/suppression/{id}`Remove from suppression**Bulk suppress bounced emails**

```
{
  "recipients": ["bounce1@example.com", "bounce2@example.com"],
  "channel": "email",
  "reason": "bounce"
}
```

---

### 📦 Email Templates

[](#-email-templates)

MethodEndpointDescriptionGET`/templates`List templates (`?category=`)GET`/templates/presets`View built-in preset definitionsPOST`/templates`Create custom templatePOST`/templates/presets/{key}/import`Import a preset into your libraryDELETE`/templates/{id}`Delete templatePOST`/campaigns/{id}/apply-template/{tid}`Apply to campaign**Built-in presets:** `welcome`, `newsletter`, `promotion`, `abandoned_cart`, `win_back`, `order_confirmation`

```
# Import the welcome preset
POST /api/reachhub/templates/presets/welcome/import
```

---

### 🔌 Outbound Webhooks

[](#-outbound-webhooks)

MethodEndpointDescriptionGET`/webhooks/subscriptions`List subscriptionsPOST`/webhooks/subscriptions`Create subscriptionPUT`/webhooks/subscriptions/{id}`UpdateDELETE`/webhooks/subscriptions/{id}`DeletePOST`/webhooks/subscriptions/{id}/test`Send test payloadGET`/webhooks/events`List all available events**Create subscription**

```
{
  "name": "My Zapier Hook",
  "url": "https://hooks.zapier.com/hooks/catch/xxx/yyy/",
  "events": ["campaign.completed", "contact.unsubscribed", "bounce.received"],
  "auth_type": "bearer",
  "auth_config": { "bearer_token": "zapier-token-here" }
}
```

**Available events (19):**`campaign.created`, `campaign.updated`, `campaign.sent`, `campaign.completed`, `campaign.failed`, `campaign.paused`, `campaign.cancelled`, `contact.created`, `contact.updated`, `contact.unsubscribed`, `contact.suppressed`, `workflow.enrolled`, `workflow.completed`, `workflow.errored`, `bounce.received`, `complaint.received`, `open.tracked`, `click.tracked`, `delivery.confirmed`

All payloads are HMAC-SHA256 signed via `X-ReachHub-Signature` header.

---

### 🔑 API Key Management

[](#-api-key-management)

MethodEndpointDescriptionGET`/api-keys`List all keysPOST`/api-keys`Create key with permissionsDELETE`/api-keys/{id}`Revoke key**Switch to multi-key mode** in `.env`:

```
REACHHUB_AUTH_MODE=api_keys
```

**Create a read-only analytics key**

```
{
  "name": "Dashboard Read-Only",
  "permissions": ["analytics.read", "campaigns.read", "contacts.read"],
  "expires_in_days": 365
}
```

**Available permission scopes:**`campaigns.read`, `campaigns.write`, `contacts.read`, `contacts.write`, `analytics.read`, `workflows.read`, `workflows.write`, `privacy.read`, `privacy.write`, `webhooks.read`, `webhooks.write`, `*` (super)

---

### 📊 Analytics

[](#-analytics)

MethodEndpointDescriptionGET`/analytics/campaigns/{id}`Campaign statsGET`/analytics/overview`Cross-channel summaryGET`/campaigns/calendar?month=2024-12`Scheduled/sent calendarGET`/contacts/{id}/timeline`Contact activity history**Campaign stats response**

```
{
  "stats": {
    "total_recipients": 1000,
    "sent": 998,
    "delivered": 985,
    "opened": 412,
    "clicked": 89,
    "failed": 2,
    "bounced": 13,
    "open_rate": 41.28,
    "click_rate": 21.60,
    "failure_rate": 0.20
  }
}
```

---

### 📥 Migration / Import

[](#-migration--import)

MethodEndpointDescriptionPOST`/migrate/mailchimp`Import from Mailchimp APIPOST`/migrate/csv`Import CSV filePOST`/migrate/json`Import JSON array**Mailchimp import**

```
{ "api_key": "xxx-us1", "datacenter": "us1" }
```

**CSV import with mapping**

```
{
  "mapping": { "name": "Full Name", "email": "Email Address", "phone": "Mobile" },
  "list_id": 1
}
```

---

### 📬 Inbound Webhooks (provider callbacks)

[](#-inbound-webhooks-provider-callbacks)

Register these URLs in your provider dashboards (no auth required):

ProviderURLEmail (Mailgun/SendGrid/Postmark)`POST /api/reachhub/webhooks/email`WhatsApp (Meta)`POST /api/reachhub/webhooks/whatsapp`WhatsApp verify`GET /api/reachhub/webhooks/whatsapp`SMS (Twilio/Vonage)`POST /api/reachhub/webhooks/sms`---

🗂️ Package Structure
--------------------

[](#️-package-structure)

```
packages/reachhub/
├── composer.json
├── Config/reachhub.php
├── Database/migrations/
│   ├── ..._001_create_reachhub_tables.php          (core)
│   ├── ..._002_create_reachhub_v2_tables.php       (GDPR, workflows)
│   └── ..._003_create_reachhub_v3_tables.php       (suppression, API keys, webhooks, templates)
├── Routes/api.php                                      (40+ endpoints)
└── src/
    ├── AI/
    │   ├── ContentEngine.php                           (Ollama / OpenAI)
    │   └── SendTimeOptimizer.php
    ├── Console/Commands/
    │   ├── DispatchScheduledCampaigns.php
    │   ├── WorkflowTick.php
    │   ├── RetryFailedMessages.php
    │   ├── GdprCleanup.php
    │   └── ArchiveOldCampaigns.php
    ├── Http/
    │   ├── Controllers/ (14 controllers)
    │   ├── Middleware/ReachHubAuth.php              (single-token + multi-key)
    │   └── Requests/
    ├── Jobs/DispatchCampaignChunk.php                  (chunked queue, exp. backoff)
    ├── Migration/MigrationWizard.php                   (Mailchimp, CSV, JSON)
    ├── Models/
    │   ├── Campaign.php                                (auto body_hash, rate limit)
    │   ├── Contact.php / ContactList.php / CampaignLog.php
    │   ├── SuppressionList.php                        (cross-channel suppression)
    │   ├── ApiKey.php                                  (scoped permissions)
    │   ├── WebhookSubscription.php                     (19 events, HMAC-signed)
    │   └── EmailTemplate.php                           (6 built-in presets)
    ├── Privacy/PrivacyService.php                      (AES-256-GCM, GDPR)
    ├── Providers/ReachHubServiceProvider.php
    ├── Services/
    │   ├── CampaignService.php                         (suppression + duplicate check)
    │   ├── ChannelRateLimiter.php
    │   ├── CSV/CSVPreviewService.php
    │   ├── Preview/CampaignPreviewService.php
    │   └── Channels/
    │       ├── EmailChannel.php / WhatsAppChannel.php
    │       ├── SmsChannel.php (GSM-7/UCS-2)
    │       └── PushChannel.php (FCM)
    └── Workflow/WorkflowEngine.php                     (11 step types)

```

---

🔌 Adding a Custom Channel
-------------------------

[](#-adding-a-custom-channel)

Implement `ChannelContract` and register in `CampaignService::$channelMap`:

```
// src/Services/Channels/TelegramChannel.php
class TelegramChannel implements ChannelContract
{
    public function channelName(): string { return 'telegram'; }
    public function validateConfig(): void { /* check bot token */ }
    public function send(Campaign $campaign, Contact $contact): array
    {
        // Telegram Bot API call
        return ['success' => true, 'message_id' => 'msg_123', 'error' => null];
    }
}
```

Then add `'telegram' => TelegramChannel::class` to `$channelMap` in `CampaignService`.

---

⚖️ Competitor Comparison
------------------------

[](#️-competitor-comparison)

Feature**ReachHub v4**MauticMailchimpHubSpotMarketoPrice**Free**Free$20–350/mo$50–3,200/mo$2k–10k/moSelf-hosted✅✅❌❌❌Multi-channel✅ Email/WA/SMS/Push⚠️ Email+plugins⚠️ Email-first✅ paid✅Local LLM AI✅ Free (Ollama)❌❌❌ API only❌Workflow engine✅ Conditional branching✅❌✅ paid✅GDPR suite✅ Encrypt+erase+consent⚠️ Basic⚠️✅✅Suppression list✅ Per-channel❌✅✅✅API key scopes✅❌✅✅✅Outbound webhooks✅ 19 events✅✅✅✅Email templates✅ 6+ presets❌✅✅✅Campaign approval✅❌❌✅✅Migration tools✅ Mailchimp/CSV/JSON❌❌❌❌Contact timeline✅❌✅✅✅Send-time optimisation✅ Per-contact❌✅ paid✅ paid✅---

📜 License
---------

[](#-license)

MIT © Susheel Kumar

###  Health Score

20

—

LowBetter than 13% of packages

Maintenance62

Regular maintenance activity

Popularity0

Limited adoption so far

Community8

Small or concentrated contributor base

Maturity11

Early-stage or recently created project

 Bus Factor1

Top contributor holds 50% 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.

### Community

Maintainers

![](https://www.gravatar.com/avatar/d1526758095ab08d95266bdd365dcf42735bf80c4a6eb1056f1b084c39a10dcb?d=identicon)[saksh-sky](/maintainers/saksh-sky)

---

Top Contributors

[![sakshstore](https://avatars.githubusercontent.com/u/44046755?v=4)](https://github.com/sakshstore "sakshstore (1 commits)")[![susheelhbti](https://avatars.githubusercontent.com/u/9462770?v=4)](https://github.com/susheelhbti "susheelhbti (1 commits)")

### Embed Badge

![Health badge](/badges/susheelhbti-reachhub/health.svg)

```
[![Health](https://phpackages.com/badges/susheelhbti-reachhub/health.svg)](https://phpackages.com/packages/susheelhbti-reachhub)
```

###  Alternatives

[facebook/php-business-sdk

PHP SDK for Facebook Business

90923.5M35](/packages/facebook-php-business-sdk)[exsyst/swagger

A php library to manipulate Swagger specifications

35916.3M7](/packages/exsyst-swagger)[hubspot/api-client

Hubspot API client

24015.5M18](/packages/hubspot-api-client)[botman/driver-telegram

Telegram driver for BotMan

93452.6k6](/packages/botman-driver-telegram)

PHPackages © 2026

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