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.

Timeline API Overview

Note, a newer version of this API is now available. In the UI, we’ve renamed ‘event type’ to ‘event template’ and ‘event properties’ to ‘event tokens’.

The Timeline API allows integrators to create custom timeline events that will show up in the timeline of contacts, companies, or deals. You'll find multiple use cases for this API in the sections below.

This page will walk you through setting up event types and creating events, like this example of a custom webinar event:
event_expanded.png

Prerequisites

Check the prerequisites document for what you need to start using this API.

1. Creating an event type

Event types describe an action that your app will add to the timeline of a contact, company, or deal record in HubSpot. The action should be something like viewing a video, registering for a webinar, filling out a survey, etc. A single app can define multiple event types.

Event types will be created for contacts by default, but they can be created for companies and deals as well. See creating a timeline event type for more details.

Each event type contains its own set of properties and templates. You can use events created for contacts as criteria when creating new contact lists or workflows, such as: 'create a list of all contacts that have a Video Like where the video name contains XYZ,' where your event type is named "Video Like" and has an event property named "video name." You must create an event type before you can create events.

Note: You can create up to 750 timeline event types per application

Using the API to create an event type

For this example, we'll create a new 'Example Webinar Registration' event type. For authentication, we'll use your developer API key.

curl -X POST -H "Content-Type: application/json" -d '
{ 
    "name" : "Example event type", 
    "applicationId": <<appId>>
}' \
'https://api.hubapi.com/integrations/v1/<<appId>>/timeline/event-types?hapikey=<<developerHapikey>>'

Be sure to replace <<appId>> with your App Id, which can be found in both the 'My Apps' list and the app details screen in your developer account. You'll also need to replace <<developerHapikey>>, which you can find on the 'My Apps' screen in the 'developer API key' section.

The properties headerTemplate and detailTemplate could also be provided here. See Section 3: Defining Templates.

This POST request will return the full saved definition of the event type. Be sure to note the id property in this response. This is the event type ID, which you'll need to add properties to this event type.

You can see all event types defined for an app via this GET command:

curl -X GET 'https://api.hubapi.com/integrations/v1/<<appId>>/timeline/event-types?hapikey=<<developerHapikey>>'

The GET request will also return the event type IDs.

2. Defining event properties

Once you've defined an event type, it's likely that you'll want to define properties for it as well. Event type properties allow you to attach custom data to events that can be displayed in the timeline, or for contacts, used for list segmentation and automation.

Please note: company and deal events cannot be used in list segmentation or automation.

Using the API to create event properties

Using the event type Id from the event type created in the previous step, we'll add a couple properties to identify which webinar our contacts registered for.

curl -X POST -H "Content-Type: application/json" -d '
{
    "name" : "webinarName",
    "label" : "Webinar Name",
    "propertyType": "String"
}' \
'https://api.hubapi.com/integrations/v1/<<appId>>/timeline/event-types/<<eventTypeId>>/properties?hapikey=<<developerHapikey>>'

curl -X POST -H "Content-Type: application/json" -d '
{
    "name" : "webinarId",
    "label" : "Webinar Id",
    "propertyType": "String"
}' \
'https://api.hubapi.com/integrations/v1/<<appId>>/timeline/event-types/<<eventTypeId>>/properties?hapikey=<<developerHapikey>>'

Note: You can create up to 500 properties per timeline event type

Similarly, a GET will return all properties defined on an event type:

curl -X GET -H "Content-Type: application/json" 'https://api.hubapi.com/integrations/v1/<<appId>>/timeline/event-types/<<eventTypeId>>/properties?hapikey=<<developerHapikey>>'

The supported property types are:

  • String
  • Numeric
  • Enumeration -- One of a set of options. See creating an event type property for details.
  • Date -- All dates must be in milliseconds in Unix time.

Note: Event properties cannot be named log or lookup. These tokens are reserved as helpers by the library used to render events in-app, Handlebars.js. For more information, check out the Handlebars.js docs here.

3. Defining templates

Templates define how to display an event in a record's timeline. We accept two templates: the header template, which should be a one-line description of the event; and the details template, which is the drill-down view of the event (examples below). The Timeline API allows you to specify Markdown documents with Handlebars templates for the details template.

