Support us on Product HuntZenABM - Create, optimize & report on LinkedIn Ads from any AI tool | Product Hunt

Webhooks

Send ZenABM signals to any tool the moment accounts change.

Webhooks send ZenABM signals to any other tool the moment an account changes, without manual exports or polling. Every Monday, when LinkedIn data syncs, webhooks fire automatically and push your data wherever you want it: Clay, Outreach, Salesloft, n8n, a Slack alert, or any prospecting and sales engagement tool with an endpoint. You get a filter builder to scope the data, and a payload builder to decide which fields go out.

What you can send

Any company-level signal ZenABM holds can go in the payload:

  • Engagement data: impressions, clicks, engagements and spend over a date range you pick, with the ad sets behind them.
  • Account scores: the engagement score and the account's current and lifetime ABM stage, overall and per ABM Campaign.
  • Intent signals: the intents detected from ad engagement.
  • Company details: name, domain, country, city, LinkedIn page, and the HubSpot company ID.

Webhooks carry LinkedIn Ads data plus ZenABM's ABM fields.

Best practices

One of the most common plays is sending your Interested Companies into any orchestration tool (this works great with Clay).

ZenABM's weekly data can trigger outreach sequences based on the Intent the engaged companies are showing, so the first message leads with the theme the account already responded to.

Configuring a webhook
Tip

Webhooks are triggered every Monday, after each fresh LinkedIn data sync. You can also trigger them manually on demand. If you would rather pull than be pushed, the REST API exposes the same data, scores and intents, and the MCP server exposes them to AI agents.

Prefer your CRM?

The same signals can be written straight onto company records in HubSpot, Salesforce or Attio, with no endpoint to host. See CRM sync.

How to set it up

Add a webhook

Point it at the URL in the system you want to notify.

Choose delivery type

Individual sends one request per company (best for Clay, Make, Zapier and n8n, one row or one scenario run per company). Batch sends a JSON array of companies, so fewer requests, but your tool needs an iterator to loop over the array. Large runs are split into several batch requests.

Pick a date range

7, 30, 90 or 180 days. All windowed metrics (clicks, impressions, cost and so on) cover this range.

Filter the data

Build conditions to narrow the data you want us to send (for example, Companies in the Interested ABM Stage).

Define payload

Choose which fields you want us to send.

Test it

From the webhooks list, send a test event (up to 10 real companies) or trigger a full send manually.

Which companies are sent

Without conditions, every company in your workspace is sent, including companies with no ad activity in the date range. Those companies come through with 0 metrics and often the first stage (for example Identified). This is expected.

To send only active accounts, add a condition such as Impressions greater than 0 or ABM Stage is Interested.

Payload reference

In Individual mode, each request body is one JSON object like this. In Batch mode, the body is a JSON array of these objects. You only get the fields you selected; name and linkedInId are always sent.

