Event reference
Event shape
The event object every webhook page item shares: each common key with its exact type, the relevance verdict, removed events and versioning.
A webhook POST is a small run webhook with counts and page tokens. The events come from its pages, GET /api/public/v1/events?pageToken=…, up to 100 in items (see Read a run's events). Each event is one JSON object. It has a set of common fields (the same on every event) and one platform object with the details of the item. This page shows the common part once. The pages for each platform show the platform object.
How to read this page
T | null means the key is always there and the value can be null. optional means the key can be missing. Types are written like TypeScript. Treat every string union as open: a new value can appear without a version change.
Common fields (every event)
Keys are sent in this order.
version1 today. The run webhook has its own version (3, the Signals-Event-Version header). See Versioning.eventIdeventTypeeventType is the same family.subEventTypeactionnew is a first sighting. updated is a changed item you may have seen before.signalTypereviews.new, social.post, website.changed. Full list: All event types.sourceads, reviews, linkedin, x, instagram, linkedin_mentions, reddit_mentions, news, website, job_postings or competitor_discovery. linkedin_engagement is never sent by webhook.orgIdtrackerIdprojectIdoptionalrunIdcompetitor{ name: string, domain: string | null, subjectKey: string }. name is the display name. domain is the domain you set for the tracker (hubspot.com); it is null when the tracker no longer exists, and on the webhook test event. subjectKey is an internal key for what the tracker watches: opaque, do not parse it.occurredAt2026-10-25T23:50:00.523Z). It is the vendor's publish time, or the time Signals fetched it when the vendor gives none. null on removed events, except jobs.removed.detectedAtsequenceitemKeyitemKey across its new and updated events. It is prefixed by source, for example reviews-g2-13856432 website-https://www.hubspot.com/pricing or job_postings-7421035.relevanceadsResponse | reviewResponse | socialPostResponse | mentionResponse | newsResponse | websiteResponse | jobResponse | competitorResponseeventType. The other seven are absent. null on removed events, except jobs.removed.metadatanull on removed events, except jobs.removed.Exactly one platform field
eventType tells you which key to read: ads → adsResponse, reviews → reviewResponse, social_post → socialPostResponse, mention → mentionResponse, news → newsResponse, website → websiteResponse, jobs → jobResponse, competitor → competitorResponse. metadata is a copy with the same values. Read either one, not both. If you want one code path for every platform, read metadata.
1{2 "version": 1,3 "eventId": "df38433d-cc67-4467-ba3a-8892f7a50702",4 "eventType": "website",5 "subEventType": "website_change",6 "action": "updated",7 "signalType": "website.changed",8 "source": "website",9 "orgId": "org_3KikADUjsyXrUJ4RJhWpwcp98Yf",10 "trackerId": "440b3b16-2000-484a-aa8b-7481d482f1dd",11 "projectId": "2738158a-08fd-4fc4-912d-43d4c328bc10",12 "runId": "8ba8ccfa-e9e5-4764-9feb-4b0e88a2ba4a",13 "competitor": {14 "name": "HubSpot",15 "domain": "hubspot.com",16 "subjectKey": "https://www.hubspot.com/pricing"17 },18 "occurredAt": "2026-10-27T15:08:27.064Z",19 "detectedAt": "2026-10-27T15:08:27.064Z",20 "sequence": 5,21 "itemKey": "website-https://www.hubspot.com/pricing",22 "relevance": {23 "status": "relevant",24 "confidence": 1,25 "reasoning": "HubSpot added HubSpot Credits for Breeze AI agents to its Professional plan. No price changes were detected.",26 "summary": "HubSpot added HubSpot Credits for Breeze AI agents to its Professional plan. No price changes were detected.",27 "shortSummary": "Breeze AI Credits Added",28 "categories": [29 "feature_update",30 "pricing_strategy"31 ]32 },33 "websiteResponse": {34 "title": "HubSpot Pricing",35 "text": "Title: HubSpot Pricing\n\nURL Source: https://www.hubspot.com/pricing\n\nMarkdown Content:\n# Choose your plan\n\n## Professional\n\nEverything in Starter, plus marketing automation, custom reporting, omni-channel campaigns and HubSpot Credits for Breeze AI agents. …",36 "url": "https://www.hubspot.com/pricing",37 "author": null,38 "media": [],39 "metrics": null,40 "pageUrl": "https://www.hubspot.com/pricing",41 "changes": [42 {43 "type": "major",44 "title": "Breeze AI Credits Added",45 "description": "Added HubSpot Credits for Breeze AI agents to the Professional plan feature list.",46 "previous": "# Choose your plan\n\n## Professional\n\nEverything in Starter, plus marketing automation, custom reporting and omni-channel campaigns. …",47 "current": "# Choose your plan\n\n## Professional\n\nEverything in Starter, plus marketing automation, custom reporting, omni-channel campaigns and HubSpot Credits for Breeze AI agents. …",48 "categories": [49 "feature_update",50 "pricing_strategy"51 ]52 }53 ]54 },55 "metadata": {56 "title": "HubSpot Pricing",57 "text": "Title: HubSpot Pricing\n\nURL Source: https://www.hubspot.com/pricing\n\nMarkdown Content:\n# Choose your plan\n\n## Professional\n\nEverything in Starter, plus marketing automation, custom reporting, omni-channel campaigns and HubSpot Credits for Breeze AI agents. …",58 "url": "https://www.hubspot.com/pricing",59 "author": null,60 "media": [],61 "metrics": null,62 "pageUrl": "https://www.hubspot.com/pricing",63 "changes": [64 {65 "type": "major",66 "title": "Breeze AI Credits Added",67 "description": "Added HubSpot Credits for Breeze AI agents to the Professional plan feature list.",68 "previous": "# Choose your plan\n\n## Professional\n\nEverything in Starter, plus marketing automation, custom reporting and omni-channel campaigns. …",69 "current": "# Choose your plan\n\n## Professional\n\nEverything in Starter, plus marketing automation, custom reporting, omni-channel campaigns and HubSpot Credits for Breeze AI agents. …",70 "categories": [71 "feature_update",72 "pricing_strategy"73 ]74 }75 ]76 }77}
Long text values are shortened here with “ …”. Your endpoint gets the full text.
The item part every platform has
Every platform object starts with the same six keys (after platform, when the platform has one). They describe the item itself.
titlenull when the platform has none (most social posts and reviews).texturlnull when the platform gives none (most Google ads).author{ name: string, handle: string | null, url: string | null, imageUrl: string | null }. imageUrl is the author's photo, set for LinkedIn mentions when LinkedIn sends one, else null. LinkedIn photo links expire after a few weeks: download the photo if you keep it. author is null when unknown.media{ type: 'image' | 'video' | 'document', url: string }. An empty array when there is none. Media links can expire: download what you need.metrics{ [name]: number }, for example { "rating": 4 }. null when there are none. Social posts and mentions also repeat these numbers as named keys (likes, views, …).relevance
Signals judges most items against what you track. relevance tells you the result. It has three possible shapes, told apart by status.
statusconfidence0 to 1. How sure the judge is.reasoningsummarynull when the judge wrote none.shortSummarysummary. null when none.categories["Product update/launch"]. Free-form text, can be an empty array.statusconfidence0 to 1.reasoningIrrelevant items are never sent as events. You will not receive this shape. Handle it as unknown if you want to be safe.
statusunjudged is what you get for reviews, ads, job postings, Instagram posts and new competitors. They are delivered as found. News, LinkedIn, X, mentions and website changes are judged, so they carry relevant.
Removed events
The schema allows action: "removed" for every platform. Today only the job postings tracker sends it (jobs.removed, with the job's last known values). The other trackers drop the "gone" change before an event is made, and new competitor discovery reports arrivals only. Build your receiver to survive one anyway.
A removed event has the same common fields, with three differences (not on jobs.removed, which keeps its platform field, metadata and occurredAt):
occurredAtisnull.- The platform field is
null. metadataisnull.
1{2 "version": 1,3 "eventId": "8db42a9b-7414-40bc-9443-66ac1c6c2002",4 "eventType": "ads",5 "subEventType": "meta_ad",6 "action": "removed",7 "signalType": "ads.removed",8 "source": "ads",9 "orgId": "org_3KikADUjsyXrUJ4RJhWpwcp98Yf",10 "trackerId": "9aa429da-6540-4f14-a1d8-92526ccf42de",11 "runId": "c9cd89da-52ef-4803-8669-43a0414bc65f",12 "competitor": {13 "name": "HubSpot",14 "domain": "hubspot.com",15 "subjectKey": "google:AR10072600183532683265@-|meta:https://www.facebook.com/hubspot|linkedin:hubspot"16 },17 "occurredAt": null,18 "detectedAt": "2026-10-26T08:42:28.926Z",19 "sequence": 284,20 "itemKey": "ads-meta-1576853724126416",21 "relevance": {22 "status": "unjudged"23 },24 "adsResponse": null,25 "metadata": null26}
Versioning and compatibility
- An event's
versionis1. The run webhook'sversionis3, also in theSignals-Event-Versionheader. - Only a breaking change raises it: a key removed, renamed or changed to another type.
- Adding a key is not breaking. New keys can appear at any time. Ignore keys you do not know.
- Treat every enum (
eventType,subEventType,signalType,source,format,categories) as open. A new value can show up. Do not crash on it. - Do not rely on key order in your own parser. It is stable today, but JSON objects are unordered.