The event properties are passed as data to the templates. Using our example, you can reference the 'webinarName' property in the template by using {{webinarName}}.

The extraData of an event (discussed below in Understanding extraData) can only be referenced in the details template.

See this page for more details on template rendering: https://developers.hubspot.com/docs/methods/timeline/timeline-template-rendering

Using the API to define the templates

Templates can be defined on the event type via the event type API. For example, we can add templates to our 'Example Webinar Registration' by modifying that event-type with a PUT:

curl -X PUT -H "Content-Type: application/json" -d '
{
    "id": 3,
    "applicationId": <<appId>>,
    "name": "Example event type",
    "headerTemplate": "Registered for [{{webinarName}}](https://mywebinarsystem/webinar/{webinarId})",
    "detailTemplate": "Registration occurred at {{#formatDate timestamp}}{{/formatDate}}"
}' \
'https://api.hubapi.com/integrations/v1/<<appId>>/timeline/event-types/<<eventTypeId>>?hapikey=<<developerHapikey>>'

Note the use of the #formatDate directive. This is a directive we have defined to allow for user-friendly date formatting.

Once an event is created for a contact with this event type (see 'Creating an event' below) the following will show up in that contact's timeline:

event_collapsed.png

Clicking on 'Show details' renders the details template:

event_expanded.png

To set the icon that is displayed next to the events, see Setting up a Custom Icon below.

The 'Example App Name' text above is the name of the application. In the CRM timeline, events are filterable by application.

4. Creating an event type in the UI

In addition to using the API to create and manage timeline event types, you can also manage event types in your HubSpot developer account.

When viewing the settings for your app, navigate to Timeline events using the sidebar navigation. Use the 'Create event template’ button to create a new event type for this app. If you have previously created any event types, you'll see them displayed as well.

Timeline_template

When creating a new event type, you'll start with a draft of your new event type. Set the record type and the detail and header templates for the event, and hit create to create your new event type.

Timeline_new_template

You can set any properties that you want to use with the event type from the Data tab when creating or editing your event type.

 

Timeline_example_template

5. Creating an event

Now that an event type has been set up with properties and templates, we're ready to create events for our customers' contacts, companies, and deals. The examples below assume we're working with the contacts event type created above. An example PUT to create an event is below:

curl -X PUT -H "Content-Type: application/json" \
-H "Authorization: Bearer CJSP5qf1KhICAQEYs-gDIIGOBii1hQIyGQAf3xBKmlwHjX7OIpuIFEavB2-qYAGQsF4" \
-d '
{
  "id": "001-001001",
  "eventTypeId": <<eventTypeId>>,
  "webinarName": "A Test Webinar",
  "webinarId": "001001",
  "email": "a.test.contact@email.com"
}' \
'https://api.hubapi.com/integrations/v1/<<applicationId>>/timeline/event'

This generates an event on a.test.contact@email.com's timeline like so (assuming the templates in 'Defining Templates' above):

event_collapsed.png

Note that you can't use the developer API key to create events. This is because the developer API key is only for setting up event-types from your development account. To create an event for a HubSpot account, it will need to grant access to your application via OAuth. You can use our OAuth flow to get an access token and then use it to add events to the account's contacts.

The event ID

The id property in this request can be any string. This is meant to be generic enough to fit whatever ID scheme you use to keep track of these events in your system. The PUT requests are idempotent on this id, so another PUT with the same id will not create a new event, but will update the existing event. This id must be unique across all accounts using the integration.

Setting the event timestamp

The timestamp of the event determines where in the timeline the event will appear. By default, the timestamp of the event is the time that the PUT command is sent. You can customize the event time by providing it in the request body in a timestamp property:

curl -X PUT -H "Content-Type: application/json" \
-H "Authorization: Bearer CJSP5qf1KhICAQEYs-gDIIGOBii1hQIyGQAf3xBKmlwHjX7OIpuIFEavB2-qYAGQsF4" \
-d '
{
  "id": "001-001001",
  "eventTypeId": <<eventTypeId>>,
  "webinarName": "A Test Webinar",
  "webinarId": "001001",
  "email": "a.test.contact@email.com",
  "timestamp": 1388534400000
}' \
'https://api.hubapi.com/integrations/v1/<<applicationId>>/timeline/event'

