Skip to main content

Lead Events

Lead events follow a lead from capture through ownership and funnel changes to deletion. Every event publishes the stored Lead as Sakneen holds it at the moment of the change.

Event types​

EventEmitted when
lead.createdA lead is captured in Sakneen
lead.assignedA lead without an owner gains a salesperson
lead.reassignedA lead moves from one salesperson to another
lead.status_changedThe lead status moves
lead.updatedA lead changes in a way no more specific lead event covers
lead.deletedA lead is deleted

All six use eventVersion: 1, resource.type: "lead", and the lead's integration version as resource.version.

Lead conversion

lead.converted is not emitted and is not offered in the subscription catalog. Until it ships, treat lead.status_changed reaching your organization's configured converted status as the conversion signal.

One event per change​

A single change to a lead produces exactly one event. When a change could match more than one type, Sakneen picks the most specific one in this order:

deleted > assigned | reassigned > status_changed > updated

The chosen type is a label only — it never limits the content. Every event carries the whole lead, so a bulk edit that reassigns a lead and moves its status arrives as lead.reassigned with both new values in data.

Subscribe to every type whose transition you care about. Because each event carries the full lead, subscribing to a single type still keeps your copy correct for the changes that type covers.

Envelope values​

Lead events use the standard event envelope with these values:

FieldLead event value
eventTypeOne of the six types above
eventVersion1
occurredAtThe lead snapshot's updatedAt timestamp
sourcesakneen
organizationIdOrganization that owns the lead
resource.typelead
resource.idSame identifier as data._id
resource.versionPositive, monotonically increasing lead integration version
dataThe stored lead, described below

eventVersion identifies the external contract described on this page. resource.version identifies the revision of one lead. It advances only when a change is publishable and you are subscribed, so you will not see gaps for silent edits. Compare versions rather than assuming they are contiguous.

Snapshot behavior​

The data object is the complete stored lead document at the moment of the change, not a field-level patch. Replace your stored snapshot only when the incoming resource.version is newer than the version you have already processed.

Because delivery is at least once and each delivery retries independently, events for the same lead can arrive out of order. Applying by version rather than arrival order is what keeps your copy correct.

Identifiers​

leadId is the organization number, not the canonical identifier

data._id is the lead's canonical Sakneen identifier and matches resource.id. data.leadId is the organization-scoped lead number shown in the Sakneen interface.

This differs from Client events, where the canonical identifier is published as clientId and the organization number as clientCode. Lead events publish Sakneen's stored field names directly.

Lead data​

Version one delivers the lead exactly as Sakneen stores it. data therefore reflects your organization's own lead configuration: which fields are present depends on how your organization uses Sakneen, and on the individual lead.

These fields are always present:

FieldTypeDescription
_idstringCanonical Sakneen lead identifier; matches resource.id
organizationIdstringOrganization that owns the lead; matches the envelope organization
leadIdnumberOrganization-scoped lead number shown in the Sakneen interface
dataobjectYour organization's configured lead fields, such as name, phoneNumber, email, and status
createdAtISO 8601 stringUTC time when the lead was captured
updatedAtISO 8601 stringUTC time of this lead snapshot; matches occurredAt

Every other stored lead field is delivered as stored. Common examples:

FieldTypeDescription
clientIdstringLinked Client, joining this lead to the client.* stream
salesPersonIdstringCurrent owner
assignedAtISO 8601 stringWhen the current owner was assigned
assignedByIdstringWho assigned the current owner
createdByIdstringWho captured the lead
isReassignedbooleanWhether the lead has changed owner at least once
reassignedAtISO 8601 stringWhen the lead last changed owner
isActivebooleanFalse for a duplicate lead held behind a parent
isFreshbooleanWhether the lead is still awaiting first contact
isDeletedbooleanWhether the lead has been soft-deleted
parentIdstringSet when this lead is a duplicate of an earlier one
compoundsIdsstring[]Compounds the lead is interested in
preferencesobject[]Captured lead preferences
lastActivityDateISO 8601 stringLast recorded sales activity
providerstringCapture channel, when the lead came from an ad platform
recordSystemIdstringYour external lead or submission identifier, when one was supplied

Value conventions:

  • Identifiers are strings, and timestamps are ISO 8601 strings.
  • leadId is a number.
  • Fields with no stored value are omitted. An omitted field is not an empty string, zero, false, or an empty array.
  • Numbers, booleans, arrays, and nested objects appear as stored.

The following are never included in data:

  • integrationVersion, which is published as resource.version instead;
  • Sakneen's internal document version key and identifier alias;
  • computed values and related records loaded from other collections, such as the linked salesperson, client, child leads, activities, and feedback.
The payload contains your organization's raw lead data

Because version one sends the lead as stored, data can contain internal operational content:

  • notes and data.leadNotes — free-text sales commentary written by your team about a named person;
  • rowData and additionalData — verbatim import rows and provider request bodies, exactly as they arrived, which can include tracking metadata;
  • provider, CRM, and record-system identifiers.

Send lead events only to destinations entitled to your organization's full lead data, including personal data belonging to your contacts, and do not forward the payload unchanged to less-trusted systems. Confirm this is compatible with your own privacy commitments before subscribing.

