There's a new version of the HubSpot API

As of November 30, 2022, HubSpot API keys are no longer a supported authentication method for accessing HubSpot APIs. Instead, you should use a private app access token or OAuth to authenticate API calls. Learn more about this change and how to migrate an API key integration to use a private app instead.

Webhooks API Overview

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:

  • That you set up a HubSpot app to use webhooks by subscribing to the events you want to be notified about, and by specifying a URL to send those notifications. See the prerequisites documentation for more details about creating an app.
  • That you deploy a publicly available, secure (HTTPS) endpoint for that URL that can handle the webhook payloads specified in this documentation.

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.

Scopes

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.

Webhooks setup

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.

Webhook URL and rate limits

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.

Managing via the UI

You can manage your URL and rate limit settings via your app’s configuration page in your developer account:

  1. In the Apps dashboard, select the app that you'd like to set up webhooks for.

    app_id_list
  2. Select the Webhooks left nav item. This screen provides an interface you can use to set the target URL and event throttling limit.

    webhook_settings

Managing via the API

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.

Settings fields

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"

Viewing settings

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
}
Updating settings

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.

Webhook subscriptions

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.

Managing subscriptions via the UI

You can create webhook subscriptions via your developer account:

  1. In the developer Apps dashboard, select the app that you'd like to send webhooks for.

  2. Select the "Webhook subscriptions" nav item.

  3. Click “Create subscription”

    webhook_settings
  4. 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.

    create_webhook_subscription
  5. (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.

    activate_subscription

Managing subscriptions via the API

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.

Subscription fields

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.

Subscription types

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. 

Get subscriptions

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
  }
]
Create a new subscription

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.


Update a subscription

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 }
Delete a subscription

To delete a subscription you can call the following endpoint:

DELETE https://api.hubapi.com/webhooks/v1/{appId}/subscriptions/{subscriptionId}

Webhooks payloads

The endpoint at the URL you specify in webhooks settings will receive requests like the following:

Method type: POST

Headers:

Content-Type: Application/Json
X-HubSpot-Signature: {A hash of the app secret and request body, see below for more details.}


Example 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.

Handling privacy compliant contact deletions

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: privacy deletion notifications have some special behavior:
A privacy deletion event will also trigger the normal contact.delete event, so you will receive two notifications if you are subscribed to both events.
These notifications are not guaranteed to be sent in any order, or in the same batch of messages. You will need to use the objectId to match the separate messages.

Security

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.

Retries

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 URL
Timeout - If your service takes longer than 5 seconds to send back a response to a batch of notifications
Error codes - If your service responds with any HTTP status code (4xx or 5xx)

Notifications 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.

Limits

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"
}

 

Docs for this section or API