Agent skill

TIMIFY Webhooks Skill

Receive and authenticate TIMIFY webhooks. Use when setting up a TIMIFY webhook subscription endpoint, checking the custom "Include header name" header, debugging 401s, or handling appointment scheduling events like Event Created, Customers Updated and Resource Deleted.

Install this skill

npx skills add hookdeck/webhook-skills --skill timify-webhooks


TIMIFY (appointment scheduling) sends an HTTP POST with a JSON body to your Server URL when something happens in a webhook subscription's scope: a booking is created, a customer is deleted, a resource is updated. Webhooks are not signed. The only built-in protection is the optional custom header: enable Include header name when you create the subscription and TIMIFY adds that header, with the secret value you entered, to every request. Your endpoint authenticates the request by comparing the header with the value you stored.

Sync-type webhooks, such as Before Confirmations, expect a synchronous answer and aren't supported.

When to Use This Skill

  • How do I receive TIMIFY webhooks?
  • How do I authenticate TIMIFY webhook requests? (No signature: use the custom header)
  • How do I use "Include header name" on a TIMIFY webhook subscription?
  • How do I handle Event created, updated or deleted webhooks?
  • Why does my TIMIFY webhook endpoint return 401?

Verification (core)

const crypto = require('crypto');

// Hash both sides: equal-length buffers, so timingSafeEqual never throws.
function safeEqual(a, b) {
  const ha = crypto.createHash('sha256').update(String(a)).digest();
  const hb = crypto.createHash('sha256').update(String(b)).digest();
  return crypto.timingSafeEqual(ha, hb);
}

function verifyTimifyRequest(headers, secret = process.env.TIMIFY_WEBHOOK_SECRET,
                             name = process.env.TIMIFY_WEBHOOK_HEADER || 'Authorization') {
  if (!secret) return false;                       // never accept when unconfigured
  const received = headers[name.toLowerCase()];    // Node lowercases header names
  return Boolean(received) && safeEqual(received, secret);  // WHOLE value, no Bearer parsing
}
  • The header name is whatever you typed in the subscription, so read it from TIMIFY_WEBHOOK_HEADER (default Authorization) and look it up case-insensitively.
  • Compare the whole header value with TIMIFY_WEBHOOK_SECRET. If you entered Bearer abc123, the secret is Bearer abc123; do not strip or parse the prefix.
  • Return 401 for a missing header or a mismatch, 400 for a body that isn't a JSON object, 200 once handled.
  • Read the body raw (express.raw({ type: '*/*' })) and authenticate before parsing it.
  • Know the limits. A static shared credential authenticates the sender, not the body, and gives no replay protection (no signature, no timestamp). Use HTTPS only, and rotate the value in the subscription and in TIMIFY_WEBHOOK_SECRET if it leaks.

For complete handlers with tests, see examples/express/, examples/nextjs/, examples/fastapi/.

Webhooks and Types

TIMIFY's webhook overview lists these webhooks (the scope table) and their types. The overview page does not document the payload field names, so the examples dispatch defensively on an illustrative webhook and type and acknowledge anything they don't recognise.

WebhookTypes
CustomersCreated Updated Deleted
EventCreated Updated Deleted
EventsDeleted
ServicesCreated Updated Deleted
ResourceCreated Updated Deleted
CompanyCreated Updated Deleted
ManagerCreated Updated Deleted
EnterpriseUpdated
Customer FieldsCreated Updated Deleted
ShiftCreated Updated Deleted
NotificationCreated
Service GroupsCreated Updated Deleted
Before Confirmations, Before RemindersSync (not supported)

The Developer Platform application needs the scopes each webhook requires (see references/overview.md).

Environment Variables

TIMIFY_WEBHOOK_HEADER=Authorization       # the header name you entered in the subscription
TIMIFY_WEBHOOK_SECRET=your-secret-value   # the exact, whole header value

Local Development

TIMIFY can't reach localhost. Tunnel with the Hookdeck CLI (no account required):

npx hookdeck-cli listen 3000 timify --path /webhooks/timify

Use the printed URL as the Server URL of the webhook subscription.

Resources


Repository

hookdeck/webhook-skills

v0.1.0 · MIT · Updated Nov 9, 2026

View on GitHub →