A later event version will add organization-level field selection.

Sakneen can add fields to event version 1 at any time. Ignore unknown fields, and do not assume a fixed set of keys. Read the fields your integration understands, and validate them on your side rather than assuming a Sakneen-side shape guarantee.

Lead statuses​

Lead statuses are configured per organization, so data.data.status is free text rather than a fixed set. Two organizations can use different labels for the same stage, and one organization can rename a status at any time.

Normalize on your side if you need stable buckets — for example by lowercasing and removing non-alphanumeric characters, so "No Answer", "no-answer", and "noAnswer" all collapse to the same key.

Representative event​

{
"eventId": "019c0f13-c4d9-5e60-b7a1-2f8c05e94d13",
"eventType": "lead.status_changed",
"eventVersion": 1,
"occurredAt": "2026-08-06T11:40:00.000Z",
"source": "sakneen",
"organizationId": "64f1a0d6d5d0a14a5c0e8a10",
"correlationId": "019c0f13-c4d9-7a3f-9e05-7b1d2c6a8e40",
"resource": {
"type": "lead",
"id": "64f1a0d6d5d0a14a5c0e8a30",
"version": 3
},
"data": {
"_id": "64f1a0d6d5d0a14a5c0e8a30",
"organizationId": "64f1a0d6d5d0a14a5c0e8a10",
"leadId": 4127,
"clientId": "64f1a0d6d5d0a14a5c0e8a20",
"recordSystemId": "website-form-018f9f29-4b8a-7c1a",
"compoundsIds": ["64f1a0d6d5d0a14a5c0e8a40"],
"salesPersonId": "64f1a0d6d5d0a14a5c0e8a50",
"assignedAt": "2026-08-06T10:15:00.000Z",
"assignedById": "64f1a0d6d5d0a14a5c0e8a50",
"createdById": "64f1a0d6d5d0a14a5c0e8a50",
"isActive": true,
"isDeleted": false,
"isFresh": false,
"isReassigned": false,
"lastActivityDate": "2026-08-06T11:40:00.000Z",
"data": {
"email": "[email protected]",
"firstName": "Nour",
"lastName": "Hassan",
"phoneNumber": "+201000000000",
"status": "Meeting Scheduled"
},
"createdAt": "2026-08-06T09:00:00.000Z",
"updatedAt": "2026-08-06T11:40:00.000Z"
}
}

Deletion snapshots​

lead.deleted represents a soft deletion. Its data object is the full final stored lead with isDeleted: true; it is not a tombstone containing only an identifier. Repeating a delete for an already deleted lead does not produce a new lifecycle event.

Recovering from a missed event​

Every lead event carries the whole lead, so a missed event repairs itself: the next event you receive for that lead replaces your copy with current state.

One case does not repair itself. Events routed to a destination while it is suspended are cancelled and cannot be replayed from the Developer Console, so a lead that changed only during the suspension will not be corrected until it changes again. Re-read those leads after reactivating a destination:

GET /external/apis/v1.0/leads/:recordSystemId
api-key: YOUR_API_KEY

The response wraps the lead: its lead field carries the same shape lead events publish in data.

{
"ok": true,
"lead": {
"_id": "64f1a0d6d5d0a14a5c0e8a30",
"organizationId": "64f1a0d6d5d0a14a5c0e8a10",
"leadId": 4127,
"clientId": "64f1a0d6d5d0a14a5c0e8a20",
"recordSystemId": "website-form-018f9f29-4b8a-7c1a",
"salesPersonId": "64f1a0d6d5d0a14a5c0e8a50",
"isActive": true,
"isDeleted": false,
"isFresh": false,
"data": {
"firstName": "Nour",
"status": "Meeting Scheduled"
},
"createdAt": "2026-08-06T09:00:00.000Z",
"updatedAt": "2026-08-06T11:40:00.000Z"
}
}

This route requires the lead to have a recordSystemId. Leads captured without one cannot be re-read by external identifier.

Processing recommendations​

  • Verify the webhook signature against the raw request body.
  • Deduplicate every event by eventId; delivery is at least once.
  • Partition processing by resource.type and resource.id.
  • Apply a snapshot only when resource.version is newer than the version you have already processed.
  • Replace your stored snapshot instead of treating data as a field-level patch.
  • Do not require resource versions to be consecutive.
  • Configure the webhook endpoint to accept JSON request bodies up to 1 MiB.
  • Return 2xx only after durable acceptance. See Delivery and retries for automatic and manual retry behavior.

Scope​

Version one publishes lead changes made through Sakneen's own lead flows: lead capture across the sales, ecommerce, admin, external API, and AI paths and both bulk imports; assignment and reassignment; status changes, including those derived from sales feedback; other direct lead edits; and deletion.

The following do not emit lead events:

  • Salesforce field synchronization into Sakneen
  • Lead capture from Facebook, LinkedIn, and TikTok ad integrations
  • Lead expiry and inactivity background jobs
  • Migrations, seeders, repairs, and backfills

Assignment performed as part of a CRM synchronization does emit, because the lead genuinely changed owner.

Historical leads are not backfilled. Events begin once an active destination subscribes.