Skip to main content

Webhooks

When a signal fires, Datamagnet sends an HTTP POST request to the webhook_url you configured when creating the signal.

Registering a webhook

Pass a webhook_url when calling /signal/create or update it later via /signal/update.
Example

Payload format by signal type

Every delivery is one JSON object with a top-level event field:

job_change · new_post · person_activity

The first run for each profile records a baseline and sends a baseline event listing the profiles now tracked. After that, each run that finds changes sends one delivery with every change in changes. job_id and job_name are the signal’s signal_id and name, so you can tell apart several signals of one type. A profile tracked by two signals appears in a delivery from each.
baseline
job_change
new_post
For person_activity, changes holds one entry per reaction, comment, or reply. See the Person Activity guide for its payload.

Engagement signals

All four engagement signal types — keyword_engagement, industry_engagement, company_engagement, and person_engagement — share the same webhook payload structure. The only difference is the signal_type value and the meaning of signal_keyword.
keyword_engagement example
company_engagement example
industry_engagement example
person_engagement example

Engagement signal payload fields

Missed a delivery, or want the history? /signal/leads returns your stored leads with these same fields, on request.

Top level

string
Same as signal_type.
string
The account email that owns the signal.
string
One of "keyword_engagement" · "company_engagement" · "industry_engagement" · "person_engagement".
object
Aggregated counts for this run. The group count key varies by signal type:All types include total_raw, after_dedup, after_icp, flame_1, flame_2, flame_3.
array
Qualified leads sorted by lead_score descending. Each object contains the fields below.

Per-lead fields

string
The LinkedIn profile URL of the person who engaged.
string
Full name of the engager.
string
Current LinkedIn headline of the engager.
string
The search term or group label that surfaced this lead.
  • keyword_engagement — the keyword that matched (e.g. "sales intelligence")
  • company_engagement — the company label (e.g. "Salesforce")
  • industry_engagement — the industry label (e.g. "Financial Services")
  • person_engagement — the monitored person’s label (e.g. "John Doe")
string
How the person engaged with the post. Either "like" (or a specific reaction type such as "celebrate", "support") or "comment".
string
URL of the LinkedIn post the person engaged with.
Deep link to the specific engagement. For comments, this links directly to the comment. For likes, same as engagement_post_url.
string | null
The text of the comment left by the engager. null for likes and reactions — only populated when engagement_type is "comment".
string | null
First 300 characters of the post the engager interacted with. Gives context about the content that triggered the signal. null if the post text could not be retrieved.
string | null
Full name of the person or page who authored the post. null if the author could not be retrieved.
integer
Overall lead quality score from 1 to 3.composite = 0.5 × icp_score + 0.5 × signal_score
number
ICP fit score between 0.0 and 1.0. Reflects how well the lead matches the configured ICP filters.
number
Intent signal score between 0.0 and 1.0. Based on engagement type (comment = 1.0, like = 0.7), post recency (decays over 14 days), and keyword specificity.
string
ISO 8601 timestamp of when the lead was scored.

job_change · new_post · person_activity payload fields

Top level

string
"baseline", or the signal type when there are changes.
string
The account email that owns the signal.
string
The signal’s signal_id.
string
The signal’s display name.
string
"job_change", "new_post", or "person_activity".
array
baseline events only. Each newly tracked profile: profile_url, profile_name.
array
Change events only. One entry per change, with the fields below.

Per-change fields

string
Unique ID of this change. Use it to de-duplicate on your side.
string
The tracked LinkedIn profile.
string
Full name of the tracked person.
string
"job_change" or "new_post"; for person_activity, "reaction", "comment", or "reply".
string
One or two sentences describing the change.
number | null
How sure the detection is, from 0.0 to 1.0. null for person_activity.
string
ISO 8601 time the change was detected.
object
Details of the change.When the change could not be analysed in detail, change_data also has "_llm_fallback": true and a shorter, generic summary. The change itself is real.

Verifying webhook signatures

If you set a webhook_secret, every request includes an X-Datamagnet-Signature header: sha256= followed by the hex HMAC-SHA256 of the raw request body, signed with your secret. The same value is also sent as X-Signature-256.
Always use a timing-safe comparison (hmac.compare_digest in Python, crypto.timingSafeEqual in Node.js) to prevent timing attacks.

Responding to webhooks

Your endpoint must return a 2xx status within 10 seconds. If it times out or returns an error, Datamagnet retries the same payload: A 400, 401, 403, or 404 response means the endpoint is misconfigured, so it is retried once and then dropped. Use event_id (profile signals) to ignore a change you already processed. Acknowledge immediately and process asynchronously to avoid timeouts:
Python (Flask)