HubSpot Connector

Manage contacts, companies, deals, and marketing in HubSpot

HubSpot Connector

Integrate your workflows with HubSpot CRM and marketing automation. Create and manage contacts, manage deals, run email campaigns, and sync your customer data seamlessly.

Overview

The HubSpot connector provides 9 operations for managing your inbound marketing and CRM workflows. Whether you're automating contact creation, managing the sales pipeline, or triggering marketing campaigns, this connector makes it easy.

Authentication

HubSpot supports two authentication methods:

Option 1: OAuth 2.0 (Recommended)

Secure, user-authorized access. Best for production:

auth_type: oauth2
client_id: "your-app-client-id"
client_secret: "your-app-secret"
scopes:
  - crm.objects.contacts.read
  - crm.objects.contacts.write
  - crm.objects.companies.read
  - crm.objects.deals.read

How to set it up:

  1. Go to HubSpot App Marketplace > Develop apps
  2. Create a new app
  3. Under Auth, enable OAuth and add redirect URI: https://yourapp.deepchain.dev/oauth/callback
  4. Request the scopes you need (contacts, companies, deals, etc.)
  5. Copy your Client ID and Client Secret

Option 2: Private App Token

For testing or simpler setups:

auth_type: private_app
access_token: "pat-your-private-app-token"

Create a private app in Settings > Integrations > Private apps and copy the access token.

Available Operations

Here's what you can do:

Contacts

Operation What It Does
getContact Fetch a contact by ID
createContact Create a new contact
updateContact Update contact details
searchContacts Search contacts with filters

Companies

Operation What It Does
getCompany Fetch a company by ID
createCompany Create a new company
updateCompany Update company details

Deals

Operation What It Does
getDeal Fetch a deal by ID
createDeal Create a new deal
updateDeal Update deal details

Practical Workflow Examples

Example 1: Auto-Create Contact from Email Signup

Someone subscribes to your email list → automatically create a contact in HubSpot:

- id: create_contact
  type: hubspot_connector
  config:
    operation: createContact
    properties:
      email: "{{ input.email }}"
      firstname: "{{ input.first_name }}"
      lastname: "{{ input.last_name }}"
      company: "{{ input.company_name }}"
      phone: "{{ input.phone }}"
      lifecyclestage: "subscriber"

Example 2: Search for Existing Contacts

Check if a contact already exists before creating a duplicate:

- id: search_contact
  type: hubspot_connector
  config:
    operation: searchContacts
    filterGroups:
      - filters:
          - propertyName: "email"
            operator: "EQ"
            value: "{{ input.email }}"
    limit: 1

Then in a conditional:

- id: check_exists
  type: conditional
  config:
    condition: "{{ search_contact_1.response.length > 0 }}"
    true_path: "update_contact"
    false_path: "create_contact"

Example 3: Move Contact Through the Funnel

Update a contact's lifecycle stage as they progress:

- id: update_lifecycle
  type: hubspot_connector
  config:
    operation: updateContact
    contactId: "{{ input.contact_id }}"
    properties:
      lifecyclestage: "{{ input.new_stage }}"  # e.g., "lead", "marketingqualifiedlead", "customer"

Example 4: Create a Deal and Link to Contact

Create an opportunity and connect it to the contact:

- id: create_deal
  type: hubspot_connector
  config:
    operation: createDeal
    properties:
      dealname: "{{ input.deal_name }}"
      dealstage: "negotiation"  # Pick from your HubSpot pipeline stages
      amount: "{{ input.deal_value }}"
      closedate: "{{ formatDate(input.close_date, 'x') }}"  # Unix timestamp
      hubspot_owner_id: "{{ input.owner_id }}"  # Sales rep user ID

Example 5: Update Multiple Contacts in Bulk

Use search results to update many contacts at once:

- id: find_inactive
  type: hubspot_connector
  config:
    operation: searchContacts
    filterGroups:
      - filters:
          - propertyName: "lifecyclestage"
            operator: "EQ"
            value: "lead"
          - propertyName: "hs_analytics_last_visit"
            operator: "LT"
            value: "{{ formatDate(subtractDays(now(), 90), 'x') }}"
    limit: 100

- id: loop_inactive
  type: loop
  config:
    items: "{{ find_inactive_1.response }}"

- id: update_stage
  type: hubspot_connector
  config:
    operation: updateContact
    contactId: "{{ loop_1.current.id }}"
    properties:
      lifecyclestage: "subscriber"

Rate Limits

HubSpot enforces different limits based on your app type:

  • OAuth apps: 100 requests per 10 seconds
  • Private apps: 150 requests per 10 seconds
  • Burst limit: 1,200 requests per minute

Note: DeepChain handles retries automatically, so you'll rarely hit these limits. But if you do, we'll queue requests until the rate limit resets.

Error Handling

Common HubSpot Errors

Error What It Means How to Fix
UNAUTHORIZED Invalid or expired token Re-authenticate in Credentials
INVALID_EMAIL Email format is invalid Check the email address
CONTACT_EXISTS Contact already exists Use update instead of create
INVALID_PROPERTY Property doesn't exist Check property names in HubSpot
INVALID_ENUM_VALUE Picklist value doesn't exist Pick a value from the list

Debugging

Enable debug logging:

Node Configuration:
  debug: true
  logRequest: true
  logResponse: true

Check execution logs for exact API responses from HubSpot.

Best Practices

1. Store Contact IDs, Not Email Addresses

Always use HubSpot's internal contact ID, not email:

# Good
contactId: "{{ input.contact_id }}"

# Okay but slower
searchContacts:
  filterGroups:
    - filters:
        - propertyName: "email"
          value: "{{ input.email }}"

2. Use Correct Property Names

HubSpot property names are specific—check your HubSpot setup:

# Standard properties (note lowercase)
email: "{{ input.email }}"
firstname: "{{ input.first_name }}"
lastname: "{{ input.last_name }}"

# Custom properties (usually lowercase with underscores)
custom_field_name: "{{ input.value }}"

3. Format Dates as Unix Timestamps

HubSpot dates need Unix timestamps (milliseconds):

closedate: "{{ formatDate(input.date, 'x') }}"  # Converts to Unix timestamp

4. Handle Lifecycle Stages

Use the exact stage names from your HubSpot pipeline:

lifecyclestage: "subscriber"  # or "lead", "marketingqualifiedlead", "opportunity", "customer", "evangelist", "other"

5. Batch Operations When Possible

Instead of updating one contact at a time, batch them:

# Do searches once, then loop and update
- id: find_contacts
  type: hubspot_connector
  config:
    operation: searchContacts
    # ... filter criteria ...

- id: loop
  type: loop
  items: "{{ find_contacts_1.response }}"

- id: batch_update
  type: hubspot_connector
  config:
    operation: updateContact
    contactId: "{{ loop_1.current.id }}"
    # ... update properties ...

Next Steps