This is preferred if you know the exact time an action occurred. In this example, if we have the timestamp for this webinar registration, we should provide it in this PUT.

Times must be in milliseconds epoch time.

6. Associating an event with a CRM object

In order to create an event, you must be able to associate the event with a contact, company, or deal in the customer's account.

In the examples above, we're working with an event type that has the objectType set to CONTACT, and we use email to associate theevent with a contact in the user's account. Email addresses must be unique for contacts in HubSpot, so if there is an existing contact with the provided email, that contact would be updated. However, if no contact exists under the email address you provide, a new contact will be created. By default, this new contact will only have the email contact property provided. See the section below about 'Stamping event data onto contact properties' to learn how to add additional data to contact properties. The example data here uses email (as do the examples above this section):

{
  "id": "001-001001",
  "eventTypeId": <<eventTypeId>>,
  "webinarName": "A Test Webinar",
  "webinarId": "001001",
  "email": "a.test.contact@email.com"
}

If you are working with known contacts, you can also use the contact vid to associate the event. In those cases, you would use objectId in the request JSON. Note that this must the be the vid of an existing contact, as you will not be able to create new contacts using objectId. This example uses the objectId instead of email:

{
  "id": "001-001001",
  "eventTypeId": <<eventTypeId>>,
  "webinarName": "A Test Webinar",
  "webinarId": "001001",
  "objectId": 1234
}

You can also associate an event with a contact by usertoken, or utk. The usertoken is used by the HubSpot tracking code to track visitors, and is stored in the hubspotutk cookie. Use the utk parameter to associate an event with a contact by usertoken. Note: It is not possible to associate events with anonymous visitors using the usertoken, so if the event is associated using only the utk, and the provided usertoken is not already associated with a contact, no new contact would be created and the event would not be visible in HubSpot. However, the event would appear in the timeline if a new contact was associated with the usertoken through another means (usually through a form submission including the hutk, or through the identify method of the Tracking Code API). For this reason, we recommend including the email in addition to the utk to make sure that the event gets associated with a new or existing contact.

If you're working with an event type for contacts, it's possible to include multiple identification parameters with the event, so any combination of the email, objectId, and utk parameters may be included. If multiple parameters are included, the objectId (vid) will have the highest priority when determining which contact to associate with the event, followed by utk, with email being the lowest priority. This means that you can update the email address of an existing record by including a new email address in the email parameter with the vid of a known record in objectId. This example uses the email address and usertoken together:

{
  "id": "001-001001",
  "eventTypeId": <<eventTypeId>>,
  "webinarName": "A Test Webinar",
  "webinarId": "001001",
  "email": "a.test.contact@email.com",
  "utk": "89b5afb740d41f4cd6651ac5237edf09"
}

In addition to working with contacts, it's also possible to create event types for companies and deals. For those event types, you must use objectId to associate the event with the company or deal. For companies, the objectId must be set to the companyId of the company you want to associate the event with, and for deals you would set the objectId to the dealId of the deal record.

In the example below, assuming the event type was set to the COMPANY objectType, this event would be associate with the company record with companyId 528253914:

{
  "id": "002-001002",
  "eventTypeId": <<eventTypeId>>,
  "webinarName": "A Test Webinar",
  "webinarId": "001001",
  "objectId": "528253914"
}

7. Timeline extensions

The timeline extensions feature can be used to display data from an external system using an iFrame. When included, the event will display a link that will open a modal window displaying the iFrame contents when clicked. The details for the iFrame are set in the timelineIFrame field, which is an object containing the following fields:

  • linkLabel - The text used to display the link that will display the IFrame.
  • iframeLabel - The label of the modal window that displays the IFrame contents. 
  • iframeUri - The URI of the IFrame contents.
  • width - The width of the modal window.
  • height - The height of the modal window.

For example, using this data for an event:

{
  "id": "1501696173424",
  "eventTypeId": 18568,
  "webinarName": "A Test Webinar",
  "webinarId": "001001",
  "email": "a.test.contact@email.com",
  "timelineIFrame": {
    "linkLabel": "View external data",
    "iframeLabel": "Example iframe",
    "iframeUri": "https://www.example.com",
    "width": 800,
    "height": 300
  }
}

Would create this event, with the "View external data" link:

external_data_link.png

Clicking that link would open a modal window displaying the page set in iframeUri:

