If youāve tried to use HubSpotās v4 Association API, you probably felt confused. The docs are complex, the setup isnāt beginner-friendly, and the new structure (compared to v3) isnāt easy to follow.
In this guide, Iāll walk you through how I got it workingāstep-by-step.
š¤ What Are “Associations” in HubSpot?
Associations mean connecting two objects together. For example:
- A company is linked to a contact
- A deal is linked to a company
- A deal is linked to a line item
This connection lets you track related data easily in the CRM.
HubSpot v4 Associations API: Required Fields
HubSpot’s v4 associations API uses a new structure:
- Instead of just saying āassociate object A with object B,ā
- Now you also need:
associationCategory
(usuallyHUBSPOT_DEFINED
)associationTypeId
(a number that tells HubSpot what kind of relationship this is)
Common Association Type IDs
Youāll need to know the numeric ID of the association you want.
Example IDs:
Association | ID |
---|---|
company_to_contact | 1 |
deal_to_company | 2 |
contact_to_deal | 3 |
deal_to_line_item | 19 |
Full reference:
š HubSpot Docs – Association v4 Type IDs
Python Code Example for HubSpot v4 Associations
Hereās a working Python code example using requests
:
import requests import json url = "https://api.hubapi.com/crm/v4/objects/deals/<DEAL_RECORD_ID>/associations/default/line_items/<LINE_ITEMS_RECORD_ID>" payload = json.dumps([ { "associationCategory": "HUBSPOT_DEFINED", "associationTypeId": 19 } ]) headers = { 'Content-Type': 'application/json', 'Authorization': 'Bearer YOUR_ACCESS_TOKEN' } response = requests.put(url, headers=headers, data=payload) print(response.status_code) print(response.text)
Replace:
38700000000
= your Deal ID34400000000
= your Line Item IDYOUR_ACCESS_TOKEN
= your HubSpot private app token (with CRM object write permissions)
Postman Example (for Testing)
You can also test associations in Postman:
- Method:
PUT
- URL:
https://api.hubapi.com/crm/v4/objects/deals/{dealRecordId}/associations/default/line_items/{lineItemRecordId}
- Headers:
Authorization: Bearer YOUR_ACCESS_TOKEN
Content-Type: application/json
- Body (raw JSON):
[ { "associationCategory": "HUBSPOT_DEFINED", "associationTypeId": 19 } ]
š”Tips from My Experience
- Association type ID is required ā this is what broke most of my first attempts.
- V4 doesnāt use the same structure as v3 ā make sure youāre reading the right docs.
- Log everything ā response status, request body, etc., to debug easily.
- Map your association type keys (like
contact_to_deal
) to IDs in your code.
Example:
association_type_map = { "company_to_contact": 1, "deal_to_company": 2, "contact_to_deal": 3, "deal_to_line_item": 19, }
Want More Advanced HubSpot CRM v4 Association Example
In the earlier example, we showed the basic way to associate two HubSpot objects using the v4 API and a single association type ID.
However, in real-world projects, you might need to link multiple object types in one go ā for example:
- Connect a Company to a Contact
- Link that Contact to a Deal
- Associate the Deal back to the Company
- Attach a Line Item to the Deal
Example Diagram:

Hereās an example of a Python function that handles multiple associations at once:
from dataclasses import dataclass, asdict HUBSPOT_API_URL = "https://api.hubapi.com" # set your base URL @dataclass class AssociateEntity: source_object_type: str source_object_id: str to_object_type: str to_object_id: str association_type_id: int def associate_hubspot_objects(company_record_id, contact_record_id, deal_id, line_item_id): associations = [] # Build association list if company_record_id and contact_record_id: associations.append( AssociateEntity("companies", company_record_id, "contacts", contact_record_id, 1) # Example ID ) associations.append( AssociateEntity("contacts", contact_record_id, "deals", deal_id, 3) # Example ID ) if deal_id and company_record_id: associations.append( AssociateEntity("deals", deal_id, "companies", company_record_id, 4) # Example ID ) if deal_id and line_item_id: associations.append( AssociateEntity("deals", deal_id, "line_items", line_item_id, 19) # Example ID ) # Process each association for assoc in associations: data = asdict(assoc) url = ( f"{HUBSPOT_API_URL}/crm/v4/objects/" f"{data['source_object_type']}/{data['source_object_id']}/" f"associations/default/{data['to_object_type']}/{data['to_object_id']}" ) payload = [ { "associationCategory": "HUBSPOT_DEFINED", "associationTypeId": data["association_type_id"], } ] try: response = hubspot_request(url, method="PUT", payload=payload) print(f"Association success: {data} ā Status {response.status_code}") except Exception as e: print(f"Association failed: {data} ā Error: {e}")
This function:
- Builds a list of association tasks based on the IDs you pass in.
- Uses a
dataclass
to keep the code organized and readable. - Loops through each association and sends it to HubSpot via your
associate_hubspot_ids()
function.
By using this approach, you can handle multiple relationships in one process instead of calling the API many times manually.
Additional Resources
- HubSpot Docs – Link to HubSpot’s official docs for associations v4
Final Thoughts
The HubSpot v4 association system is powerful, but also more complex than before. If you’re new to it, it can feel overwhelming. Thatās why I created this simplified guideāto save others the hours I spent solving this!
If youāre working with deals, contacts, line items, or companies, and want to associate them properly, just copy this setup and tweak it for your needs.
š Have Questions?
Feel free to comment below or contact me if you need help with your HubSpot integration.
Thanks for reading, and happy coding! š