---
title: "HubSpot Connector"
description: "Complete HubSpot CRM integration guide for syncing contacts, companies, deals, tickets, and marketing data with Brevo via Tajo."
url: https://tajo.io/docs/connectors/crm/hubspot/
markdown: https://tajo.io/docs/connectors/crm/hubspot.md
lang: en-US
robots: noindex
---

# HubSpot Connector

Connector status: In progress Being built. Not verified yet.

| Source field | Destination field | Sample value |
| --- | --- | --- |
| `record.id` | `source_id` | `record_1042` |
| `record.updated_at` | `updated_at` | `2026-10-18T08:00:00Z` |
| `record.value` | `value` | `sample_value` |

Connect your HubSpot CRM to Brevo via Tajo for bidirectional contact sync, deal tracking, engagement data, and unified marketing automation across both platforms.

## Overview

| Property | Value |
| --- | --- |
| **Platform** | HubSpot |
| **Category** | CRM |
| **Setup Complexity** | Medium |
| **Official Integration** | No |
| **Data Synced** | Contacts, Companies, Deals, Tickets, Events |
| **API Base URL** | `https://api.hubapi.com` |

## Features

- **Bidirectional contact sync** - Keep contacts in sync between HubSpot and Brevo in real time
- **Deal pipeline tracking** - Sync deal stages and values for revenue-based segmentation
- **Company data sync** - Associate contacts with company records and firmographic data
- **Ticket integration** - Track support tickets for customer health scoring
- **Engagement tracking** - Sync email opens, clicks, meetings, calls, and notes
- **Custom object support** - Map HubSpot custom objects to Brevo attributes
- **Workflow triggers** - Use HubSpot lifecycle stage changes to trigger Brevo automations
- **Webhook events** - Real-time notifications for CRM data changes

## Prerequisites

Before you begin, ensure you have:

1. A HubSpot account (Free, Starter, Professional, or Enterprise)
2. A HubSpot private app or OAuth app with required scopes
3. A Brevo account with API access
4. A Tajo account

## Authentication

### Private App Access Token (Recommended)

Create a private app in HubSpot for direct API access with granular scope control.

1. Go to HubSpot Settings > Integrations > Private Apps
2. Create a new private app
3. Configure required scopes
4. Copy the access token

```bash
curl -X GET "https://api.hubapi.com/crm/v3/objects/contacts" \
  -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
  -H "Content-Type: application/json"
```

### OAuth 2.0

Use OAuth 2.0 for multi-account integrations that require user authorization.

```bash
# Authorization URL
https://app.hubspot.com/oauth/authorize?client_id={client_id}&scope=crm.objects.contacts.read&redirect_uri={redirect_uri}
```

#### Required Scopes

```
crm.objects.contacts.read
crm.objects.contacts.write
crm.objects.companies.read
crm.objects.deals.read
crm.objects.deals.write
crm.objects.custom.read
crm.schemas.custom.read
```

## Configuration

### Basic Setup

```yaml
connectors:
  hubspot:
    enabled: true
    access_token: "${HUBSPOT_ACCESS_TOKEN}"

    # Data sync options
    sync:
      contacts: true
      companies: true
      deals: true
      tickets: true
      engagements: true

    # Sync direction
    direction: bidirectional  # or 'hubspot_to_brevo' | 'brevo_to_hubspot'

    # List assignment in Brevo
    lists:
      all_contacts: 10
      qualified_leads: 11
      customers: 12
```

### Field Mapping

Map HubSpot properties to Brevo contact attributes:

#### Default Mappings

| Parameter | Type | Description |
| --- | --- | --- |
| `email` required | string | Contact email (primary identifier) |
| `firstname` optional | string | Maps to FIRSTNAME attribute in Brevo |
| `lastname` optional | string | Maps to LASTNAME attribute in Brevo |
| `phone` optional | string | Maps to SMS attribute for WhatsApp/SMS |
| `company` optional | string | Associated company name |
| `lifecyclestage` optional | string | HubSpot lifecycle stage (subscriber, lead, MQL, SQL, customer) |
| `hs_lead_status` optional | string | Lead qualification status |
| `hubspot_owner_id` optional | string | Assigned sales owner ID |

#### Custom Property Mapping

```yaml
field_mapping:
  # Standard fields
  email: email
  firstname: FIRSTNAME
  lastname: LASTNAME
  phone: SMS

  # CRM fields
  lifecyclestage: LIFECYCLE_STAGE
  hs_lead_status: LEAD_STATUS
  company: COMPANY_NAME

  # Deal metrics
  hs_total_deal_value: DEAL_VALUE
  num_associated_deals: DEAL_COUNT

  # Custom properties
  preferred_channel: PREFERRED_CHANNEL
  customer_segment: SEGMENT
```

