Search code examples
pythonpandashubspot

Importing pandas dataframe data to HubSpot CRM


I need to send data which is in a pandas dataframe df. I need to import this data to Hubspot

from io import StringIO
csv_data = StringIO()
df.to_csv(csv_data, index=False)
csv_data.seek(0)

import requests
import json
# Your HubSpot API Key
api_key = 'api_key'

# HubSpot Import API endpoint
endpoint = 'https://api.hubapi.com/crm/v3/imports'

# Create a payload
payload = {
    'name': 'data source',
    'files': [
        {
              'file_name': 'datasource.csv',
              'fileData': csv_data.read()
        }

    ]
}

headers = {
    'Content-Type': 'application/json',
    'Authorization': f'Bearer {api_key}'
}

# Make the request
response = requests.post(endpoint, json=payload, headers=headers)

if response.status_code == 200:
    print('Data import successful!')
else:
    print(f'Data import failed with status code {response.status_code}: {response.text}')

I am getting this error:

Data import failed with status code 415: <html>
<head>
<meta http-equiv="Content-Type" content="text/html;charset=utf-8"/>
<title>Error 415 Unsupported Media Type</title>
</head>
<body><h2>HTTP ERROR 415</h2>
<p>Reason:
<pre>    Unsupported Media Type</pre></p>
</body>
</html>

The endgoal is to get the data from the dataframe in HubSpot. Any way to resolve this?


Solution

  • This is how I got it to work for contact imports. It should work for other CRM entities as well:

    import io
    
    import pandas as pd
    import requests
    
    
    class SpoofedBufferedReader(io.BufferedReader):
        def __init__(self, data, name):
            self.data = data
            self.name = name
            self.buffer = io.BytesIO(self.data)
            super().__init__(self.buffer)
    
        def read(self, size=-1):
            return self.buffer.read(size)
    
        def seek(self, offset, whence=io.SEEK_SET):
            return self.buffer.seek(offset, whence)
    
        def tell(self):
            return self.buffer.tell()
    
        @property
        def name(self):
            return self._name
    
        @name.setter
        def name(self, value):
            self._name = value
    
    
    def import_file(df: pd.DataFrame) -> int:
        """
        Import file into Hubspot.
    
        Args:
            df (pd.DataFrame): Data to import into Hubspot
    
        Returns:
            int
        """
        headers = {
            'Authorization': f'Bearer {<your_access_token>}'
        }
        data = {
            "name": "Update Contacts",
            "importOperations": {
                "0-1": "UPDATE"
            },
            "dateFormat": "DAY_MONTH_YEAR",
            "files": [
                {
                    "fileName": "contacts_update.csv",
                    "fileFormat": "CSV",
                    "fileImportPage": {
                        "hasHeader": True,
                        "columnMappings": [
                            {
                                "columnObjectTypeId": "0-1",
                                "columnName": "Email",
                                "propertyName": "email",
                                "columnType": "HUBSPOT_ALTERNATE_ID"
                            },
                            {
                                "columnObjectTypeId": "0-1",
                                "columnName": "<your_column_name_1>",
                                "propertyName": "<your_hs_property_name_1>"
                            },
                            {
                                "columnObjectTypeId": "0-1",
                                "columnName": "<your_column_name_2>",
                                "propertyName": "<your_hs_property_name_2>"
                            },
                        ]
                    }
                }
            ]
        }
        payload = {"importRequest": json.dumps(data)}
    
        # Create a file-like object from the CSV data
        csv_data = df.to_csv(index=True, header=True).encode('utf-8')
    
        # Set up the POST request
        files = [
            ('files', SpoofedBufferedReader(data=csv_data, name="contacts_update.csv"))
        ]
    
        response = requests.post("https://api.hubapi.com/crm/v3/imports", data=payload, files=files, headers=headers)
        response.raise_for_status()
    
        return response.status_code