Perfex CRM Webhooks — 100+ Events, HMAC-Signed

Subscribe to every meaningful change in your Perfex CRM. Three processing modes, automatic retries, and a dead-letter queue — bundled with every PerfexAPI license from $49.

Why webhooks (and not polling)?

Polling a REST API every minute burns CPU on both ends and leaks the current state of your CRM to anyone watching the wire. Webhooks push a signed payload only when something actually changes — with latencies measured in milliseconds instead of minutes.

PerfexAPI ships 100+ webhook events across all 19 CRM resources. Every event carries the full resource payload, a unique delivery ID, a timestamp, and an HMAC-SHA256 signature so you never have to call back to verify authenticity.

Three processing modes

Pick the delivery semantics that match your workload — no other Perfex CRM module offers this.

Immediate

Fires on the request thread

Lowest latency. Best for low-volume installs or when the receiving endpoint responds in under 100ms.

Smart

Debounces rapid events

Collapses repeated events from the same resource within a 2-second window. Ideal for customer-edit flows where users save multiple times.

Async

Background queue worker

Queues delivery to a worker process. Request thread returns immediately. Recommended for production and for downstream endpoints with variable response times.

Full event catalog

The most common events are documented below. The module also ships internal events for advanced use cases — the full catalog totals 100+ hooks.

Customer

5 events
  • customer.created

    A new customer is created

  • customer.updated

    A customer is updated

  • customer.deleted

    A customer is deleted

  • customer.contact_added

    A contact is added to a customer

  • customer.status_changed

    Customer status changes

Contact

3 events
  • contact.created

    A new contact is created

  • contact.updated

    A contact is updated

  • contact.deleted

    A contact is deleted

Lead

5 events
  • lead.created

    A lead is created

  • lead.updated

    A lead is updated

  • lead.converted

    A lead is converted to a customer

  • lead.status_changed

    Lead status changes

  • lead.assigned

    A lead is assigned to staff

Invoice

8 events
  • invoice.created

    An invoice is created

  • invoice.updated

    An invoice is updated

  • invoice.sent

    An invoice is sent

  • invoice.paid

    An invoice is paid

  • invoice.overdue

    An invoice becomes overdue

  • invoice.cancelled

    An invoice is cancelled

  • invoice.status_changed

    Invoice status changes

  • invoice.deleted

    An invoice is deleted

Payment

3 events
  • payment.created

    A new payment is recorded

  • payment.updated

    A payment is updated

  • payment.deleted

    A payment is deleted

Credit Note

7 events
  • credit_note.created

    A credit note is created

  • credit_note.updated

    A credit note is updated

  • credit_note.deleted

    A credit note is deleted

  • credit_note.status_changed

    Credit note status changes

  • credit_note.sent

    A credit note is sent to the client

  • credit_note.refund_created

    A refund is created for a credit note

  • credit_note.credits_applied

    Credits are applied to an invoice

Estimate

8 events
  • estimate.created

    An estimate is created

  • estimate.updated

    An estimate is updated

  • estimate.deleted

    An estimate is deleted

  • estimate.sent

    An estimate is sent to the client

  • estimate.accepted

    An estimate is accepted by the client

  • estimate.declined

    An estimate is declined by the client

  • estimate.converted

    An estimate is converted to an invoice

  • estimate.expiring

    An estimate is about to expire

Proposal

8 events
  • proposal.created

    A proposal is created

  • proposal.updated

    A proposal is updated

  • proposal.deleted

    A proposal is deleted

  • proposal.sent

    A proposal is sent to the client

  • proposal.accepted

    A proposal is accepted

  • proposal.declined

    A proposal is declined

  • proposal.converted

    A proposal is converted to an invoice

  • proposal.comment_added

    A comment is added to a proposal

Item

3 events
  • item.created

    A new item/product is created

  • item.updated

    An item/product is updated

  • item.deleted

    An item/product is deleted

Contract

8 events
  • contract.created

    A contract is created

  • contract.updated

    A contract is updated

  • contract.deleted

    A contract is deleted

  • contract.signed

    A contract is signed

  • contract.expiring

    A contract is about to expire

  • contract.expired

    A contract expires

  • contract.renewed

    A contract is renewed

  • contract.cancelled

    A contract is cancelled

Project

4 events
  • project.created

    A project is created

  • project.updated

    A project is updated

  • project.completed

    A project is completed

  • project.status_changed

    Project status changes

Task

10 events
  • task.created

    A task is created

  • task.updated

    A task is updated

  • task.deleted

    A task is deleted

  • task.assigned

    A task is assigned

  • task.completed

    A task is completed

  • task.overdue

    A task becomes overdue

  • task.comment_added

    A comment is added to a task

  • task.priority_changed

    A task priority is changed

  • task.timesheet_added

    A timesheet entry is added to a task

  • task.status_changed

    A task status changes