## API Endpoints

### CRM Objects

| Method | Endpoint | Description |
| --- | --- | --- |
| `GET` | `/crm/v3/objects/contacts` | List contacts |
| `POST` | `/crm/v3/objects/contacts` | Create a contact |
| `PATCH` | `/crm/v3/objects/contacts/{id}` | Update a contact |
| `GET` | `/crm/v3/objects/companies` | List companies |
| `GET` | `/crm/v3/objects/deals` | List deals |
| `POST` | `/crm/v3/objects/deals` | Create a deal |
| `GET` | `/crm/v3/objects/tickets` | List tickets |

### Associations

| Method | Endpoint | Description |
| --- | --- | --- |
| `GET` | `/crm/v4/objects/{objectType}/{objectId}/associations/{toObjectType}` | Get associations |
| `PUT` | `/crm/v4/objects/{objectType}/{objectId}/associations/{toObjectType}/{toObjectId}` | Create association |

### Engagements

| Method | Endpoint | Description |
| --- | --- | --- |
| `GET` | `/crm/v3/objects/calls` | List call engagements |
| `GET` | `/crm/v3/objects/emails` | List email engagements |
| `GET` | `/crm/v3/objects/meetings` | List meetings |
| `GET` | `/crm/v3/objects/notes` | List notes |
| `GET` | `/crm/v3/objects/tasks` | List tasks |

## Events

### Contact Events

| Event | Trigger | Use Case |
| --- | --- | --- |
| `contact.creation` | New contact created | Welcome flow trigger |
| `contact.propertyChange` | Contact property updated | Attribute sync |
| `contact.merge` | Contacts merged | Deduplication handling |
| `contact.deletion` | Contact deleted | Cleanup in Brevo |

### Deal Events

| Event | Trigger | Use Case |
| --- | --- | --- |
| `deal.creation` | New deal created | Sales notification |
| `deal.propertyChange` | Deal stage changed | Pipeline automation |
| `deal.deletion` | Deal removed | Revenue reporting |

### Company Events

| Event | Trigger | Use Case |
| --- | --- | --- |
| `company.creation` | New company added | Account-based marketing |
| `company.propertyChange` | Company data updated | Firmographic sync |

## Code Examples

### Initialize Connector

```javascript
import { TajoClient } from '@tajo/sdk';

const tajo = new TajoClient({
  apiKey: process.env.TAJO_API_KEY,
  brevoApiKey: process.env.BREVO_API_KEY
});

// Connect HubSpot
await tajo.connectors.connect('hubspot', {
  accessToken: process.env.HUBSPOT_ACCESS_TOKEN
});
```

### Run Contact Sync

```javascript
// Full bidirectional sync
await tajo.connectors.sync('hubspot', {
  type: 'full',
  resources: ['contacts', 'companies', 'deals'],
  direction: 'bidirectional',
  since: '2023-01-01'
});

// Check sync status
const status = await tajo.connectors.status('hubspot');
console.log(status);
// {
//   connected: true,
//   lastSync: '2024-01-15T10:30:00Z',
//   contactsSynced: 34200,
//   companiesSynced: 5100,
//   dealsSynced: 2340
// }
```

### Handle Webhook Events

```javascript
// Handle HubSpot webhook notifications
app.post('/webhooks/hubspot', async (req, res) => {
  const signature = req.get('X-HubSpot-Signature-v3');

  // Verify webhook signature
  if (!verifyHubSpotSignature(req.body, signature)) {
    return res.status(401).send('Unauthorized');
  }

  for (const event of req.body) {
    await tajo.connectors.handleWebhook('hubspot', {
      eventType: event.subscriptionType,
      objectId: event.objectId,
      propertyName: event.propertyName,
      propertyValue: event.propertyValue
    });
  }

  res.status(200).send('OK');
});
```

## Rate Limits

HubSpot applies rate limits per private app or OAuth app:

| Plan | Rate Limit | Burst Limit |
| --- | --- | --- |
| Free/Starter | 100 requests/10 seconds | 150 requests/10 seconds |
| Professional | 150 requests/10 seconds | 200 requests/10 seconds |
| Enterprise | 200 requests/10 seconds | 250 requests/10 seconds |
| API add-on | 200 requests/10 seconds | 250 requests/10 seconds |

Additional limits:

- **Search API**: 5 requests/second per app
- **Batch operations**: 100 records per batch request
- **Daily limit**: 500,000 requests/day (OAuth apps)

Rate Limit Handling

HubSpot returns a `429 Too Many Requests` response when limits are exceeded. Use exponential backoff and monitor the `X-HubSpot-RateLimit-*` headers.

