Agent skill
Autotask Webhooks Skill
Receive and verify Autotask PSA webhooks (Datto, now Kaseya). Use when setting up Autotask webhook handlers, debugging X-Hook-Signature verification, or handling Company, Contact, Ticket and TicketNote Create, Update, Delete and Deactivated callouts.
Install this skill
npx skills add hookdeck/webhook-skills --skill autotask-webhooks
When to Use This Skill
- How do I receive Autotask webhooks?
- How do I verify the Autotask
X-Hook-Signatureheader? - Why is my Autotask webhook signature verification failing?
- How do I handle Ticket, Company or Contact Create/Update/Delete callouts?
- How do I create an Autotask webhook with a
SecretKeythrough the REST API?
Verification (core)
Autotask signs the raw request body with HMAC-SHA1, keyed with the SecretKey set when the webhook was created (up to 64 characters). The digest is base64 (keep the = padding) and is sent as X-Hook-Signature: sha1=<base64>, for example sha1=UaDXFl2DRDu9dnINVkFle7y5uAE=. There is no timestamp and Autotask ships no verification SDK, so verify manually.
const crypto = require('crypto');
function verifyAutotaskWebhook(rawBody, header, secret) {
if (typeof header !== 'string' || !header.startsWith('sha1=')) return false;
const received = header.slice('sha1='.length);
const expected = crypto.createHmac('sha1', secret).update(rawBody).digest('base64');
// Equal-length UTF-8 buffers, no lenient base64 decode of the header
const a = Buffer.from(received, 'utf8');
const b = Buffer.from(expected, 'utf8');
return a.length === b.length && crypto.timingSafeEqual(a, b);
}
In Python, compare bytes so a non-ASCII header returns 401 instead of raising a 500: hmac.compare_.
Always verify the raw body. In Express use express.raw({ type: '*/*' }) so any content type is verified; don't JSON.parse first.
For complete handlers with tests, see examples/express/, examples/nextjs/, examples/fastapi/.
Payload and Events
Autotask has no event-name string. Each callout is a JSON POST with Action, Guid, EntityType, Id, Fields, EventTime, SequenceNumber and PersonID. Dispatch on EntityType and Action.
Action | Triggered When | Fields |
|---|---|---|
Create | A record is created | All subscribed, non-null fields and UDFs |
Update | A subscribed field changes | Fields and UDFs that changed |
Delete | A record is deleted | Base payload only |
Deactivated | The webhook is deactivated | Base payload only; Guid identifies the webhook |
Entities that support webhooks: Companies, Contacts, Assets (Configuration Items), Tickets and Ticket Notes. The examples handle Company, Contact, Ticket and TicketNote.
For the full reference, see Creating a webhook.
Environment Variables
AUTOTASK_WEBHOOK_SECRET=your_webhook_secret_key_here # the SecretKey set when creating the webhook
Local Development
# Start tunnel (no account needed)
npx hookdeck-cli listen 3000 autotask --path /webhooks/autotask
Reference Materials
- references/overview.md - Autotask webhook concepts, entities, payload fields
- references/setup.md - Creating a webhook through the REST API
- references/verification.md - Signature verification details and gotchas