HubSpot
Run a workflow on CRM events: a contact or company is created, or a property you watch changes. Each notification becomes the workflow's input — enrich the new contact, sync the company, react to a lifecycle-stage change.
For behavior shared by every provider (testing, deduplication), see the webhook triggers reference.
Prerequisites
Setting up a HubSpot trigger requires a connected HubSpot account in Cotera. Without one, install fails with a credentials error.
HubSpot only exposes webhooks through a legacy app, so you'll need one to point at Cotera. Create it under Settings → Integrations → Legacy Apps → Create Legacy App. The legacy app is also where you grant the CRM scopes the subscriptions need — a contact.* subscription requires contact read access, company.* requires company read access.
Setup
HubSpot allows only one webhook delivery URL per app, so Cotera doesn't create subscriptions over the API — you register the URL once on your legacy app:
- Add a From an app trigger and pick HubSpot. Cotera gives you a single delivery URL shared by all your org's HubSpot triggers.
- In HubSpot, create a legacy app under Settings → Integrations → Legacy Apps → Create Legacy App (or open an existing one), open its Webhooks settings, and set the target URL to Cotera's URL.
- Grant the app the CRM scopes for the objects you're subscribing to (contacts, companies), then subscribe to the event types you want (contact creation, company property change, and so on).
- Back in Cotera, add a trigger per event you care about — for property changes, set the property to watch.
All of your org's HubSpot events arrive on that one shared endpoint; Cotera routes each notification to the triggers that match it.
Events
| Event key | Fires when | Config |
|---|---|---|
contact.created | A new contact is created | Optional property conditions |
company.created | A new company is created | Optional property conditions |
contact.property_changed | A watched property changes on a contact | propertyName (required) |
company.property_changed | A watched property changes on a company | propertyName (required) |
Property-change subscriptions are scoped to one property. Because every property change lands on the shared endpoint, Cotera gates each trigger to its configured propertyName (for example lifecyclestage) — so a contact-property trigger fires only for the property it watches.
Payload
HubSpot delivers notifications in a batch array; Cotera splits the batch and runs your workflow once per matching notification, with that single notification as the input:
{
"objectId": 123456,
"propertyName": "lifecyclestage",
"propertyValue": "customer",
"changeSource": "CRM_UI",
"eventId": 3816279482,
"subscriptionId": 61,
"portalId": 33,
"appId": 1160452,
"occurredAt": 1462216307947,
"eventType": "contact.propertyChange",
"subscriptionType": "contact.propertyChange",
"attemptNumber": 0
}
| Field | Description |
|---|---|
objectId | The CRM object (contact or company) the event is about. |
propertyName / propertyValue | The changed property and its new value (property-change events only). |
subscriptionType | HubSpot's event type, e.g. contact.creation or company.propertyChange. |
portalId | The HubSpot account (portal) the event came from. |
occurredAt | When the event happened, as a Unix-millisecond timestamp. |
eventId | HubSpot's unique event id, used to deduplicate retries. |
Creation events (contact.created, company.created) carry the same shape without the propertyName / propertyValue fields.
Signature verification
HubSpot signs each delivery with its v3 scheme: a base64 HMAC-SHA256 over the request method, URL, body, and timestamp, sent in the X-HubSpot-Signature-v3 header alongside an X-HubSpot-Request-Timestamp. Cotera verifies it — including a timestamp-freshness check to reject replays — using the HubSpot app's client secret, so there's no per-trigger secret for you to manage. Deliveries that fail verification are rejected before your workflow runs.