How to attach a file to HubSpot contact through APIs, in Power Automate

With this article, the issues and solutions I am trying to address are:

  1. How to use HubSpot APIs
  2. How to upload a file to HubSpot
  3. How to make association between a Contact and the uploaded file
  4. How to achieve all of these using Power Automate

On a high level, below is the list of API tasks we have to do to achieve this. We have to make requests to three calls (one less if you have Customer ID already).

High level Power Automate flow

See below the high level flow I have created to demonstrate:

Prerequisites

  1. Basic knowledge in HubSpot. We would be interacting the CRM Contacts and Library
  2. Good knowledge in Power Automate
  3. A HubSpot account – Sandbox / Developer
  4. Create a Private App in HubSpot
  5. Get an Access Token
  6. Create a sample contact in HubSpot (for testing)
  7. Create a folder in the HubSpot Library (optional)

Detailed Flow

In this example, I am using a HTTP Request Trigger, which starts when we POST a file and a email-id (I used it to represent a customer in HubSpot contact form). I am doing some

Set the stage

For those struggling to get few items from the POST’ed content, find below details for your reference.

Using Postman to trigger a Power Automate HTTP flow

A. Get File content

triggerOutputs()['body']['$multipart'][0]['body']

B. Get filename

Honestly, I am not sure if there is a straight forward method available. This is my way of parsing filename from the Content-Disposition string:

// Input sample: "headers": {
//        "Content-Disposition": "form-data; name=\"email\"",
//        "Content-Length": "25"
//      }

// Power fx
trim(concat(split(split(triggerOutputs()['body']['$multipart'][0]['headers']['Content-Disposition'], 'filename="')[1], '"')[0]))

C. Get Email

triggerOutputs()['body']['$multipart'][1]['body']['$content']

HubSpot API Calls

Since the APIs for fetching Contact ID and Uploaded File ID are independent tasks, I am executing them in parallel.

A. Upload file, and get file id

I have used only minimum number parameters to avoid the confusion. I am uploading the file to a folder in the library.

Find the POST’ing JSON script for the Body. I see many people are struggling to make this correct.

{
  "$content-type": "multipart/form-data",
  "$multipart": [
    {
      "headers": {
        "Content-Disposition": "form-data; name=\"folderPath\""
      },
      "body": "/Sample Folder"
    },
    {
      "headers": {
        "Content-Disposition": "form-data; name=\"file\"; filename=\"@{variables('Filename')}\""
      },
      "body": @{variables('file')}
    },
    {
      "headers": {
        "Content-Disposition": "form-data; name=\"options\""
      },
      "body": {
        "access": "PRIVATE"
      }
    }
  ]
}

Upon successful upload, you will be receiving a JSON response with File ID.

B. Get the Customer ID of a contact using email as parameter.

This is a straight forward task. Just call the API using GET. Example: https://api.hubapi.com/crm/v3/objects/contacts/john@mathew.com?idProperty=email

C. Create Contact-File association

Once you have FileID and Contact ID, now you can POST a create-note API call to https://api.hubapi.com/crm/v3/objects/notes

Below is the JSON body you have to use:

{
    "properties": {
        "hs_timestamp": "2024-07-30T10:30:00.000Z",
        "hs_attachment_ids": "<File ID>"
    },
    "associations": [
        {
            "to": {
                "id": "<Customer ID>"
            },
            "types": [
                {
                    "associationCategory": "HUBSPOT_DEFINED",
                    "associationTypeId": 10
                }
            ]
        }
    ]
}

Note: associationTypeId is the magic number which tells the API to make Contact-File association. Please check the documentation for more association types.

Find the Power Automate action view:

Verify if the flow has worked

Go to HubSpot, select contact and you should be able to see the file attached.

Additionally, if you go to the Library -> Files -> Sample Folder, you can see the same file appearing there.