HubSpot APIs
Configuring an integration between Redpoint Data Management (RPDM) and HubSpot APIs allows you to create and update Customer Relationship Management (CRM) records. This document contains instructions for creating a contact list, mapping its columns to HubSpot fields, and uploading it to HubSpot CRM.
Basic requirements
Each task contained in this document has the following requirements:
A HubSpot private app: https://developers.hubspot.com/docs/platform/create-private-apps-with-projects.
The app must have the
crm.import
scope.The access token for the app.
Basic authentication flow
Authentication only requires your app’s access token. This access token is set as the Bearer
via the Authorization
header on all API calls.
Create a contact list
HubSpot does not have a standard format for the contact list files uploaded to the server. Instead, their API allows the user to map columns from the contact list file to fields within HubSpot. All examples in this document will use a simple contact list CSV with three columns: First Name, Last Name, and Email. HubSpot supports both CSVs and Excel files.
Upload contact list to HubSpot
HubSpot provides a simple one-step process for uploading the contact list file to their API.
Endpoint: https://api.hubapi.com/crm/v3/imports/
Method: POST
Header:
Field | Data Type | Description |
---|---|---|
|
| (Required)
|
|
| (Required)
|
Parameters:
The following parameters must be included in the request body in the form-data
format.
Field | Data Type | Description |
---|---|---|
|
| (Required) JSON formatted metadata about the import. This includes a name for the import and the column mappings for each file. See below for more on the required format. |
|
| (Required) Supports CSV and Excel files. The file type must match the definition in the |
RPDM caveat:
The requirement for multipart/form-data
and a file upload presents a difficulty for RPDM. The request must be created manually using a Calculate
function after consuming the customer file. We must define a form-data boundary, the request content type, including the boundary, and the request itself. See below:
Field: boundary
Expression:
"0ebd3"
Field: contentType
Expression:
"multipart/form-data; boundary=" + boundary
Field: request
Expression:
"--" + boundary + "
Content-Disposition: form-data; name=\"files\"; filename=\"${importFileName}\"
Content-Type: text/csv
"+ DecodeTextBytes(contents,"UTF8") +
"--" + boundary + "
Content-Disposition:form-data;name=\"importRequest\"
" + importRequestJSON + "
--" + boundary + "--"
When run through an RPDM web service with the request field assigned to the Body
field, this will produce a payload that contains contents of the file located at filename
.
Request:
POST /crm/v3/imports/ HTTP/1.1
Host: api.hubapi.com:443
Authorization: Bearer pat-na1-fe552659-e84e-47e6-bd69-f3f45be0a952
Content-Type: multipart/form-data; boundary=0ebd3
Content-Length: 1193
--0ebd3
Content-Disposition: form-data; name="files"; filename="import.csv"
Content-Type: text/csv
First Name,Last Name,Email
Johnny,Doe,johndoe@redpointglobal.com
Jane,Doe,janedoe@redpointglobal.com
--0ebd3
Content-Disposition:form-data;name="importRequest"
{
"name": "November Marketing Event Leads",
"importOperations": {
"0-1": "UPSERT"
},
"dateFormat": "DAY_MONTH_YEAR",
"createContactListFromImport": true,
"files": [
{
"fileName": "import.csv",
"fileFormat": "CSV",
"fileImportPage": {
"hasHeader": true,
"columnMappings": [
{
"columnObjectTypeId": "0-1",
"columnName": "First Name",
"propertyName": "firstname"
},
{
"columnObjectTypeId": "0-1",
"columnName": "Last Name",
"propertyName": "lastname"
},
{
"columnObjectTypeId": "0-1",
"columnName": "Email",
"propertyName": "email",
"columnType": "HUBSPOT_ALTERNATE_ID"
}
]
}
}
]
}
--0ebd3--
Response:
{
"state": "STARTED",
"importRequestJson": {
"portalId": 45915953,
"language": "en-us",
"numberFormatLocale": {
"language": "en",
"country": "US"
},
"dateFormat": "DAY_MONTH_YEAR",
"timeZone": "Z",
"userId": null,
"importOperations": {
"0-1": "UPSERT"
},
"optOutBusinessUnitId": null,
"invalidPropertyValues": [],
"importName": "November Marketing Event Leads",
"fileImports": [{
"columnDelimiter": null,
"estimatedLineCount": 3,
"fileFormat": "CSV",
"charset": "UTF-8",
"fileId": 165399500647,
"pages": [{
"columnMappings": [{
"columnObjectType": null,
"columnObjectTypeId": "0-1",
"toColumnObjectTypeId": null,
"engagementType": null,
"columnName": "First Name",
"propertyName": "firstname",
"ignored": false,
"idColumnType": null,
"columnType": "STANDARD",
"foreignKeyType": null,
"associationLabels": null,
"associationIdentifierColumn": false,
"skipIfKnownColumn": false,
"marketingEventSubmissionType": null
}, {
"columnObjectType": null,
"columnObjectTypeId": "0-1",
"toColumnObjectTypeId": null,
"engagementType": null,
"columnName": "Last Name",
"propertyName": "lastname",
"ignored": false,
"idColumnType": null,
"columnType": "STANDARD",
"foreignKeyType": null,
"associationLabels": null,
"associationIdentifierColumn": false,
"skipIfKnownColumn": false,
"marketingEventSubmissionType": null
}, {
"columnObjectType": null,
"columnObjectTypeId": "0-1",
"toColumnObjectTypeId": null,
"engagementType": null,
"columnName": "Email",
"propertyName": "email",
"ignored": false,
"idColumnType": null,
"columnType": "HUBSPOT_ALTERNATE_ID",
"foreignKeyType": null,
"associationLabels": null,
"associationIdentifierColumn": false,
"skipIfKnownColumn": false,
"marketingEventSubmissionType": null
}],
"hasHeader": true
}]
}],
"createContactListFromImport": true,
"source": "API",
"importNotificationType": "IMPORT_COMPLETED",
"marketableContactImport": false,
"skipIfKnownImport": false,
"marketingEventObjectId": null,
"parentChildCompanyImport": false
},
"importSource": "API",
"createdAt": "2024-04-24T12:57:55.086Z",
"updatedAt": "2024-04-24T12:57:55.492Z",
"metadata": {
"objectLists": [],
"counters": {},
"fileIds": ["165399500647"]
},
"importName": "November Marketing Event Leads",
"optOutImport": false,
"id": "45881547"
}
importRequest schema
Field | Data Type | Description |
---|---|---|
|
| (Required) The name of the import. |
|
| Field used to indicate whether the import should create and update, only create, or only update records for a certain object or activity. Include the |
|
| The format for dates included in the file. By default, this is set to |
|
| Indicates the marketing status of contacts in your import file. |
|
| Set to |
|
| Array of file objects in your import. Each object contains information about a file in the import. See below. |
files schema
Field | Data Type | Description |
---|---|---|
|
| (Required) The name of the import file. Must match the name of the CSV or Excel file that is being uploaded. |
|
| (Required) Format of the import file. |
|
| (Required) Contains information to map the contact list file’s columns to HubSpot data. See below. |
fileImportPage schema
Field | Data Type | Description |
---|---|---|
|
| (Required) Indicates whether the contact list file has a header row. |
|
| (Required) Maps the columns in the contact list file to HubSpot data. See below. |
columnMappings schema
Field | Data Type | Description |
---|---|---|
|
| (Required) The name or |
|
| The name of the column header. |
|
| The internal name of the HubSpot property that the data will map to. For the common column in multi-file imports, |
|
| Used to specify that a column contains a unique identifier property Depending on the property and goal of the import, use one of the following values:
|
|
| For multi-file or multiple object imports, the name or |
|
| For multi-file imports only, the type of association the common column should use, specified by the |
|
| For multi-file imports only, indicates the property used in the common column to associate the records. Include this field for the common column property in the file of the object the property belongs to. For example, if you're associating contacts and companies in two files with contact property Email as the common column, set the |
Example importRequest JSON object:
{
"name": "November Marketing Event Leads",
"importOperations": {
"0-1": "UPSERT"
},
"dateFormat": "DAY_MONTH_YEAR",
"createContactListFromImport": true,
"files": [
{
"fileName": "import.csv",
"fileFormat": "CSV",
"fileImportPage": {
"hasHeader": true,
"columnMappings": [
{
"columnObjectTypeId": "0-1",
"columnName": "First Name",
"propertyName": "firstname"
},
{
"columnObjectTypeId": "0-1",
"columnName": "Last Name",
"propertyName": "lastname"
},
{
"columnObjectTypeId": "0-1",
"columnName": "Email",
"propertyName": "email",
"columnType": "HUBSPOT_ALTERNATE_ID"
}
]
}
}
]
}
Final notes
While using the createContactListFromImport
flag and setting Email to be a HUBSPOT_ALTERNATE_ID
, we observed the following:
Uploading two lists with the same name would result in the second list having a random number appended to the name.
A contact that existed in both lists with the same email would be updated across both lists.
Sample files
The following are provided as a working example of how to import contacts into HubSpot via RPDM. The .dlb
file is the working example that can reference the import.csv
to illustrate how to import the file.