{
  "name": "Example Inc",
  "linkedInId": "urn:li:organization:123456",
  "linkedInUrl": "https://www.linkedin.com/company/123456",
  "domain": "example.com",
  "country": "DE",
  "city": "Berlin",
  "abmStage": "Aware",
  "lifetimeAbmStage": "Interested",
  "abmCampaigns": ["DACH Fintech"],
  "abmCampaignStages": [{ "campaignId": "cmabc123", "campaign": "DACH Fintech", "stage": "Aware" }],
  "intents": ["Compliance"],
  "clicks": 4,
  "engagements": 11,
  "impressions": 820,
  "costInUsd": 96.4,
  "costPerClick": 24.1,
  "totalClicks": 4,
  "totalEngagements": 11,
  "totalImpressions": 820,
  "linkedInCampaignsWithClicks": ["Compliance - Video"],
  "linkedInCampaignsWithEngagements": ["Compliance - Video"],
  "linkedInCampaignsWithImpressions": ["Compliance - Video", "Brand - Image"],
  "lifetimeEngagementScore": 3,
  "hubspotCompanyId": "12345678"
}
FieldWhat it contains
domainBare domain of the company website: no https://, no www., no path. For example example.com. Empty string if unknown. Use it to match the company in your CRM.
abmStageCurrent ABM Stage, sent exactly as named on your ABM Stages page. Calculated from your ABM Campaigns, with the scope selected there and their start date. With no ABM Campaign, it is the same as lifetimeAbmStage. Empty string if none.
lifetimeAbmStageLifetime ABM Stage. Not limited in scope, and starts about 90 days before you signed up. It never goes down, so it shows how far the company ever got across all your motions.
abmCampaignStagesOne entry per ABM Campaign the company belongs to, with its stage inside that campaign (same stage names). Not limited by the webhook's campaign selection. Empty array until you create an ABM Campaign, or if the company is in none.
abmCampaignsNames of the ABM Campaigns the company belongs to.
intentsNames of the intents detected for the company.
clicks, engagements, impressions, costInUsd, costPerClickActivity in the webhook's date range. See the next section for scope.
totalClicks, totalEngagements, totalImpressionsCompany-wide activity in the same date range. See the next section.
linkedInCampaignsWith…Names of the LinkedIn ad sets that got clicks, engagements or impressions from the company.
lifetimeEngagementScoreWhole number from 1 to 5, based on all LinkedIn interactions. Not affected by the date range.
hubspotCompanyIdID of the matched HubSpot company. Empty string if there is no match.

clicks vs. totalClicks

Both use the same date range. "Total" does not mean lifetime.

  • clicks, engagements, impressions: activity on the campaigns, ad sets or ABM Campaigns you selected on the webhook. With no campaign selection, they equal the company-wide numbers.
  • totalClicks, totalEngagements, totalImpressions: company-wide activity across all your LinkedIn ads. They are only sent when the webhook has no campaign selection.

For a weekly overwrite in your CRM, use clicks, engagements and impressions. They are always present and match your campaign selection.

Useful CRM fields for campaign performance

To judge campaign performance per account, send abmStage, engagements, clicks, lifetimeEngagementScore, intents and abmCampaignStages. Add lifetimeAbmStage to see how far each company ever got.

Create an ABM Campaign before launch

You can read performance without one, but an ABM Campaign groups your LinkedIn campaigns under one ABM motion, gives a per-campaign stage view, and fills abmCampaigns and abmCampaignStages in the webhook. If you have one target account list, the simplest setup is one ABM Campaign that holds all your LinkedIn campaigns.

Delivery, responses and retries

Webhooks send a POST with a JSON body every Monday, after the weekly LinkedIn sync.

  • Success: any 2xx response.
  • Timeout: 30 seconds per request.
  • 429: we back off and retry the same request, up to 8 times, then continue the run later.
  • 5xx, 408, timeout or network error: we retry the whole run once, after about 1 to 5 minutes. Failures after that retry are final.
  • 404: no retry, and the webhook is turned off. Check the URL and turn it back on.
  • 400, 403, 413: no retry.

A run stops early after the first 404, after 3 400/403 responses in a row, or after 3 network errors in a row.

Tip

If your tool needs more than 30 seconds to process a company, answer 200 right away and do the work afterwards.

Changing a webhook later

You can edit an existing webhook at any time: add or remove payload fields (for example intents, abmCampaigns, abmCampaignStages or costInUsd), change conditions, the date range or the URL. You do not need a new webhook. The next send uses the new settings.

Example: Make.com to Pipedrive

This recipe updates existing Pipedrive organizations with ZenABM data every week. It does not create new organizations.

Create the scenario in Make

Add a Webhooks → Custom webhook trigger and copy its URL.

Create the webhook in ZenABM

Paste the URL. Pick Individual delivery, so each company starts one scenario run. Select domain plus the fields you want in Pipedrive. Add a condition such as Impressions greater than 0 to skip inactive companies.

Send a test event

Make reads the sample and learns the fields.

Find the organization

Add a Pipedrive Search for organizations module. Search by the domain field (or by name if your organizations have no domain field).

Update it

Add a filter that continues only when an organization was found. Then add a Pipedrive Update an organization module and map the ZenABM fields to your custom fields.

The same pattern (webhook trigger → search by domain → update) works in Zapier and n8n.