A production-ready Node.js webhook server for Unthread.io integration. Built with TypeScript, Express.js, and Redis for reliable webhook event processing with HMAC signature verification and intelligent platform detection.
These outstanding organizations partner with us to support our open-source work:
π Platinum Sponsor |
---|
![]() |
Unthread Streamlined support ticketing for modern teams. |
Open source development is resource-intensive. These sponsored ads help keep Log Engine free and actively maintained while connecting you with tools and services that support open-source development.
Requirements: Node.js 20+, Redis, Yarn
# 1. Install dependencies
yarn install
# 2. Configure environment
cp .env.example .env
# Edit .env with your Unthread webhook secret
# 3. Start Redis (choose one)
redis-server # Local installation
brew services start redis # macOS
sudo systemctl start redis-server # Linux
docker run -d -p 6379:6379 redis:alpine # Docker
# 4. Run the server
yarn dev # Development with auto-reload
yarn start # Production mode
Server runs on http://localhost:3000
with endpoints:
GET /health
- Health checkPOST /unthread-webhook
- Webhook endpoint
# 1. Copy environment template
cp .env.example .env
# Edit .env with your webhook secret
# 2. Start with Docker Compose
docker-compose up -d
# 3. Check status
docker-compose ps
# 4. View logs
docker-compose logs -f
# 5. Stop services
docker-compose down
Environment Files:
.env
- Single config file for both local development and Docker.env.example
- Template (Redis URL gets overridden automatically for Docker)
Create a .env
file from the example:
cp .env.example .env
Required variables:
Variable | Description | Default | Required |
---|---|---|---|
UNTHREAD_WEBHOOK_SECRET |
Your Unthread.io signing secret | - | β |
NODE_ENV |
Environment mode | development |
β |
PORT |
Server port | 3000 |
β |
TARGET_PLATFORM |
Platform identifier (e.g., telegram, discord) | telegram |
β |
REDIS_URL |
Redis connection URL | redis://localhost:6379 |
β |
- Go to Unthread Dashboard
- Navigate to Webhooks settings
- Copy your signing secret to
UNTHREAD_WEBHOOK_SECRET
in.env
- Set your webhook URL to:
https://your-domain.com/unthread-webhook
For local testing, use ngrok: ngrok http 3000
- Webhook Reception: Receives POST requests from Unthread.io at
/unthread-webhook
- Security: Validates HMAC-SHA256 signatures using your webhook secret
- Deduplication: Prevents duplicate event processing with Redis TTL cache
- Platform Detection: Identifies if events come from dashboard or target platform
- Queue Publishing: Sends processed events to Redis
unthread-events
queue
url_verification
- Automatic URL verificationconversation_created
- New conversationsconversation_updated
- Status changesconversation_deleted
- Conversation removalmessage_created
- New messages
Events are queued with this structure:
{
"platform": "unthread",
"targetPlatform": "telegram",
"type": "message_created",
"sourcePlatform": "dashboard",
"data": {
"eventId": "evt_123456789",
"conversationId": "conv_abc123",
"content": "Hello from support!",
"eventTimestamp": 1733097600000
},
"timestamp": 1733097600000
}
yarn clean # Clean previous builds
yarn build # Build for production
yarn type-check # TypeScript type checking only
yarn dev # Development with hot-reload
yarn start # Run production build
src/
βββ app.ts # Main application entry
βββ config/ # Configuration files
βββ controllers/ # Request handlers
βββ middleware/ # Auth & validation
βββ services/ # Business logic
βββ types/ # TypeScript types
βββ utils/ # Helper functions
curl http://localhost:3000/health
Healthy Response:
{
"status": "OK",
"redis": "connected",
"timestamp": "2025-06-21T12:00:00.000Z"
}
Error Response:
{
"status": "ERROR",
"redis": "disconnected",
"timestamp": "2025-06-21T12:00:00.000Z"
}
Redis Connection Issues:
- Verify Redis is running:
redis-cli ping
- Check
REDIS_URL
in your.env
file - Review server logs for connection errors
Platform Detection Issues:
- Check logs for detection summary details
- Verify event structure matches Unthread format
- Events may be classified as "unknown" for edge cases
Contributions are welcome, create a pull request to this repo and I will review your code. Please consider to submit your pull request to the dev
branch. Thank you!
When contributing, please ensure your code follows the existing TypeScript patterns and includes appropriate error handling.
Like this project? Leave a star! βββββ
There are several ways you can support this project:
- Become a sponsor and get some perks! π
- Buy me a coffee if you just love what I do! β
Found this project helpful? Consider nominating me (@warengonzaga) for the GitHub Star program! This recognition supports ongoing development of this project and my other open-source projects. GitHub Stars are recognized for their significant contributions to the developer community - your nomination makes a difference and encourages continued innovation!
Licensed under GNU General Public License v3.0 - ensuring modifications remain open source.
This project is created by Waren Gonzaga under WG Technology Labs, with the help of awesome contributors.
π» Made with β€οΈ by Waren Gonzaga under WG Technology Labs