CJM
Webhooks

Webhook triggers reference

Choose events, read their JSON payloads, and verify every request.

This page describes the outbound webhook contract: CJM sends a JSON POST to the URL configured in Set up an outbound webhook.

Common request format

Every request has this body shape:

{
  "event": {
    "id": "unique-event-id",
    "trigger": "lead.captured",
    "projectId": "project-id",
    "profileId": "profile-id-or-null",
    "occurredAt": "2026-09-07T10:00:00.000Z",
    "queuedAt": "2026-09-07T10:00:01.000Z"
  },
  "data": {},
  "metadata": {}
}

data changes with the trigger. metadata can contain contextual values and should be treated as optional. Do not assume that a profile is always present: profileId can be null.

Security headers

HeaderUse
Content-TypeAlways application/json.
X-CJM-Event-IdThe same ID as event.id; use it to deduplicate retries.
X-CJM-TriggerThe internal event trigger selected in CJM. Use event.trigger in the body when routing by the public trigger name.
X-CJM-TimestampTime the request was signed.
X-CJM-Signaturesha256=<hex digest> when a secret is configured.

To verify the signature, keep the exact raw JSON body. Build timestamp.eventId.body by joining X-CJM-Timestamp, X-CJM-Event-Id, and the raw body with periods, then calculate HMAC-SHA256 with your configured secret. Compare the result with the value after sha256=. Reject a request if it does not match.

Available triggers and data

TriggerSent whenFields in data
lead.capturedA lead is captured.eventId, eventName, trigger, timestamp, receivedAt
customer.convertedA lead becomes a customer.previousType, currentType, convertedAt
profile.score.changedA profile score changes.oldScore, newScore, fitScore, intentScore, activityScore, scoreIncreased
profile.stage.changedA profile changes CRM pipeline stage.previousStageId, nextStageId, nextStageName, crmStageId, monetaryValue, integrationSlug, eventId; currency and dealId may be present
form.submission.createdA tracked form submission is created.submissionId, formId, formConfigId, formVersionId, score fields, submittedAt, eventId
integration.meta.event_sentA Meta integration event is dispatched.providerPayload, normalizedUserData, result
integration.google_ads.event_sentA Google Ads integration event is dispatched.providerPayload, normalizedUserData, hashedUserData, result
system.testYou select Send test for connectivity.message, requestedBy, requestedAt

For Meta and Google Ads, result contains success, status, externalId, and errorSummary. The payload can include personal data supplied to the destination, so secure the receiver, limit access to its logs, and apply your privacy policy.

Receiver checklist

  1. Read the raw request body before changing or parsing it for signature verification.
  2. Verify X-CJM-Signature and reject invalid signatures.
  3. Deduplicate by X-CJM-Event-Id before performing an irreversible action.
  4. Route using event.trigger, then validate the expected data fields for that trigger.
  5. Return a 2xx response only after accepting the event.

See Set up an outbound webhook for retry behaviour and troubleshooting.

On this page