Add attachment to contact using api

Hello,

I just got uploading files working using the api but now i want to associate this file to a contact. I want to use the same functionality as the UI:

I tried using the /engagements/v1/engagements and recreated the call made by the UI, getting a OK back but don’t see the attachment on the user. Anyone any idea’s?

{
	"engagement": {
		"active": true,
		"type": "NOTE",
		"timestamp": 1692174466
	},
	"associations": {
		"contactIds": [
			1234
		],
		"companyIds": [],
		"dealIds": [],
		"ownerIds": [],
		"ticketIds": []
	},
	"attachments": [
		{
			"id": 32111231
		}
	],
	"metadata": {
		"body": ""
	}
}

Best regards,

Michael

Hi @MTan90,

Attachments (the functionality in your screenshot) are added using engagements (Calls, Emails, Notes, Tasks and Meetings). More information on this can be found here. Specifically:

“Use HubSpot’s files tool to manage and store files in HubSpot. Files hosted in HubSpot can be uploaded and used in both HubSpot and external content. They can also be attached to records using the engagements API.”

The approach we need to take is as follows:

1) Upload the file using Files API

We first upload the file to the Hubspot file manager. There are various parameters you can set to locate your file in an appropriate folder if you’d like. In any event on response you get a payload similar to the below, the most important attribute is the “id” which we can use when creating the engagement.

POST https://api.hubapi.com/files/v3/files
RESPONSE
{
 "id": "76894753722",
 "createdAt": "2023-08-16T09:17:11.805Z",
 "updatedAt": "2023-08-16T09:17:11.805Z",
 "archived": false,
 "parentFolderId": "76538018526",
 "name": "My API File-2",
 "path": "/API uploads/My API File-2.png",
 "size": 20659,
 "height": 500,
 "width": 500,
 "encoding": "png",
 "type": "IMG",
 "extension": "png",
 "defaultHostingUrl": "https://140281183.fs1.hubspotusercontent-eu1.net/hubfs/140281183/API%20uploads/My%20API%20File-2.png",
 "url": "https://140281183.fs1.hubspotusercontent-eu1.net/hubfs/140281183/API%20uploads/My%20API%20File-2.png",
 "isUsableInContent": true,
 "access": "PUBLIC_NOT_INDEXABLE"
}

2) Create engagement using Engagement API and associate file

Using the ID returned in the successful response to the request above we can then create our engagement. Whether it’s a “Note, Email, Call, Task or Meeting” is entirely up to you. In my example I’ve opted to use a note to facilitate the attachment. See my request below:

POST https://api.hubapi.com/crm/v3/objects/notes
BODY
{
 "properties": {
 "hs_timestamp": "2023-08-16T10:30:00.000Z",
 "hs_attachment_ids": "76894753722"
 },
 "associations": [
 {
 "to": {
 "id": "101"
 },
 "types": [
 {
 "associationCategory": "HUBSPOT_DEFINED",
 "associationTypeId": 10
 }
 ]
 }
 ]
}
RESPONSE
{
 "id": "19529202369",
 "properties": {
 "hs_attachment_ids": "76894753722",
 "hs_createdate": "2023-08-16T09:24:15.453Z",
 "hs_lastmodifieddate": "2023-08-16T09:24:15.453Z",
 "hs_object_id": "19529202369",
 "hs_object_source": "INTEGRATION",
 "hs_object_source_id": "1914406",
 "hs_timestamp": "2023-08-16T10:30:00Z"
 },
 "createdAt": "2023-08-16T09:24:15.453Z",
 "updatedAt": "2023-08-16T09:24:15.453Z",
 "archived": false
}

And the output in the CRM as shown below i.e Note on the record timeline and attachment populated:

In my case I created a note on a contact record. Depending on which record you’d like to create the engagement is up to you along with the type of engagement you wish to create. The process for attaching the file is the same regardless.

Is there a limit to the number of files that can be uploaded for a hubspot enterprise account?

considering i have caried this out exactly like you have put it but i keep getting this error:

2024-12-18 23:55:17,355 - ERROR - Failed to relate file to contact 76*********7: {“status”:“error”,“message”:“one or more associations are not valid”,“correlationId”:“a5d41”,“errors”:[{“context”:{“validationResult”:[“USER_DOES_NOT_HAVE_PERMISSIONS”]}}],“category”:“BAD_REQUEST”}

what could be the issue? what am i doing wrong exactly? my code for relation is as follows:

def relate_file_to_contact(app_id, file_id, file_title​:disappointed_face:

“”"

Relate the uploaded file to a HubSpot contact using the app_id.

:param app_id: The app_id associated with the contact.

:param file_url: The URL of the uploaded file.

:param file_title: The title of the uploaded file.

“”"

contact_id = get_contact_id_by_app_id(app_id)

if contact_id:

# Create engagement to associate the file with the contact

engagement_payload = {

“properties”: {

“hs_timestamp”: datetime.now().strftime(“%Y-%m-%dT%H:%M:%S.”) + f"{int(datetime.now().microsecond / 1000):03d}Z",

“hs_attachment_ids”: file_id

},

“associations”: [

{

“to”: {

“id”: contact_id

},

“types”: [

{

“associationCategory”: “HUBSPOT_DEFINED”,

“associationTypeId”: 10 # Association type for contact

}

]

}

]

}

# URL to create engagement (Note)

url = f"{HUBSPOT_API_BASE_URL}/crm/v3/objects/notes"

headers = {

“Authorization”: f"Bearer {HUBSPOT_API_KEY}",

“Content-Type”: “application/json”

}

try:

response = requests.post(url, headers=headers, json=engagement_payload)

if response.status_code == 200:

logging.info(f"Successfully related file to contact {contact_id} with file {file_title}.")

else:

logging.error(f"Failed to relate file to contact {contact_id}: {response.text}")

except Exception as e:

logging.error(f"Error occurred while relating file to contact: {e}")