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.
Please note: beginning December 2024, the following changes will be made to the v1 Integration Timeline API.
You can now use the POST method to create events, however it's recommended to transition to the v3 Timeline Events API for the most up to date features. Learn more about this update on the HubSpot Developer Changelog.
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:
Check the prerequisites document for what you need to start using this API.
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
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.
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 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.
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
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:
Clicking on 'Show details' renders the details template:
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.
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.
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.
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.
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):
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 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.
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.
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"
}
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:
Clicking that link would open a modal window displaying the page set in iframeUri
:
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'
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:
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.
To add visual appeal to your timeline items, you'll want to add a custom icon.
This image file for this icon should:
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.
Once you set the icons, they will be shown next to all of the timeline events associated with this application: