feat: add webhook support for real-time Autotask updates

Implements comprehensive webhook infrastructure to receive and process
real-time entity updates from Autotask, reducing API calls and improving
data freshness.

Features:
- Webhook receiver endpoint: POST /api/webhooks/autotask
- Automatic entity mapping and upsert to PostgreSQL
- Event logging and tracking in webhook_logs table
- Duplicate event prevention via unique event_id
- Failed event tracking with error messages
- Statistics and monitoring APIs
- Support for 8 entity types: Companies, Tickets, Tasks, Projects,
  Time Entries, Contacts, Contracts, Configuration Items

Architecture:
- WebhookService: Core processing logic
- Database tables: webhook_logs, webhook_configs
- API endpoints: /autotask (receiver), /logs, /stats
- Automatic data mapping using existing entity-mapper

Benefits:
- Near real-time updates (<1 minute vs 24 hours)
- Reduced API usage (webhooks vs polling)
- Complements daily incremental sync for redundancy
- Automatic recovery from webhook failures

Files Added:
- lib/types/webhook.ts - TypeScript types and interfaces
- lib/services/webhook-service.ts - Webhook processing service
- app/api/webhooks/autotask/route.ts - Webhook receiver
- app/api/webhooks/logs/route.ts - Logs API
- app/api/webhooks/stats/route.ts - Statistics API
- migrations/004_webhook_support.sql - Database schema
- docs/WEBHOOK_SETUP.md - Complete setup guide (47 sections)
- docs/WEBHOOKS_README.md - Quick start guide

Next Steps:
1. Run database migration
2. Configure webhooks in Autotask
3. Test endpoint and monitor logs

See docs/WEBHOOK_SETUP.md for detailed setup instructions.
This commit is contained in:
root 2026-01-24 10:07:20 -05:00
parent 31c2d94a1b
commit 1f83456199
8 changed files with 1317 additions and 0 deletions

110
lib/types/webhook.ts Normal file
View file

@ -0,0 +1,110 @@
/**
* Autotask Webhook Types
* Based on: https://autotask.net/help/DeveloperHelp/Content/APIs/Webhooks/WEBHOOKS.htm
*/
/**
* Webhook event types from Autotask
*/
export enum WebhookEventType {
CREATE = 'create',
UPDATE = 'update',
DELETE = 'delete',
}
/**
* Supported entity types for webhooks
*/
export enum WebhookEntityType {
COMPANIES = 'Companies',
TICKETS = 'Tickets',
TASKS = 'Tasks',
PROJECTS = 'Projects',
TIME_ENTRIES = 'TimeEntries',
CONTACTS = 'Contacts',
CONTRACTS = 'Contracts',
CONFIGURATION_ITEMS = 'ConfigurationItems',
}
/**
* Autotask webhook payload structure
*/
export interface AutotaskWebhookPayload {
/**
* Unique identifier for the webhook event
*/
eventId: string;
/**
* Type of event (create, update, delete)
*/
eventType: WebhookEventType;
/**
* Entity type that triggered the webhook
*/
entityType: WebhookEntityType;
/**
* ID of the entity that changed
*/
entityId: number;
/**
* Timestamp when the event occurred
*/
eventTimestamp: string;
/**
* Optional: Full entity data (if configured in webhook)
*/
entity?: Record<string, any>;
/**
* Optional: Previous values for update events
*/
previousValues?: Record<string, any>;
}
/**
* Webhook processing result
*/
export interface WebhookProcessingResult {
success: boolean;
eventId: string;
entityType: WebhookEntityType;
entityId: number;
action: 'created' | 'updated' | 'deleted' | 'skipped';
error?: string;
processingTime: number;
}
/**
* Webhook log entry for tracking
*/
export interface WebhookLog {
id?: number;
event_id: string;
entity_type: string;
entity_id: number;
event_type: WebhookEventType;
status: 'pending' | 'processed' | 'failed';
error_message?: string;
received_at: Date;
processed_at?: Date;
processing_time_ms?: number;
payload: Record<string, any>;
}
/**
* Webhook configuration
*/
export interface WebhookConfig {
id?: number;
entity_type: WebhookEntityType;
event_types: WebhookEventType[];
is_active: boolean;
autotask_webhook_id?: string;
created_at?: Date;
updated_at?: Date;
}