## Troubleshooting

### Common Issues

| Issue | Cause | Solution |
| --- | --- | --- |
| 401 Unauthorized | Expired or invalid token | Regenerate private app token or refresh OAuth token |
| Contact not synced | Missing email property | HubSpot contacts require an email for Brevo sync |
| Duplicate contacts | No deduplication rule | Configure merge rules in HubSpot |
| Webhook not received | Subscription not active | Re-register webhook subscriptions |
| Property not mapped | Custom property not created | Create the property in HubSpot first |

### Debug Mode

Enable verbose logging:

```yaml
connectors:
  hubspot:
    debug: true
    log_level: verbose
    log_webhooks: true
```

### Test Connection

```bash
tajo connectors test hubspot
# ✓ API connection successful
# ✓ Contacts readable
# ✓ Companies readable
# ✓ Deals readable
# ✓ Webhooks registered
```

## Best Practices

1. **Use private apps over API keys** - API keys are deprecated; use private apps for better security
2. **Implement bidirectional sync carefully** - Avoid infinite loops by tracking sync source
3. **Map lifecycle stages** - Use HubSpot lifecycle stages to segment contacts in Brevo
4. **Batch API requests** - Use batch endpoints for bulk operations to stay within rate limits
5. **Monitor webhook delivery** - Set up retry logic and dead letter handling
6. **Use incremental sync** - Sync only changed records using the `lastmodifieddate` property

## Security

- **Private App Tokens** - Scoped access tokens with granular permissions
- **OAuth 2.0** - Industry-standard authorization with refresh token rotation
- **Webhook signatures** - HMAC-based signature verification (v3)
- **TLS encryption** - All API communication encrypted in transit
- **Scoped permissions** - Minimum required scope access per integration

## Related Resources

- [HubSpot API Documentation](https://developers.hubspot.com/docs/api/overview)
- [HubSpot Authentication Guide](https://developers.hubspot.com/docs/api/working-with-oauth)
- [Salesforce Connector](https://tajo.io/docs/connectors/crm/salesforce)
- [Customer Sync Skill](https://tajo.io/docs/skills/data-sync/customer-sync)
- [Brevo Contacts API](https://tajo.io/docs/contact-management)

## Open-Source Implementation Map

This section is derived from official or public repository material discovered for the HubSpot connector. Use it as the engineering companion to the setup guide above: it shows where the API surface lives, what implementation assets exist, and how Tajo should translate them into reliable Brevo sync behavior.

### Repository Snapshot

| Repository | Commit | Languages / formats | Files |
| --- | --- | --- | --- |
| [HubSpot/HubSpot-Public-API-Spec-Collection](https://github.com/HubSpot/HubSpot-Public-API-Spec-Collection) | 852bc16 | JSON (511), postman/api (1), postman/api\_00f8c226-8513-4ea0-8592-ed2d246f258d (1), postman/api\_02993b5c-6639-4475-8a76-b8ed19a52d3a (1), postman/api\_03bbec65-b602-4556-b3ec-f032da516ef2 (1), postman/api\_058ba0d6-3d29-4a4d-b8e8-1870a36cb2b1 (1) | 625 |

### Integration Shape

```mermaid
graph LR
  Source["HubSpot API / repository"] --> Auth["Auth and scopes"]
  Source --> Objects["Objects, events, and schemas"]
  Auth --> Tajo["Tajo connector runtime"]
  Objects --> Tajo
  Tajo --> Brevo["Brevo contacts, attributes, lists, campaigns"]
  Tajo --> Ops["Backfill, cursor, retries, logs"]
```

### What To Reuse

- Postman Integration: Synchronization with HubSpot’s Public APIs via Open API 3.0 Schema
- Purpose
- Usage
- These specifications are not intended for external use. If you are an external developer looking for HubSpot’s API documentation, please refer to our official API documentation.
- Updating the Specifications

### Tajo Revamp Checklist

- Keep authentication setup aligned with the vendor docs and the public repository’s current API shape.
- Map primary resources into explicit Tajo sync objects with stable external IDs.
- Prefer cursor-based or updated-at incremental sync where the API exposes it; otherwise document the fallback.
- Treat webhook handlers as idempotent and replay-safe, especially for order, contact, ticket, and campaign events.
- Capture pagination, rate limits, retry headers, and partial-failure behavior in connector smoke tests.
- Keep examples small and runnable against sandbox or test-mode accounts.

### Sources

- [HubSpot/HubSpot-Public-API-Spec-Collection](https://github.com/HubSpot/HubSpot-Public-API-Spec-Collection)
- [Vendor documentation](https://developers.hubspot.com/mcp)