Timesheet

3 events
  • timesheet.created

    A timesheet entry is created

  • timesheet.updated

    A timesheet entry is updated

  • timesheet.deleted

    A timesheet entry is deleted

Ticket

10 events
  • ticket.created

    A ticket is created

  • ticket.updated

    A ticket is updated

  • ticket.deleted

    A ticket is deleted

  • ticket.assigned

    A ticket is assigned to staff

  • ticket.status_changed

    Ticket status changes

  • ticket.priority_changed

    Ticket priority changes

  • ticket.reply_added

    A reply is added to a ticket

  • ticket.attachment_added

    An attachment is added to a ticket

  • ticket.closed

    A ticket is closed

  • ticket.reopened

    A ticket is reopened

Expense

3 events
  • expense.created

    A new expense is created

  • expense.updated

    An expense is updated

  • expense.deleted

    An expense is deleted

Note

3 events
  • note.created

    A note is created

  • note.updated

    A note is updated

  • note.deleted

    A note is deleted

Staff

8 events
  • staff.created

    A staff member is created

  • staff.updated

    A staff member is updated

  • staff.deleted

    A staff member is deleted

  • staff.activated

    A staff member is activated

  • staff.deactivated

    A staff member is deactivated

  • staff.permissions_changed

    Staff permissions are changed

  • staff.password_changed

    A staff member password is changed

  • staff.login

    A staff member logs in

Subscription

1 events
  • subscription.created

    A customer subscribes

HMAC-SHA256 signatures

Every webhook request is signed with your per-endpoint secret. Verify in constant time and reject requests that fail the check.

verify-webhook.js
// Node.js — verify the X-Webhook-Signature header
import crypto from 'crypto';

function verifyWebhook(rawBody, signature, secret) {
  const expected = crypto
    .createHmac('sha256', secret)
    .update(rawBody, 'utf8')
    .digest('hex');

  return crypto.timingSafeEqual(
    Buffer.from(signature, 'hex'),
    Buffer.from(expected, 'hex'),
  );
}

// In your Express handler
app.post('/perfex-webhook', (req, res) => {
  const ok = verifyWebhook(
    req.rawBody,
    req.header('X-Webhook-Signature'),
    process.env.PERFEX_WEBHOOK_SECRET,
  );
  if (!ok) return res.status(401).end();
  // ... process req.body.event and req.body.data (payload also carries timestamp, webhook_id, metadata)
  res.sendStatus(200);
});

PHP and Python equivalents in the docs.

Retries and dead-letter queue

Exponential backoff

Up to 8 retries at 30s, 1m, 5m, 15m, 1h, 6h, 12h, 24h. Any 2xx response is treated as success; 4xx and 5xx trigger the next retry.

Dead-letter queue

Payloads that exhaust their retries are moved to the DLQ and surfaced in the Webhooks admin page. Replay a single delivery or bulk-replay all failures in one click.

100+ events, bundled free.

Themesic's separate Webhooks module ships ~35 events for an additional $59. PerfexAPI bundles everything in the $49 base license — and real-time webhooks beat 15-minute Zapier polling every day of the week.

Frequently asked questions

How do I verify Perfex CRM webhook signatures?

Each webhook request includes an X-Webhook-Signature header with an HMAC-SHA256 of the raw body computed with your per-endpoint secret. Recompute on your side and use a constant-time compare. See the code snippet above.

What is the retry policy for failed webhooks?

Up to 8 retries with exponential backoff (30s, 1m, 5m, 15m, 1h, 6h, 12h, 24h). Exhausted payloads move to the dead-letter queue and can be replayed from the admin page.

What is the difference between Immediate, Smart, and Async modes?

Immediate fires on the request thread for lowest latency. Smart debounces repeated events within 2 seconds. Async queues delivery to a background worker — recommended for production.

Can I use Perfex CRM webhooks with n8n?

Yes. The free n8n-nodes-perfexcrm community node exposes a PerfexCRM Trigger that listens for every supported event and verifies the HMAC signature automatically.

Are webhooks included in the price, or sold separately?

Bundled free with every PerfexAPI license starting at $49. Competitors sell API and Webhooks as separate $59 modules.

Can I rotate the webhook secret without downtime?

Yes. Each endpoint can hold a primary secret and a grace secret for up to 24 hours. New deliveries sign with the primary; your verifier can accept either during the window.

Ready to push signed events into your stack?

Install PerfexAPI, create an endpoint, pick a processing mode, and you are live.

Maintained by Kostas Malakontas at OBS Technologies · Last reviewed