There's a new version of the HubSpot API
We're also working on a new documentation website, you're invited to check it out and give us your feedback.
The Webhooks API allows you to subscribe to events happening in a HubSpot account with your integration installed. Rather than making an API call when an event happens in a connected account, HubSpot can send an HTTP request to an endpoint you configure. You can configure subscribed events in your app’s settings or using the endpoints detailed below. Webhooks can be more scalable than regularly polling for changes, especially for apps with a large install base.
Using the Webhooks API requires the following:
Webhooks are set up for a HubSpot app, not individual accounts. Any accounts that install your app (by going through the OAuth flow) will be subscribed to its webhook subscriptions.
In order to use webhooks, your app will need to be configured to require the crm.objects.contacts.read
scope. This scope must be set up before you will be able to create any any webhook subscriptions, either from your developer account in the app settings, or when using the Webhooks API to configure subscriptions. See the OAuth documentation for more details about scopes and setting up the authorization URL for your app.
If your app is already using webhooks, you will not be able to remove the crm.objects.contacts.read
scope until you remove all webhook subscriptions from your app.
Note: Webhook settings can be cached for up to five minutes. When making changes to the webhook URL, rate limits, or subscription settings, it may take up to five minutes to see your changes go into effect.
Before setting up your webhook subscriptions, you need to specify a URL to send those notifications to. Additionally, you can also tune the rate at which your endpoint can handle requests.
Setting this rate limit helps us send you notifications as fast as possible without putting too much load on your API.
If you set this limit too low, you may find that notifications timeout if there are too many notifications being sent to your API such that this limit is saturated for more than a few seconds. This will result in delays before getting notifications.
If you set this limit too high, you may saturate the resources available to your endpoint which could result in slow responses, notification delays, or result in your endpoint becoming unresponsive.
You can manage your URL and rate limit settings via your app’s configuration page in your developer account:
In the Apps dashboard, select the app that you'd like to set up webhooks for.
Select the Webhooks left nav item. This screen provides an interface you can use to set the target URL and event throttling limit.
These endpoints allow you to programmatically set webhook settings for an app. It is recommended that you use the UI to get your apps set up. You will need to use your developer API key when making requests to these endpoints.
The settings object has the following fields:
webhookUrl
- The URL where we'll send webhook notifications. Must be served over HTTPS.
maxConcurrentRequests
- The concurrency limit for this URL, as discussed in "Webhook URL and Concurrency Limit"
The following endpoint access the webhook settings current set up for your application, if any:
GET https://api.hubapi.com/webhooks/v1/{appId}/settings
The result will look something like:
{ "webhookUrl": "https://testing.com/webhook", "maxConcurrentRequests": 20 }
To modify these settings you can use the following endpoint:
PUT https://api.hubapi.com/webhooks/v1/{appId}/settings
With a request body like:
{ "webhookUrl": "https://testing.com/webhook-modified", "maxConcurrentRequests": 25 }
Validation:
webhookUrl
must be a valid URL served over HTTPS.
maxConcurrentRequests
must be a number greater than five.
Once you’ve set up your webhook URl and rate limit settings, you’ll need to create one or more subscriptions. Webhook subscriptions tell HubSpot which events your particular app would like to receive. We currently support the following subscription types:
Contact creations
Contact deletions
Privacy compliant contact deletions - see below for more details
Contact property changes
Company creations
Company deletions
Company property changes
Deal creations
Deal deletions
Deal property changes
A couple things to keep in mind about subscriptions:
For property change subscriptions, you will need to specify which property you want to be notified of. You can specify multiple property change subscriptions. If a customer's account doesn't have the property you specify in a subscription, you will not get any webhooks from that customer for that property.
Certain properties are not available for property change subscriptions. These properties are:
Contact properties:
days_to_close
recent_conversion_event_name
recent_conversion_date
first_conversion_event_name
first_conversion_date
num_unique_conversion_events
num_conversion_events
Deal properties:
num_associated_contacts
Subscriptions apply to all customers that have installed your integration. This means that you only need to specify what subscriptions you need once. Once you've enabled a subscription for an application, it will automatically start getting webhooks for all customers that have installed your application, and you will automatically start getting webhooks from any new customers that install your integration going forward.
There can be up to a five minute delay between creating or changing your subscriptions and those changes taking effect.
You can create webhook subscriptions via your developer account:
In the developer Apps dashboard, select the app that you'd like to send webhooks for.
Select the "Webhook subscriptions" nav item.
Click “Create subscription”
Select the object type (i.e. contact, company, deal) and event type (i.e. creation, change, deletion). Note: Deleted for privacy can only be selected when "contacts" is the only selected object type.
(Optional) For property change events, select the property in question. Note: You can also manually enter property names, allowing you to use custom properties.
NOTE: New subscriptions are created in the paused state. You will need to activate the subscription for webhooks to send.
These endpoints allow you to programmatically create subscriptions. There is nothing in these endpoints that you cannot do via the UI, and the UI is the preferred way to set up your app. You will need to use your developer API key when making requests to these endpoints.
A subscription object has the following fields:
id
- A number representing the unique ID of a subscription.
createdAt
- When this subscription was created, this is a millisecond timestamp.
createdBy
- The userId of the user that created this subscription.
enabled
- Whether or not this subscription is currently active and triggering notifications.
subscriptionDetails
- This describes what types of events this subscription is listening for
subscriptionType
- A string representing what type of subscription this is--as defined in 'Subscription Types` below.
propertyName
- Only needed for property-change types. The name of the property to listen for changes on. This can only be a single property name.
The subscriptionType
property can be one of the following values:
contact.creation
- To get notified if any contact is created in a customer's account.contact.deletion
- To get notified if any contact is deleted in a customer's account.contact.privacyDeletion
- To get notified if a contact is deleted for privacy compliance reasons. See below for more details.contact.propertyChange
- To get notified if a specified property is changed for any contact in a customer's account.company.creation
- To get notified if any company is created in a customer's account.company.deletion
- To get notified if any company is deleted in a customer's account.company.propertyChange
- To get notified if a specified property is changed for any company in a customer's account.deal.creation
- To get notified if any deal is created in a customer's account.deal.deletion
- To get notified if any deal is deleted in a customer's account.deal.propertyChange
- To get notified if a specified property is changed for any deal in a customer's account.ticket.creation
- To get notified if any ticket is created in a customer's account.ticket.deletion
- To get notified if any ticket is deleted in a customer's account.ticket.propertyChange
- To get notified if a specific property is changed for any ticket in a customer's account.product.creation
- To get notified if any product is created in a customer's account.product.deletion
- To get notified if any product is deleted in a customer's account.product.propertyChange
- To get notified if a specified property is changed for any product in a customer's account. line_item.creation
- To get notified if any line item is created in a customer's account.line_item.deletion
- To get notified if any line item is deleted in a customer's account.line_item.propertyChange
- To get notified if a specified property is changed for any line item in a customer's account. conversation.creation
- To get notified if a new thread is created in an account.conversation.deletion
- To get notified if a thread is archived or soft-deleted in an account.conversation.privacyDeletion
- To get notified if a thread is permanently deleted in an account.conversation.propertyChange
- To get notified if a property on a thread has been changed.conversation.newMessage
- To get notified if a new message on a thread has been received. To retrieve the list of subscriptions:
GET https://api.hubapi.com/webhooks/v1/{appId}/subscriptions
The response will be an array of objects representing your subscriptions. Each object will include information on the subscription like the ID, create date, type, and whether or not it’s currently enabled. Here’s what an example response would look like:
[ { "id": 25, "createdAt": 1461704185000, "createdBy": 529872, "subscriptionDetails": { "subscriptionType": "contact.propertyChange", "propertyName": "lifecyclestage" }, "enabled": true }, { "id": 59, "createdAt": 1462388498000, "createdBy": 529872, "subscriptionDetails": { "subscriptionType": "company.creation" }, "enabled": false }, { "id": 108, "createdAt": 1463423132000, "createdBy": 529872, "subscriptionDetails": { "subscriptionType": "deal.creation" }, "enabled": true } ]
To create new subscriptions:
POST https://api.hubapi.com/webhooks/v1/{appId}/subscriptions
With a request body like:
{ "subscriptionDetails": { "subscriptionType": "company.propertyChange", "propertyName": "companyname" }, "enabled": false }
Where the fields in this request body match those defined in "Subscription Fields". However, with this endpoint you cannot specify id
, createdAt
, or createdBy
, as those fields are set automatically.
Validation:
subscriptionType
must be a valid subscription type as defined in the above section on "Subscription Types".
propertyName
must be a valid property name. If a customer has no property defined that matches this value, then this subscription will not result in any notifications.
enabled
must be true
or false
.
You can only update the enabled flag of a subscription. To do so you can use the following endpoint:
PUT https://api.hubapi.com/webhooks/v1/{appId}/subscriptions/{subscriptionId}
Request body:
{ "enabled" : false }
To delete a subscription you can call the following endpoint:
DELETE https://api.hubapi.com/webhooks/v1/{appId}/subscriptions/{subscriptionId}
The endpoint at the URL you specify in webhooks settings will receive requests like the following:
Method type: POST
Headers:
Content-Type: Application/JsonExample request body:
[ { "objectId": 1246965, "propertyName": "lifecyclestage", "propertyValue": "subscriber", "changeSource": "ACADEMY", "eventId": 3816279340, "subscriptionId": 25, "portalId": 33, "appId": 1160452, "occurredAt": 1462216307945, "subscriptionType": "contact.propertyChange", "attemptNumber": 0 }, { "objectId": 1246978, "changeSource": "IMPORT", "eventId": 3816279480, "subscriptionId": 22, "portalId": 33, "appId": 1160452, "occurredAt": 1462216307945, "subscriptionType": "contact.creation", "attemptNumber": 0 } ]
Request fields:
objectId
: The ID of the object that was created/changed/deleted. For contacts this is the vid; for companies, the companyId; and for deals the dealId.
propertyName
: This is only sent when the notification is for a property change. This is the name of the property that was changed
propertyValue
: This is only sent when the notification is for a property change. This is the new value that was set for this property that triggered this notification.
changeSource
: The source of this change. Can be any of the change sources that you find on contact property histories.
eventId
: The unique ID of the event that triggered this notification.
subscriptionId
: The ID of the subscription that caused us to send you a notification of this event.
portalId
: The customer's portalId that this event came from.
appId
: The ID of your application. (In case you have multiple applications pointing to the same webhook URL.)
occurredAt
: When this event occurred, as a millisecond timestamp.
subscriptionType
: The type of event this notification is for. See the list of subscription types in the above section on "Subscription Types".
attemptNumber
: Which attempt this is to notify your service of this event (starting at 0). If your service times-out or throws an error as described in "Retries" below, we will attempt to send the notification to your service again.
NOTE ON BATCHING: As shown above, you will receive multiple notifications in a single request. The batch size can vary, but will be under 100 notifications. We will send multiple notifications only when a lot of events have occurred within a short period of time. For example, if you've subscribed to new contacts and a customer imports a large number of contacts, we will send you the notifications for these imported contacts in batches and not one-per-request.
NOTE ON ORDER: We do not guarantee that you get these notifications in the order they occurred. Please use the occurredAt
property for each notification to determine when the notification occurred.
NOTE ON UNIQUENESS: We do not guarantee that you will only get a single notification for an event. Though this should be rare, it is possible that we will send you the same notification multiple times.
HubSpot users have the ability to permanently delete a contact record to comply with privacy laws. Please see the following help article for more details on this feature: https://knowledge.hubspot.com/articles/kcs_article/contacts/how-do-i-perform-a-gdpr-compliant-delete-in-hubspot
You can subscribe to the contact.privacyDeletion
subscription type to receive webhook notifications when a user performs a privacy compliant contact deletion.
Note: Webhooks use the v1 version of the X-HubSpot-Signature header. Please see this page for more details on validating this version of the signature, and this page for more details about validating requests in general.
To ensure that the requests you're getting at your webhook endpoint are actually coming from HubSpot, we populate a X-HubSpot-Signature
header with a SHA-256 hash of the concatenation of the app-secret for your application and the request body we're sending.
To verify this signature, concatenate the app secret of your application and the un-parsed request body of the request you're handling, and get a SHA-256 hash of the result. Compare the resulting hash with the value of the X-HubSpot-Signature
. If these values match, then this verifies that this request came from HubSpot. (Or someone else who knows your application secret. It's important to keep this value secret.) If these values do not match, than this request may have been tampered with in-transit or someone may be spoofing webhook notifications to your endpoint.
If your service has problems handling notifications at any time, we will attempt to re-send failed notifications up to 10 times.
We will retry in the following cases:
Connection failed - If we cannot open an http connection to the provided webhook URLNotifications will be retried up to 10 times. These retries will be spread out over the next 24 hours, with varying delays between requests. Individual notifications will have some randomization applied, to prevent a large number of concurrent failures from being retried at the exact same time.
You can create a maximum of 1000 subscriptions per application. If you attempt to create more you will receive a 400 bad request in return with the following body:
{ "status": "error", "message": "Couldn't create another subscription. You've reached the maximum number allowed per application (1000).", "correlationId": "2c9beb86-387b-4ff6-96f7-dbb486c00a95", "requestId": "919c4c84f66769e53b2c5713d192fca7" }