Python Add Note AttributeError

I have a Python script to add a note to all of my contacts that have “Active” status and the role of “Primary Owner”. The script retrieves the contacts fine; however, it fails when it tries to create a note for each contact. I’ve used Notes - v3 | HubSpotAPI and Engagements | Notes | HubSpot for references.

Code:

from hubspot import HubSpot
from hubspot.crm.contacts import SimplePublicObjectInput, ApiException
from hubspot.crm.objects import ApiException
from hubspot.crm.objects.notes import SimplePublicObjectInputForCreate, ApiException
from datetime import datetime as d
import datetime as dt
import logging as log

log.basicConfig(level=log.INFO, format='%(asctime)s | %(levelname)s | %(message)s', datefmt='%m-%d-%Y %H:%M:%S')

log.info('Initializing...')

API_KEY = 'REDACTED'
BASE_URL = 'https://api.hubapi.com'
STATUS_PROP = 'hs_content_membership_status'
STATUS_VALUE = 'active'
ROLE_PROP = 'role'
ROLE_VALUE = 'Primary Owner'
ERROR_STATUS = False

client = HubSpot(access_token=API_KEY)
log.info('Connected to HubSpot')

# Create a note (engagement) to add to the contacts
def create_note_for_contact(contact_id, note_content):

 properties = {
 "hs_note_body": f"{str(note_content)}",
 "hs_timestamp": f"{str(d.now(dt.timezone.utc).timestamp() * 1000)}",
 "hubspot_owner_id": "REDACTED",
 "hs_attachment_ids": "REDACTED"
 }
 simple_public_object_input_for_create = SimplePublicObjectInputForCreate(
 associations=[{"types":[{"associationCategory":"HUBSPOT_DEFINED","associationTypeId":202}],
 "to":{contact_id}}],
 # object_write_trace_id='string',
 properties=properties
 )
 try:
 response = client.crm.objects.notes.basic_api.create(simple_public_object_input_for_create=simple_public_object_input_for_create)
 log.info(f"Note added to contact {contact_id}")
 except ApiException as e:
 log.error(f"Error adding note to contact {contact_id}: {e}")
 global ERROR_STATUS
 ERROR_STATUS = True

# Function to get contacts with 'hs_content_membership_status' = 'active'
def get_active_contacts():
 filter_criteria = {
 "filterGroups": [{
 "filters": [{
 "propertyName": f"{STATUS_PROP}",
 "operator": "EQ",
 "value": f"{STATUS_VALUE}"
 },
 {
 "propertyName": f"{ROLE_PROP}",
 "operator": "EQ",
 "value": f"{ROLE_VALUE}"
 }]
 }],
 "limit": 100, 
 "properties": ["firstname", "lastname", "hs_content_membership_status"]
 }

 try:
 # Fetch contacts with filter
 response = client.crm.contacts.search_api.do_search(filter_criteria)
 contacts = response.results
 log.info(f"Found {len(contacts)} contacts with active membership status.")
 return contacts
 except ApiException as e:
 log.error(f"Error fetching contacts: {e}")
 global ERROR_STATUS
 ERROR_STATUS = True
 return []

# Main function to add a note to all active contacts
def add_note_to_all_active_contacts(note_content):
 contacts = get_active_contacts()
 try:
 log.info(f"Adding note to {len(contacts)} contacts...")
 for contact in contacts:
 contact_id = contact.id
 create_note_for_contact(contact_id, note_content)
 except ApiException as e:
 log.error(f"Error adding note to contacts: {e}")
 global ERROR_STATUS
 ERROR_STATUS = True

def confirm_input():
 valid_responses = ['y', 'n', 'yes', 'no']
 while True:
 response = input('Are you sure you want to continue? (y/n): ')
 if response in valid_responses:
 if response.lower() in ['y', 'yes']:
 return True
 else:
 return False
 else:
 log.error('Invalid response. Please enter "y" or "n".')

if __name__ == "__main__":
 log.info('Starting...')
 # Example note content

 note = input('Enter the note to be added to all active primary contacts: \n')
 if confirm_input():
 log.info(f'User confirmed adding the following note to all active primary contacts:\n {note}')

 # Run the function to add a note to all active contacts
 add_note_to_all_active_contacts(note)

 if ERROR_STATUS:
 log.error('Error(s) occurred. Please check the logs.')
 else:
 log.info('Done!')

 else:
 log.warning('User cancelled the operation.')

The error I have been getting is:

Hi ,I just reviewed your code and it looks like you are not passing the correct

hubspot_owner_id

in the properties json . You need to send either correct one or you can skip that .
Also you can skip

hs_attachment_ids

and then try again . If you want to send the owner id you can get owners list using this endpoint

https://api.hubapi.com/crm/v3/owners

:check_mark: Mark this answer as solution if it helped you

Hi @Bhupendra_Kumar, thanks for taking a look. I verified the owner ID is correct using the endpoint you provided. I also tried omitting the hubspot_owner_id and hs_attachment_ids and received the same error.

Hi @TWinter2954 , If possible Can you provide me the json that you are posting over the API so that we can figure out if error was with data or the code level.
Thanks

Also @TWinter2954 i want to add one more thing the associations JSON should be like this

[{"types":[{"associationCategory":"HUBSPOT_DEFINED","associationTypeId":202}],
 "to":{"id":"contact_id"}}]

what you are sending is :

[{"types":[{"associationCategory":"HUBSPOT_DEFINED","associationTypeId":202}],
 "to":{contact_id}}]

the “to” object would have id as key .

Hi @TWinter2954

If that helped you can you please mark it as a solution to help the other community members.

Thanks

Hi @Bhupendra_Kumar, I will try this tomorrow afternoon and let you know. Thanks!