iframe_modal.png

8. Stamping event data onto CRM object properties

In many cases, you'll want to modify the properties for the contacts, companies, or deals to which you're adding events. This commonly happens in cases where adding the event will actually create a contact--you'll likely want to update the first and last name properties on the contact so that you don't just create a contact with only an email address and an event.

You can stamp data onto the associated object from an event by mapping your event properties to contact, company, or deal properties.

Consider this PUT command for defining an event property, note the objectProperty field:

curl -X POST -H "Content-Type: application/json" -d '
{
    "name" : "companyName",
    "label" : "Company Name",
    "propertyType": "String",
    "objectProperty": "company"
}' \
'https://api.hubapi.com/integrations/v1/<<applicationId>>/timeline/event-types/<<eventTypeId>>/properties?hapikey=<<developerHapikey>>'

This uses objectProperty to map this event property to the company contact property. This means that when we create a new event that specifies a 'companyName', the 'company' property of the associated contact will also be set.

For example, creating an event like this:

curl -X PUT -H "Content-Type: application/json" \
-H "Authorization: Bearer CJSP5qf1KhICAQEYs-gDIIGOBii1hQIyGQAf3xBKmlwHjX7OIpuIFEavB2-qYAGQsF4" \
-d '
{
  "id": "001-001002",
  "eventTypeId": <<eventTypeId>>,
  "webinarName": "A Test Webinar With Company",
  "webinarId": "001001",
  "companyName": "TestCo",
  "email": "a.test.contact@email.com"
}' \
'https://api.hubapi.com/integrations/v1/<<applicationId>>/timeline/event'

Causes the 'company' property to be set on the contact with the email address 'a.test.contact@email.com'

set_property.png

Notes:
  • If an event property is stamped to a custom property, and that custom property is not present for a HubSpot account, then the value will still be set for the event, but it will be ignored for the object that the event is created for.
  • Custom properties can only be mapped for contacts. Other objects will only allow you to map default properties.

9. Understanding extraData

You may need to add detail data to an event that doesn't fit the simple property-value structure used by the event type properties. You may need to add a list or some hierarchical breakdown to an integration event. This is where extraData comes in.

You can add a extraData attribute to an events JSON body. The value of this extraData can be any valid JSON. For example:

curl -X PUT -H "Content-Type: application/json" \
-H "Authorization: Bearer CJSP5qf1KhICAQEYs-gDIIGOBii1hQIyGQAf3xBKmlwHjX7OIpuIFEavB2-qYAGQsF4" \
-d '
{
    "id": "001-001002",
    "eventTypeId": <<eventTypeId>>,
    "webinarName": "A Test Webinar With Extra Data",
    "webinarId": "001001",
    "email": "a.test.contact@email.com",
    "extraData": {
      "pollData": [
        { "question": "How excited are you for this webinar?", "answer":"Quite!" },
        { "question": "How frequently do you use our product?", "answer":"Daily" }
      ],
      "coWorkers": [
        { "name": "Joe Coworker", "email":"jmcoworker@testco.com" },
        { "name": "Jane Coworker", "email":"jcoworker@testco.com" }
      ]
  }
}' \
'https://api.hubapi.com/integrations/v1/<<applicationId>>/timeline/event'

An example of using extraData in a details template:

Registration occurred at {{#formatDate timestamp}}{{/formatDate}}

#### Poll Questions
{{#each extraData.pollData}}
  **{{question}}**: {{answer}}
{{/each}}

#### Co-Workers
{{#each extraData.coWorkers}}
  * {{name}}
{{/each}}

Which will result in a timeline event that looks like:

extra_data.png

Note: The extraData attribute can only be referenced in the details template for an event. It cannot be used in either the header template or in list segmentation.

10. Setting up a custom icon

To add visual appeal to your timeline items, you'll want to add a custom icon.

This image file for this icon should:

  • Have roughly square dimensions
  • Have a transparent background
  • Have the content in the center of the icon
  • Be able to size down to 30x30 pixels
  • Have a file size of 5MB or less

To set the icon used for timeline events, go to the Timeline events menu item. Click on the placeholder image or the existing icon to set or update the icon.
timeline_icon

Once you set the icons, they will be shown next to all of the timeline events associated with this application:

timeline_icon.png

Docs for this section or API