525 lines
12 KiB
Markdown
525 lines
12 KiB
Markdown
|
|
# Autotask Webhook Setup Guide
|
||
|
|
|
||
|
|
## Overview
|
||
|
|
|
||
|
|
This guide explains how to configure Autotask webhooks for real-time data synchronization with Pulse. Webhooks provide near-instant updates when entities change in Autotask, reducing API calls and keeping your data fresh.
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## Table of Contents
|
||
|
|
|
||
|
|
- [Benefits of Webhooks](#benefits-of-webhooks)
|
||
|
|
- [Supported Entities](#supported-entities)
|
||
|
|
- [Prerequisites](#prerequisites)
|
||
|
|
- [Setup Steps](#setup-steps)
|
||
|
|
- [Webhook Endpoint](#webhook-endpoint)
|
||
|
|
- [Testing Webhooks](#testing-webhooks)
|
||
|
|
- [Monitoring](#monitoring)
|
||
|
|
- [Troubleshooting](#troubleshooting)
|
||
|
|
- [Recommended Sync Strategy](#recommended-sync-strategy)
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## Benefits of Webhooks
|
||
|
|
|
||
|
|
### **Real-Time Updates**
|
||
|
|
- Instant notification when entities are created or updated in Autotask
|
||
|
|
- No polling delay - changes appear within seconds
|
||
|
|
|
||
|
|
### **Reduced API Usage**
|
||
|
|
- Fewer API calls compared to frequent polling
|
||
|
|
- Lower risk of hitting API rate limits
|
||
|
|
- More efficient use of resources
|
||
|
|
|
||
|
|
### **Better Data Freshness**
|
||
|
|
- Combined with daily incremental syncs for redundancy
|
||
|
|
- Ensures no events are missed
|
||
|
|
- Automatic recovery from webhook failures
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## Supported Entities
|
||
|
|
|
||
|
|
The following entities support webhook notifications:
|
||
|
|
|
||
|
|
| Entity | Events | Notes |
|
||
|
|
|--------|--------|-------|
|
||
|
|
| **Companies** | Create, Update | Real-time company changes |
|
||
|
|
| **Tickets** | Create, Update | New tickets and status updates |
|
||
|
|
| **Tasks** | Create, Update | Task creation and modifications |
|
||
|
|
| **Projects** | Create, Update | Project changes |
|
||
|
|
| **Time Entries** | Create, Update | New time entries |
|
||
|
|
| **Contacts** | Create, Update | Contact information changes |
|
||
|
|
| **Contracts** | Create, Update | Contract updates |
|
||
|
|
| **Configuration Items** | Create, Update | Asset changes |
|
||
|
|
|
||
|
|
**Note:** Delete events are supported but less common in Autotask workflows.
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## Prerequisites
|
||
|
|
|
||
|
|
Before setting up webhooks, ensure you have:
|
||
|
|
|
||
|
|
1. **Autotask API Access**
|
||
|
|
- API user with appropriate permissions
|
||
|
|
- API integration enabled in Autotask
|
||
|
|
|
||
|
|
2. **Public Webhook Endpoint**
|
||
|
|
- Your Pulse instance must be accessible from the internet
|
||
|
|
- HTTPS endpoint (required by Autotask)
|
||
|
|
- Example: `https://your-pulse-instance.com/api/webhooks/autotask`
|
||
|
|
|
||
|
|
3. **Database Migration**
|
||
|
|
- Run migration `004_webhook_support.sql` to create webhook tables
|
||
|
|
```bash
|
||
|
|
docker exec pulse-postgres psql -U pulse_user -d pulse_autotask -f /migrations/004_webhook_support.sql
|
||
|
|
```
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## Setup Steps
|
||
|
|
|
||
|
|
### **Step 1: Configure Webhook Endpoint in Autotask**
|
||
|
|
|
||
|
|
1. Log in to Autotask as an administrator
|
||
|
|
2. Navigate to **Admin** → **Features & Settings** → **API & Integrations**
|
||
|
|
3. Click on **Webhooks**
|
||
|
|
4. Click **New Webhook**
|
||
|
|
|
||
|
|
### **Step 2: Create Webhook for Each Entity**
|
||
|
|
|
||
|
|
For each entity you want to track (e.g., Tickets):
|
||
|
|
|
||
|
|
1. **Webhook Name:** `Pulse - Tickets`
|
||
|
|
2. **Endpoint URL:** `https://your-pulse-instance.com/api/webhooks/autotask`
|
||
|
|
3. **Entity Type:** Select the entity (e.g., `Tickets`)
|
||
|
|
4. **Events:** Select events to track:
|
||
|
|
- ✅ Create
|
||
|
|
- ✅ Update
|
||
|
|
- ⬜ Delete (optional)
|
||
|
|
5. **Include Entity Data:** ✅ **Enabled** (recommended)
|
||
|
|
- This includes full entity data in the webhook payload
|
||
|
|
- Reduces need for additional API calls
|
||
|
|
6. **Active:** ✅ **Enabled**
|
||
|
|
7. Click **Save**
|
||
|
|
|
||
|
|
### **Step 3: Record Webhook IDs**
|
||
|
|
|
||
|
|
After creating each webhook, Autotask will provide a Webhook ID. Record these for reference:
|
||
|
|
|
||
|
|
```
|
||
|
|
Companies: webhook_12345
|
||
|
|
Tickets: webhook_12346
|
||
|
|
Tasks: webhook_12347
|
||
|
|
Projects: webhook_12348
|
||
|
|
TimeEntries: webhook_12349
|
||
|
|
Contacts: webhook_12350
|
||
|
|
```
|
||
|
|
|
||
|
|
### **Step 4: Verify Webhook Configuration**
|
||
|
|
|
||
|
|
Check that webhooks are configured in the database:
|
||
|
|
|
||
|
|
```sql
|
||
|
|
SELECT entity_type, is_active, autotask_webhook_id
|
||
|
|
FROM webhook_configs
|
||
|
|
ORDER BY entity_type;
|
||
|
|
```
|
||
|
|
|
||
|
|
Update webhook IDs if needed:
|
||
|
|
|
||
|
|
```sql
|
||
|
|
UPDATE webhook_configs
|
||
|
|
SET autotask_webhook_id = 'webhook_12345'
|
||
|
|
WHERE entity_type = 'Companies';
|
||
|
|
```
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## Webhook Endpoint
|
||
|
|
|
||
|
|
### **Endpoint Details**
|
||
|
|
|
||
|
|
- **URL:** `https://your-domain.com/api/webhooks/autotask`
|
||
|
|
- **Method:** `POST`
|
||
|
|
- **Content-Type:** `application/json`
|
||
|
|
- **Authentication:** None (Autotask doesn't support webhook authentication)
|
||
|
|
- Secure via IP whitelisting or network-level security
|
||
|
|
|
||
|
|
### **Payload Structure**
|
||
|
|
|
||
|
|
Autotask sends webhooks with this structure:
|
||
|
|
|
||
|
|
```json
|
||
|
|
{
|
||
|
|
"eventId": "evt_abc123",
|
||
|
|
"eventType": "create",
|
||
|
|
"entityType": "Tickets",
|
||
|
|
"entityId": 12345,
|
||
|
|
"eventTimestamp": "2026-01-24T10:00:00Z",
|
||
|
|
"entity": {
|
||
|
|
"id": 12345,
|
||
|
|
"title": "New Ticket",
|
||
|
|
"status": 1,
|
||
|
|
"companyID": 67890,
|
||
|
|
...
|
||
|
|
}
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
### **Response**
|
||
|
|
|
||
|
|
The endpoint returns:
|
||
|
|
|
||
|
|
```json
|
||
|
|
{
|
||
|
|
"success": true,
|
||
|
|
"eventId": "evt_abc123",
|
||
|
|
"action": "created",
|
||
|
|
"processingTime": 45
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## Testing Webhooks
|
||
|
|
|
||
|
|
### **1. Health Check**
|
||
|
|
|
||
|
|
Verify the webhook endpoint is accessible:
|
||
|
|
|
||
|
|
```bash
|
||
|
|
curl https://your-pulse-instance.com/api/webhooks/autotask
|
||
|
|
```
|
||
|
|
|
||
|
|
Expected response:
|
||
|
|
```json
|
||
|
|
{
|
||
|
|
"status": "active",
|
||
|
|
"endpoint": "/api/webhooks/autotask",
|
||
|
|
"message": "Autotask webhook receiver is ready"
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
### **2. Test Webhook from Autotask**
|
||
|
|
|
||
|
|
1. In Autotask, go to the webhook configuration
|
||
|
|
2. Click **Test Webhook**
|
||
|
|
3. Autotask will send a test event
|
||
|
|
4. Check webhook logs in Pulse
|
||
|
|
|
||
|
|
### **3. Create Test Entity**
|
||
|
|
|
||
|
|
Create a test ticket or company in Autotask and verify:
|
||
|
|
|
||
|
|
1. Webhook is received (check logs)
|
||
|
|
2. Entity appears in database
|
||
|
|
3. Processing time is reasonable (<1 second)
|
||
|
|
|
||
|
|
### **4. View Webhook Logs**
|
||
|
|
|
||
|
|
```bash
|
||
|
|
# Via API
|
||
|
|
curl https://your-pulse-instance.com/api/webhooks/logs?limit=10
|
||
|
|
|
||
|
|
# Via Database
|
||
|
|
docker exec pulse-postgres psql -U pulse_user -d pulse_autotask -c \
|
||
|
|
"SELECT event_id, entity_type, entity_id, status, processing_time_ms
|
||
|
|
FROM webhook_logs
|
||
|
|
ORDER BY received_at DESC
|
||
|
|
LIMIT 10;"
|
||
|
|
```
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## Monitoring
|
||
|
|
|
||
|
|
### **Webhook Statistics**
|
||
|
|
|
||
|
|
View webhook statistics via API:
|
||
|
|
|
||
|
|
```bash
|
||
|
|
curl https://your-pulse-instance.com/api/webhooks/stats?hours=24
|
||
|
|
```
|
||
|
|
|
||
|
|
Response:
|
||
|
|
```json
|
||
|
|
{
|
||
|
|
"success": true,
|
||
|
|
"stats": {
|
||
|
|
"total": 150,
|
||
|
|
"processed": 148,
|
||
|
|
"failed": 2,
|
||
|
|
"pending": 0,
|
||
|
|
"byEntityType": {
|
||
|
|
"Tickets": 75,
|
||
|
|
"Companies": 25,
|
||
|
|
"Tasks": 30,
|
||
|
|
"TimeEntries": 20
|
||
|
|
}
|
||
|
|
},
|
||
|
|
"period": "24 hours"
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
### **Failed Webhooks**
|
||
|
|
|
||
|
|
Check for failed webhook processing:
|
||
|
|
|
||
|
|
```sql
|
||
|
|
SELECT event_id, entity_type, entity_id, error_message, received_at
|
||
|
|
FROM webhook_logs
|
||
|
|
WHERE status = 'failed'
|
||
|
|
ORDER BY received_at DESC
|
||
|
|
LIMIT 20;
|
||
|
|
```
|
||
|
|
|
||
|
|
### **Processing Performance**
|
||
|
|
|
||
|
|
Monitor webhook processing times:
|
||
|
|
|
||
|
|
```sql
|
||
|
|
SELECT
|
||
|
|
entity_type,
|
||
|
|
COUNT(*) as total,
|
||
|
|
AVG(processing_time_ms) as avg_ms,
|
||
|
|
MAX(processing_time_ms) as max_ms
|
||
|
|
FROM webhook_logs
|
||
|
|
WHERE status = 'processed'
|
||
|
|
AND received_at >= NOW() - INTERVAL '24 hours'
|
||
|
|
GROUP BY entity_type
|
||
|
|
ORDER BY avg_ms DESC;
|
||
|
|
```
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## Troubleshooting
|
||
|
|
|
||
|
|
### **Webhooks Not Received**
|
||
|
|
|
||
|
|
**Check 1: Endpoint Accessibility**
|
||
|
|
```bash
|
||
|
|
# From external network
|
||
|
|
curl https://your-pulse-instance.com/api/webhooks/autotask
|
||
|
|
```
|
||
|
|
|
||
|
|
**Check 2: Firewall/Network**
|
||
|
|
- Ensure port 443 (HTTPS) is open
|
||
|
|
- Check firewall rules allow Autotask IPs
|
||
|
|
- Verify SSL certificate is valid
|
||
|
|
|
||
|
|
**Check 3: Autotask Configuration**
|
||
|
|
- Verify webhook is Active in Autotask
|
||
|
|
- Check endpoint URL is correct
|
||
|
|
- Ensure entity type matches
|
||
|
|
|
||
|
|
### **Webhooks Failing to Process**
|
||
|
|
|
||
|
|
**Check Logs:**
|
||
|
|
```sql
|
||
|
|
SELECT event_id, entity_type, error_message, payload
|
||
|
|
FROM webhook_logs
|
||
|
|
WHERE status = 'failed'
|
||
|
|
ORDER BY received_at DESC
|
||
|
|
LIMIT 5;
|
||
|
|
```
|
||
|
|
|
||
|
|
**Common Issues:**
|
||
|
|
|
||
|
|
1. **Missing Entity Data**
|
||
|
|
- Enable "Include Entity Data" in Autotask webhook config
|
||
|
|
- Without this, webhook only includes entity ID
|
||
|
|
|
||
|
|
2. **Foreign Key Violations**
|
||
|
|
- Run full sync for dependent entities first
|
||
|
|
- Example: Sync Companies before Tickets
|
||
|
|
|
||
|
|
3. **Invalid Data**
|
||
|
|
- Check entity mapper for missing field mappings
|
||
|
|
- Review error_message in webhook_logs
|
||
|
|
|
||
|
|
### **High Failure Rate**
|
||
|
|
|
||
|
|
If >5% of webhooks fail:
|
||
|
|
|
||
|
|
1. **Run Full Sync** for affected entities
|
||
|
|
2. **Check Dependencies** - ensure parent entities are synced
|
||
|
|
3. **Review Error Patterns** - look for common error messages
|
||
|
|
4. **Contact Support** - if issues persist
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## Recommended Sync Strategy
|
||
|
|
|
||
|
|
### **Optimal Configuration**
|
||
|
|
|
||
|
|
Combine webhooks with scheduled syncs for best results:
|
||
|
|
|
||
|
|
#### **1. Webhooks (Real-Time)**
|
||
|
|
- **Enabled for:** Companies, Tickets, Tasks, Projects, Time Entries, Contacts
|
||
|
|
- **Events:** Create, Update
|
||
|
|
- **Purpose:** Instant updates for active entities
|
||
|
|
|
||
|
|
#### **2. Daily Incremental Sync (Scheduled)**
|
||
|
|
- **Time:** 2:00 AM daily
|
||
|
|
- **Entities:** All entities
|
||
|
|
- **Purpose:**
|
||
|
|
- Catch any missed webhooks
|
||
|
|
- Sync entities without webhooks (Contracts, Config Items, Picklists)
|
||
|
|
- Ensure data consistency
|
||
|
|
|
||
|
|
#### **3. Weekly Full Sync (Scheduled)**
|
||
|
|
- **Time:** Sunday 3:00 AM
|
||
|
|
- **Entities:** All entities
|
||
|
|
- **Date Range:** Last 2 years
|
||
|
|
- **Purpose:**
|
||
|
|
- Complete data refresh
|
||
|
|
- Verify data integrity
|
||
|
|
- Sync historical changes
|
||
|
|
|
||
|
|
### **Cron Schedule Example**
|
||
|
|
|
||
|
|
```bash
|
||
|
|
# Daily incremental sync at 2 AM
|
||
|
|
0 2 * * * curl -X POST https://your-pulse-instance.com/api/sync/incremental
|
||
|
|
|
||
|
|
# Weekly full sync on Sunday at 3 AM
|
||
|
|
0 3 * * 0 curl -X POST https://your-pulse-instance.com/api/sync/full
|
||
|
|
```
|
||
|
|
|
||
|
|
### **Expected Data Freshness**
|
||
|
|
|
||
|
|
| Entity | Freshness | Method |
|
||
|
|
|--------|-----------|--------|
|
||
|
|
| Tickets | <1 minute | Webhook |
|
||
|
|
| Tasks | <1 minute | Webhook |
|
||
|
|
| Companies | <1 minute | Webhook |
|
||
|
|
| Projects | <1 minute | Webhook |
|
||
|
|
| Time Entries | <1 minute | Webhook |
|
||
|
|
| Contacts | <1 minute | Webhook |
|
||
|
|
| Contracts | 24 hours | Daily sync |
|
||
|
|
| Config Items | 24 hours | Daily sync |
|
||
|
|
| Picklists | 7 days | Weekly sync |
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## Security Considerations
|
||
|
|
|
||
|
|
### **1. Network Security**
|
||
|
|
|
||
|
|
**Option A: IP Whitelisting**
|
||
|
|
- Restrict webhook endpoint to Autotask IP ranges
|
||
|
|
- Configure in firewall or reverse proxy
|
||
|
|
|
||
|
|
**Option B: VPN/Private Network**
|
||
|
|
- Use VPN tunnel for webhook traffic
|
||
|
|
- More secure but complex setup
|
||
|
|
|
||
|
|
### **2. Payload Validation**
|
||
|
|
|
||
|
|
The webhook service validates:
|
||
|
|
- Required fields (eventId, eventType, entityType, entityId)
|
||
|
|
- Event ID uniqueness (prevents duplicate processing)
|
||
|
|
- Entity type is supported
|
||
|
|
|
||
|
|
### **3. Rate Limiting**
|
||
|
|
|
||
|
|
Consider adding rate limiting to prevent abuse:
|
||
|
|
```nginx
|
||
|
|
# Nginx example
|
||
|
|
limit_req_zone $binary_remote_addr zone=webhook:10m rate=100r/m;
|
||
|
|
|
||
|
|
location /api/webhooks/autotask {
|
||
|
|
limit_req zone=webhook burst=20;
|
||
|
|
proxy_pass http://pulse-app:3100;
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## Database Schema
|
||
|
|
|
||
|
|
### **webhook_logs Table**
|
||
|
|
|
||
|
|
Tracks all incoming webhook events:
|
||
|
|
|
||
|
|
```sql
|
||
|
|
CREATE TABLE webhook_logs (
|
||
|
|
id SERIAL PRIMARY KEY,
|
||
|
|
event_id VARCHAR(255) NOT NULL UNIQUE,
|
||
|
|
entity_type VARCHAR(100) NOT NULL,
|
||
|
|
entity_id INTEGER NOT NULL,
|
||
|
|
event_type VARCHAR(50) NOT NULL,
|
||
|
|
status VARCHAR(50) NOT NULL DEFAULT 'pending',
|
||
|
|
error_message TEXT,
|
||
|
|
received_at TIMESTAMP NOT NULL DEFAULT NOW(),
|
||
|
|
processed_at TIMESTAMP,
|
||
|
|
processing_time_ms INTEGER,
|
||
|
|
payload JSONB NOT NULL
|
||
|
|
);
|
||
|
|
```
|
||
|
|
|
||
|
|
### **webhook_configs Table**
|
||
|
|
|
||
|
|
Manages webhook configurations:
|
||
|
|
|
||
|
|
```sql
|
||
|
|
CREATE TABLE webhook_configs (
|
||
|
|
id SERIAL PRIMARY KEY,
|
||
|
|
entity_type VARCHAR(100) NOT NULL UNIQUE,
|
||
|
|
event_types JSONB NOT NULL,
|
||
|
|
is_active BOOLEAN NOT NULL DEFAULT true,
|
||
|
|
autotask_webhook_id VARCHAR(255)
|
||
|
|
);
|
||
|
|
```
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## API Reference
|
||
|
|
|
||
|
|
### **Receive Webhook**
|
||
|
|
|
||
|
|
```
|
||
|
|
POST /api/webhooks/autotask
|
||
|
|
Content-Type: application/json
|
||
|
|
|
||
|
|
{
|
||
|
|
"eventId": "evt_abc123",
|
||
|
|
"eventType": "create",
|
||
|
|
"entityType": "Tickets",
|
||
|
|
"entityId": 12345,
|
||
|
|
"entity": { ... }
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
### **Get Webhook Logs**
|
||
|
|
|
||
|
|
```
|
||
|
|
GET /api/webhooks/logs?limit=100&entityType=Tickets
|
||
|
|
```
|
||
|
|
|
||
|
|
### **Get Webhook Statistics**
|
||
|
|
|
||
|
|
```
|
||
|
|
GET /api/webhooks/stats?hours=24
|
||
|
|
```
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## Support
|
||
|
|
|
||
|
|
For issues or questions:
|
||
|
|
1. Check webhook logs for error messages
|
||
|
|
2. Verify Autotask webhook configuration
|
||
|
|
3. Review this documentation
|
||
|
|
4. Contact system administrator
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## Related Documentation
|
||
|
|
|
||
|
|
- [Sync Behavior Documentation](./SYNC_BEHAVIOR.md)
|
||
|
|
- [Sync Interface Guide](./SYNC_INTERFACE_GUIDE.md)
|
||
|
|
- [Autotask Webhook Documentation](https://autotask.net/help/DeveloperHelp/Content/APIs/Webhooks/WEBHOOKS.htm)
|