• Customermates logo
    CustomermatesDocumentation
  • Introduction
Getting Started
  • Quickstart
  • Core Concepts
Connect your AI
  • Custom connector
  • CLI & editors
  • Rate limits
Integrations
  • MCP
  • Webhooks
  • OpenAPI 3.1.0
  • N8N
Self-Hosting
  • Get Started
  • Architecture & Security
App guide
  • Dashboard
  • Inbox
  • Records
  • Profile
  • Company
  • API Keys
  • Filter Syntax
  • Go back
  1. Introduction
  2. Webhooks

Webhooks

Subscribe to CRM events, verify signatures, inspect failed deliveries, and read the full event catalog in one place.

Customermates sends a JSON POST to your HTTPS endpoint whenever subscribed data changes. You choose the events and provide the URL. Failed deliveries can be re-sent from the UI or through MCP. Deliveries are signed with HMAC-SHA256 over the raw request body. Every event and its payload shape is listed in the catalog at the end of this page.

Uses

Webhooks let other systems react to CRM changes without polling.

  • Push new contacts into an email sequencer.
  • Open a ticket in a support tool when a deal changes state.
  • Trigger a finance workflow when a deal is marked as closed.
  • Sync records into a data warehouse in near real time.

Create a webhook

UI: Company, then Webhooks, then New.

MCP: manage_webhooks with action: "create", plus url, events[], and optional description, secret, enabled.

{
  "url": "https://hooks.example.com/customermates",
  "events": ["contact.created", "contact.updated", "deal.updated"],
  "secret": "use-a-random-string-from-a-password-manager",
  "enabled": true
}

The URL must be HTTPS. HTTP is rejected.

What you receive

Every delivery is a POST with Content-Type: application/json and the same envelope:

{
  "event": "<event-name>",
  "data": {
    "userId": "<who-triggered-it>",
    "companyId": "<workspace>",
    "entityId": "<affected-record>",
    "payload": { /* event-specific */ }
  },
  "timestamp": "<iso-8601>"
}

userId is the user who caused the write, including a user acting through an API key. For messaging events, which are triggered by inbound provider activity rather than a user action, userId is null.

For *.updated events, payload wraps the full record together with a changes object. For *.created and *.deleted events, payload is the record itself.

Example, contact.updated:

{
  "event": "contact.updated",
  "data": {
    "userId": "u_123",
    "companyId": "c_abc",
    "entityId": "ct_xyz",
    "payload": {
      "contact": {
        "id": "ct_xyz",
        "firstName": "Max",
        "lastName": "Mustermann",
        "notes": { /* Tiptap JSON */ },
        "organizations": [{ "id": "org_1", "name": "Example GmbH" }],
        "users": [],
        "deals": [{ "id": "deal_1" }, { "id": "deal_2" }],
        "customFieldValues": [
          { "columnId": "col_abc", "value": "Won" }
        ]
      },
      "changes": {
        "organizations": {
          "previous": [],
          "current": [{ "id": "org_1", "name": "Example GmbH" }]
        }
      }
    }
  },
  "timestamp": "2026-04-22T10:00:00.000Z"
}

The record fields depend on the entity type. Custom columns appear under customFieldValues as columnId and value pairs. Use get_record_schema to see the columns configured for a given entity in your workspace.

The changes object

changes is present only on *.updated events. Each key is a record field whose value moved. previous is the value before the write, current is the value after.

Arrays of related records compare by id. Objects compare by deep equality. Scalar fields compare by value. createdAt and updatedAt are never reported as changes.

If a write does not change any field, the event is suppressed. No-op *.updated events are not delivered.

Signature verification

If you set a secret, every request includes:

X-Webhook-Signature: <hex>

<hex> is HMAC-SHA256(secret, rawRequestBody), lowercase hex, no prefix. Recompute it on your side and compare in constant time.

Node.js example:

import crypto from "crypto";

function verify(rawBody: string, received: string, secret: string) {
  const expected = crypto.createHmac("sha256", secret).update(rawBody).digest("hex");
  return crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(received));
}

Retries and failed deliveries

Every delivery is recorded. Review deliveries in the UI (Company, then Webhook Deliveries) or through manage_webhooks with action: "list_deliveries".

A delivery is marked failed if the HTTP status is outside the 2xx range or the request times out. The request timeout is 5 seconds.

Customermates automatically retries failed deliveries: up to 5 retries for timeouts, 5xx responses, and 408, 425, and 429. Permanent 4xx responses (for example 400, 401, 403, 404) are not retried, because a repeat would fail the same way. Retries happen inside the delivery run, so they do not create extra delivery records; each record shows the final outcome.

You can also resend any delivery yourself from the UI or with manage_webhooks and action: "resend_delivery" plus the delivery id. A manual resend creates a new delivery record; the original is unchanged.

Ordering and concurrency

Deliveries are not strictly ordered across events. Two contact.updated events milliseconds apart can arrive out of order. Use the timestamp in the payload to resolve order, or treat deliveries as idempotent messages keyed by entityId.

Notes are JSON, not markdown

The notes field in payloads is Tiptap JSON, the same structure the editor stores. To render it as markdown on your side, run it through a Tiptap-compatible serializer. In MCP, get_records with include: "withNotes" returns notes already serialized to markdown.

Delete payloads

Delete events carry the full record as it was before deletion, under payload, not just the id. The affected record id is also available as data.entityId.

Debugging

  • Use webhook.site as a throwaway receiver during integration testing.
  • The delivery log (manage_webhooks, action: "list_deliveries") supports searchTerm on url and event name.
  • If your receiver returns an error status, Customermates records the response so you can inspect what happened.

Event catalog

Twenty-six events are available to subscribe to: fifteen record events across the five entity types, and eleven messaging events. All use the envelope above.

Record events

EventWhen it firespayload
contact.createdA contact is created via UI, API, MCP, or importfull contact
contact.updatedAny contact field changescontact, changes
contact.deletedA contact is deletedfull contact
organization.createdAn organization is createdfull organization
organization.updatedAny organization field changesorganization, changes
organization.deletedAn organization is deletedfull organization
deal.createdA deal is createdfull deal
deal.updatedAny deal field changesdeal, changes
deal.deletedA deal is deletedfull deal
service.createdA service is createdfull service
service.updatedAny service field changesservice, changes
service.deletedA service is deletedfull service
task.createdA task is createdfull task
task.updatedAny task field changestask, changes
task.deletedA task is deletedfull task

Messaging events

Messaging events fire on inbound provider activity on connected accounts. userId is null. Payloads reference provider records by id (connectedAccountId, provider, providerMessageId, threadId, and similar) rather than embedding CRM records.

EventWhen it fires
messaging.message.receivedA chat message or email is ingested
messaging.message.updatedAn ingested message is updated
messaging.message.deletedAn ingested message is deleted
messaging.message.reactionA reaction is added to a message
messaging.email.receivedAn email is ingested
messaging.email.deletedAn ingested email is deleted
messaging.chat.updatedA chat thread is updated
messaging.chat.deletedA chat thread is deleted
messaging.calendar.changedA connected calendar changes
messaging.calendar_event.changedA calendar event changes
messaging.relation.createdA new provider relation is created

Next

  • MCP tool catalog: programmatic webhook management.
  • n8n integration: drop webhooks into visual workflows.
Uses
Create a webhook
What you receive
The changes object
Signature verification
Retries and failed deliveries
Ordering and concurrency
Notes are JSON, not markdown
Delete payloads
Debugging
Event catalog
Record events
Messaging events
Next