Webhook payload reference
The Embers event envelope, the versions on it, every event type, the lead object, the contact rules, and the key you should join on.
Every Embers webhook is a JSON POST with the same envelope. This page describes what is in it and which fields you should build on.
The envelope
Every request carries a stable event id, the event type, two version strings, a created_at, the account that produced it, and a data object shaped by the event.
api_versionis2026-07-20. It only changes if the envelope is reshaped in a way a receiver cannot absorb by ignoring unknown keys, which has not happened.schema_versionis2026-09-10. It records field-level changes, so a key that is added or dropped bumps this and leavesapi_versionalone. 2026-09-10 droppedaccount.type; route onaccount.idandaccount.name.accountcarries the account id and name, so agencies can route events for several client accounts without looking up a UUID.
Ignore keys you do not recognise.
Event types
| Type | When it fires |
|---|---|
lead.created | Embers creates a lead score for a person in your account. Carries the engagement that triggered it |
lead.engagement.added | A qualified lead you already have engages again. One event per lead per scan, with every new engagement batched in. Not sent alongside lead.created |
lead.status_changed | Someone moves a lead to a different pipeline status. Carries previous_status, status, and changed_at |
report.generated | A client report finishes generating or regenerating. Carries the report id, title, status, date range, reason, and public share URL, but not the report snapshot |
webhook.test | An administrator sent a sample from Developer, then Webhooks. data.is_test is always true and data.sample_event_type names the shape that was chosen |
On lead.engagement.added, data.engagement.engagement_count is the true total and data.engagement.engagements is capped at 50 items, with truncated set when the array is shorter than the count.
The lead object
data.lead carries id, name, title, company, linkedin_url, linkedin_urn, score, icp_match, icp_confidence, icp_reason, trend, top_signals, sources, status, follower_count, and first_seen_at, plus work_history and certifications capped at 10 entries each.
score and icp_confidence use the same 0 to 100 scale shown in the app.
There is no first name or last name field. The payload has one name.
Two numbers the app shows are derived rather than sent. Engagement rate is engagement_count divided by follower_count, which is why follower_count is included. Grade comes from score: A at 80 or more, B at 60, C at 40, D at 20, F below that.
Join on linkedin_urn
lead.linkedin_urn is LinkedIn’s own immutable member id, and it is the key to join on. Do not key on linkedin_url: members change their vanity slug, and some people are only ever seen in URN form, so the same person can appear under two different URLs. lead.id is the Embers UUID and is stable per account and member, but if two member records are merged the losing UUID stops appearing. On older records linkedin_urn may be blank, so fall back to lead.id.
Contact fields
lead.contact is additive and gated by plan.
- Free: the key is omitted entirely.
- Solo and above: the key is present, carrying
email,phone,enriched_at,last_verified_at,included,source,confidence, andstatus.
Only values Embers already stored are copied. Missing values are null, and included is true only when a stored value exists. Webhooks never trigger a fresh enrichment and never invent an address or a number. Comment text can still contain contact details the person published themselves, but that is public post content, not the structured contact object.
Engagement timestamps
engaged_at_precision tells you whether engaged_at is a measurement or a substitute. LinkedIn publishes a timestamp for comments and replies, so those are exact. Reactions are approximate, where Embers substitutes the time it first saw the reaction or the parent post’s date. Order a follow-up sequence on exact rows only.
Example
{
"id": "e1b4f6e8-4c4a-4f50-b3c7-2ef2f97d5012",
"type": "lead.status_changed",
"api_version": "2026-07-20",
"schema_version": "2026-09-10",
"created_at": "2026-07-20T10:00:00+00:00",
"account": {
"id": "4d2f0eb9-81e5-4f20-8a60-25cbb9fe9ea5",
"name": "Acme LinkedIn"
},
"data": {
"lead": {
"id": "967caf1c-c0a6-4b98-9f3b-1e0811fb53b4",
"name": "Alex Smith",
"title": "VP Sales",
"company": "Acme",
"linkedin_url": "https://www.linkedin.com/in/alex-smith/",
"linkedin_urn": "ACoAAABBBCCCDDDEEEFFFGGG",
"score": 82,
"icp_match": true,
"icp_confidence": 90,
"icp_reason": "Strong insurance principal with clear sales authority.",
"trend": "rising",
"top_signals": ["Visited pricing"],
"sources": ["post_engagement"],
"status": "contacted",
"follower_count": 4200,
"first_seen_at": "2026-06-02T09:15:00+00:00",
"contact": {
"email": "alex@acme.example",
"phone": "+13125550100",
"enriched_at": "2026-07-01T00:00:00+00:00",
"last_verified_at": "2026-07-01T00:00:00+00:00",
"included": true,
"source": "harvest",
"confidence": "safe",
"status": "ready"
}
},
"engagement": {
"recent": [
{
"engagement_type": "comment",
"engagement_category": "comment",
"engaged_at": "2026-07-19T14:02:00+00:00",
"engaged_at_precision": "exact",
"source": "post",
"comment_text": "This matches what we're seeing at renewal.",
"post_url": "https://www.linkedin.com/feed/update/7481311828074078208/",
"post_author_name": "You",
"post_author_type": "you",
"post_snippet": "A post about renewal cycles in commercial insurance.",
"intent_category": "pain_alignment"
}
],
"by_type": { "comment": 1 },
"first_engaged_at": "2026-07-19T14:02:00+00:00",
"last_engaged_at": "2026-07-19T14:02:00+00:00"
},
"previous_status": "active",
"status": "contacted",
"changed_at": "2026-07-20T10:00:00+00:00"
}
}
Related
Frequently asked questions
- Why is there no first name or last name in the payload?
- The payload carries a single name field. Split names appear in the CSV export, in HubSpot, and on the Slack card, not on the webhook.
- Will a new field break my receiver?
- Most changes are additive. 2026-09-10 removed `account.type`; ignore keys you do not recognise.
Was this article helpful?
What went wrong?
Thank you. We read every answer.
Still stuck?
Send us the article you were following and what happened. We answer from the same inbox that writes these pages.