An AI-powered webhook service that automatically classifies and labels customer support tickets in Plain according to custom company-defined priority guidelines (P0βP3).
This service receives webhooks from Plain when new tickets (threads) are created, analyzes the content using a rules-based classifier with optional AI enhancement, and automatically applies appropriate priority labels to help support teams prioritize their work.
- π― Automatic Priority Classification: P0 (Critical) to P3 (Low) based on configurable rules
- π Plain Integration: Secure webhook handling with signature verification
- π§ Rules Engine: Keyword matching, customer tier evaluation, and time-based prioritization
- π€ AI Enhancement: Optional OpenAI integration for improved classification accuracy
- π Audit Logging: Complete audit trail of all classification decisions
- π Security: Rate limiting, input validation, and secure API communication
- π Monitoring: Health checks, metrics endpoint, and structured logging
Plain Webhook β Express Server β Priority Classifier β Plain API
β
Winston Logging & Audit Trail
- Node.js 18+
- Plain workspace with API access
- Environment variables configured (see Setup section)
git clone <repository-url>
cd plain-priority-labeling
npm install
Copy the example environment file and fill in your values:
cp env.example .env
Required environment variables:
# Plain API Configuration
PLAIN_API_TOKEN=your_plain_api_token_here
PLAIN_SIGNATURE_SECRET=your_plain_webhook_signature_secret_here
# Priority Label Configuration
LABEL_P0_ID=your_p0_label_type_id_here
LABEL_P1_ID=your_p1_label_type_id_here
LABEL_P2_ID=your_p2_label_type_id_here
LABEL_P3_ID=your_p3_label_type_id_here
- Go to Plain Settings β Manage Labels
- Create four label types:
- P0 - Critical (π₯ icon recommended)
- P1 - High (
β οΈ icon recommended) - P2 - Medium (π icon recommended)
- P3 - Low (π icon recommended)
- Copy each label type ID to your
.env
file
- Go to Plain Settings β Machine Users
- Click "Add Machine User"
- Create an API key with these permissions:
thread:read
thread:edit
label:create
label:read
customer:read
threadEvent:create
- Go to Plain Settings β Webhooks
- Click "Add webhook target"
- Configure:
- Name: "Priority Labeling Service"
- URL:
https://your-domain.com/webhook/plain
- Events: Select "Thread created" and optionally "Email received"
- Version: Use the latest version
npm run dev
The server will start on http://localhost:3000
with auto-reload on file changes.
npm start
# Build the image
docker build -t plain-priority-labeling .
# Run the container
docker run -d \\
--name priority-labeling \\
-p 3000:3000 \\
--env-file .env \\
plain-priority-labeling
docker-compose up -d
GET /health
- Health check endpointPOST /webhook/plain
- Plain webhook endpointGET /metrics
- Basic metrics for monitoring
The service uses a multi-factor approach to classify ticket priority:
- Keywords: down, outage, critical, emergency, security breach, data loss
- Customer Tiers: Enterprise, Premium
- Response Time: 15 minutes
- Auto-escalation: Yes
- Keywords: bug, error, issue, not working, integration, billing
- Customer Tiers: Enterprise, Premium, Standard
- Response Time: 8 hours
- Auto-escalation: No
- Keywords: question, help, how to, documentation, training
- Customer Tiers: Standard, Basic
- Response Time: 24 hours
- Auto-escalation: No
- Keywords: feedback, suggestion, enhancement, minor improvement
- Customer Tiers: Basic, Trial
- Response Time: 72 hours
- Auto-escalation: No
Priority rules can be customized in src/config/config.js
. You can modify:
- Keywords for each priority level
- Customer tier mappings
- Time thresholds
- Confidence requirements
- Escalation rules
The service provides comprehensive logging and monitoring:
- Location: Console output (development) or
logs/
directory (production) - Format: Structured JSON with timestamps
- Levels: error, warn, info, debug
- Endpoint:
GET /health
- Response: Service status, uptime, version
- Endpoint:
GET /metrics
- Data: Memory usage, uptime, processing stats
-
Webhook signature verification fails
- Check
PLAIN_SIGNATURE_SECRET
is correct - Ensure raw body is passed to verification function
- Check
-
Labels not being applied
- Verify label type IDs in environment variables
- Check API key has
label:create
permission - Review classification confidence threshold
-
High memory usage
- Check log level configuration
- Monitor for memory leaks in long-running processes
Enable debug logging:
LOG_LEVEL=debug npm run dev
Use ngrok to expose your local server:
ngrok http 3000
# Use the HTTPS URL in Plain webhook settings
- β Webhook signature verification
- β Rate limiting
- β Input validation
- β Secure headers (Helmet.js)
- β Environment variable validation
- β API key permissions scoping
- Webhook processing: < 2 seconds target
- Rate limiting: 100 requests per 15 minutes per IP
- Timeout: 15 seconds for external API calls
- Memory: ~50MB baseline usage
- Node.js 18+ runtime
- HTTPS endpoint (required by Plain)
- Persistent logging storage (recommended)
- Process manager (PM2, systemd, etc.)
- Environment variables configured
- Plain labels created and IDs set
- API key created with correct permissions
- Webhook target configured in Plain
- HTTPS certificate valid
- Health checks passing
- Monitoring configured
- Follow the existing code style
- Add tests for new features
- Update documentation
- Ensure all tests pass
MIT License - see LICENSE file for details
For issues and questions:
- Check the troubleshooting section
- Review logs for error details
- Contact your development team
- Open an issue in the repository
Next Steps: After deployment, monitor the classification accuracy and adjust rules as needed based on agent feedback and manual priority overrides.