🔌 Hubspot Integration
🎯 Overview
Hubspot is a comprehensive CRM platform that provides customer relationship management, sales pipeline, marketing automation, and customer service tools. The DashClicks integration enables bidirectional synchronization of contacts, companies, deals, and notes (engagements) between the platforms.
Provider: HubSpot, Inc. (https://www.hubspot.com) API Version: v1 (Contacts), v2 (Companies), v1 (Deals), v1 (Engagements) Integration Type: OAuth 2.0 REST API
📁 Directory Structure
Documentation Structure:
hubspot/
├── 📄 index.md - Integration overview and setup
├── 📄 authentication.md - OAuth 2.0 flow and token management
├── 📄 contacts.md - Contact synchronization
├── 📄 companies.md - Company data export
├── 📄 deals.md - Deal pipeline management
└── 📄 notes.md - Engagements (notes) synchronization
Source Code Location:
- Base Path:
external/Integrations/Hubspot/ - Controllers:
Controllers/authController.js,Controllers/contactController.js - Providers:
Providers/api.js,Providers/crmData.js - Routes:
Routes/authRoutes.js,Routes/exportRoutes.js - Models:
Models/keys.js
🗄️ MongoDB Collections
📚 Detailed Schema: See Database Collections Documentation
integrations.hubspot.key
- Purpose: Store OAuth access tokens and refresh tokens
- Model:
shared/models/hubspot-key.js - Primary Use: Persist Hubspot OAuth credentials for authenticated API requests
Schema Structure:
{
_id: ObjectId,
account_id: String, // DashClicks account ID
owner: String, // User ID who connected the integration
token: {
access_token: String, // Short-lived access token (expires in seconds)
refresh_token: String, // Long-lived refresh token for obtaining new access tokens
expires_in: Number, // Token expiration time in seconds
token_type: String // "bearer"
},
generated_at: Number, // Unix timestamp when token was generated
token_invalidated: Boolean // Flag indicating if token is manually invalidated
}
The Hubspot key model uses {strict: false} schema option, allowing additional fields from Hubspot OAuth responses to be stored dynamically.
🔐 Authentication & Configuration
Authentication Method: OAuth 2.0 Authorization Code Grant
Required Environment Variables:
| Variable | Description | Required |
|---|---|---|
HUBSPOT_CLIENT_ID | OAuth application client ID | ✅ |
HUBSPOT_CLIENT_SECRET | OAuth application client secret | ✅ |
HUBSPOT_SCOPES | OAuth permission scopes (e.g. contacts) | ✅ |
HUBSPOT_AUTHORIZE_URL | OAuth authorization endpoint | ✅ |
HUBSPOT_TOKEN_URL | OAuth token exchange endpoint | ✅ |
HUBSPOT_GRANT_TYPE | Grant type (authorization_code) | ✅ |
HUBSPOT_REDIRECT_URL | OAuth callback URL | ✅ |
HUBSPOT_CONTACT_ENDPOINT | Contacts API endpoint | ✅ |
HUBSPOT_COMPANIES_ENDPOINT | Companies API endpoint | ✅ |
HUBSPOT_DEALS_ENDPOINT | Deals API endpoint | ✅ |
HUBSPOT_ENGAGEMENTS_ENDPOINT | Engagements (notes) API endpoint | ✅ |
Example Configuration:
HUBSPOT_CLIENT_ID=2acbec95-d71a-4f7a-a039-0f5c2c3e9282
HUBSPOT_CLIENT_SECRET=45e4abbc-41d3-40bc-9dc0-c175f8b01336
HUBSPOT_SCOPES=contacts
HUBSPOT_AUTHORIZE_URL=https://app.hubspot.com/oauth/authorize
HUBSPOT_TOKEN_URL=https://api.hubapi.com/oauth/v1/token
HUBSPOT_GRANT_TYPE=authorization_code
HUBSPOT_REDIRECT_URL=http://localhost:5000/v1/integrations/hubspot/auth/callback
HUBSPOT_CONTACT_ENDPOINT=https://api.hubapi.com/contacts/v1/lists/all/contacts/all
HUBSPOT_COMPANIES_ENDPOINT=https://api.hubapi.com/companies/v2/companies/paged?properties=name&properties=website
HUBSPOT_DEALS_ENDPOINT=https://api.hubapi.com/deals/v1/deal/paged?properties=dealname&includeAssociations=true
HUBSPOT_ENGAGEMENTS_ENDPOINT=https://api.hubapi.com/engagements/v1/engagements/paged
Credential Storage: OAuth tokens stored in integrations.hubspot.key collection
🏗️ Architecture Overview
Key Responsibilities:
- OAuth Authentication: Manage OAuth 2.0 authorization flow with automatic token refresh
- Contact Synchronization: Export contacts from Hubspot with pagination support
- Company Data: Retrieve company information with custom properties
- Deal Management: Access deal pipeline data with associations
- Engagement Tracking: Export notes and engagement history
API Communication Pattern:
- Protocol: REST API over HTTPS
- Authentication: Bearer token in Authorization header
- Data Format: JSON request/response
- Pagination: Cursor-based with offset and limit parameters
Rate Limiting:
- Hubspot Limits: 10 requests per second per OAuth token (may vary by subscription)
- Handling: No automatic rate limiting in current implementation
- Recommendation: Implement exponential backoff for 429 responses
🔗 Features & Capabilities
Core Features
- 📘 Authentication - OAuth 2.0 flow with automatic token refresh
- 📗 CRM Data - Contact, company, deal, and note synchronization
🔄 Integration Data Flow
sequenceDiagram
participant Client as DashClicks Frontend
participant Router as API Router
participant Auth as Auth Controller
participant Provider as Hubspot Provider
participant DB as MongoDB
participant Hubspot as Hubspot API
Client->>Router: GET /v1/integrations/hubspot/auth/login
Router->>Auth: Verify scope & access
Auth->>DB: Check existing token
alt Token exists and valid
Auth-->>Client: Redirect to success URL
else Token missing/invalid
Auth->>Auth: Generate JWT state token
Auth-->>Client: Redirect to Hubspot OAuth
Client->>Hubspot: User authorizes app
Hubspot-->>Auth: Redirect with code
Auth->>Provider: Exchange code for tokens
Provider->>Hubspot: POST /oauth/v1/token
Hubspot-->>Provider: Access + refresh tokens
Provider->>DB: Store tokens
Auth-->>Client: Redirect to success URL
end
Note over Client,Hubspot: Data Export Flow
Client->>Router: GET /v1/integrations/hubspot/export/contacts
Router->>DB: Fetch stored token
DB-->>Router: Return refresh token
Router->>Provider: Get fresh access token
Provider->>Hubspot: POST /oauth/v1/token (refresh)
Hubspot-->>Provider: New access token
Provider->>DB: Update stored token
Router->>Provider: Retrieve contacts
Provider->>Hubspot: GET /contacts/v1/lists/all/contacts/all
Hubspot-->>Provider: Contact data + pagination
Provider-->>Client: Formatted response with pagination
🔗 API Endpoints
Authentication Endpoints
| Endpoint | Method | Scope | Description |
|---|---|---|---|
/v1/integrations/hubspot/auth/login | GET | contacts, contacts.external | Initialize OAuth flow |
/v1/integrations/hubspot/auth/callback | GET | None | OAuth callback (auto-redirect) |
/v1/integrations/hubspot/auth/ | DELETE | contacts, contacts.external | Delete OAuth token |
Data Export Endpoints
| Endpoint | Method | Scope | Required Params | Description |
|---|---|---|---|---|
/v1/integrations/hubspot/export/contacts | GET | contacts, contacts.external | offset, limit | Export contacts |
/v1/integrations/hubspot/export/companies | GET | contacts, contacts.external | offset, limit | Export companies |
/v1/integrations/hubspot/export/deals | GET | contacts, contacts.external | offset, limit | Export deals |
/v1/integrations/hubspot/export/notes | GET | contacts, contacts.external | offset, limit | Export engagements |
Export endpoints use dynamic routing with /:type parameter, allowing contacts, companies, deals, or notes as the type.
📊 Response Format
All data export endpoints return a standardized response structure:
{
"success": true,
"message": "DATA Recieved",
"data": {
"has-more": true,
"offset": 3412996225,
"contacts": [...], // or companies, deals, etc.
"vid-offset": 3412996225 // for contacts endpoint
},
"pagination": {
"hasMore": true,
"offset": 3412996225 // Normalized offset for all types
}
}
Pagination Handling:
- Hubspot uses different pagination fields for different endpoints
contactsendpoint: Usesvid-offset(visitor ID offset)companies,deals,notes: Useoffset- Integration normalizes to consistent
pagination.offsetfield
🚨 Error Handling
Common Error Scenarios:
| Error Code | Scenario | Handling |
|---|---|---|
| 401 | Unauthorized / Invalid token | Token refresh attempted automatically |
| 404 | Token not found in database | User redirected to re-authenticate |
| 429 | Rate limit exceeded | No automatic retry (manual implementation needed) |
| 400 | Invalid request parameters | Error message returned to client |
Token Invalidation:
When token_invalidated: true is set on a stored token, the integration automatically deletes the token and forces re-authentication.
📊 Monitoring & Logging
Token Lifecycle Tracking:
generated_atfield tracks when tokens were last refreshed- Token expiration managed automatically via refresh token flow
- Manual invalidation supported via
token_invalidatedflag
Recommended Monitoring:
- Track OAuth callback failures
- Monitor token refresh frequency
- Alert on 401 errors indicating token issues
- Log rate limit 429 responses
🎯 Integration Use Cases
Contact Synchronization
Import Hubspot contacts into DashClicks for unified CRM view:
GET /v1/integrations/hubspot/export/contacts?limit=100&offset=0
Company Intelligence
Retrieve company data for enrichment:
GET /v1/integrations/hubspot/export/companies?limit=50
Deal Pipeline Analysis
Export deal data with associations for reporting:
GET /v1/integrations/hubspot/export/deals?limit=200&offset=400
Activity History
Fetch engagement notes for contact history:
GET /v1/integrations/hubspot/export/notes?limit=100
🔗 Related Documentation
- Provider API Docs: Hubspot API Documentation
- OAuth Guide: Hubspot OAuth 2.0
- Contacts API: Contacts API Reference
- Companies API: Companies API Reference
- Deals API: Deals API Reference
- Engagements API: Engagements API Reference
⚠️ Implementation Notes
OAuth State Management
- JWT tokens used for state parameter with 6-hour expiration
- State includes
account_id,owner, andforward_url - Prevents CSRF attacks by validating state on callback
Token Refresh Strategy
- Access tokens automatically refreshed on each API call
- Refresh tokens have no expiration (until manually revoked)
- Updated tokens saved back to database immediately
Pagination Best Practices
- Always include
limitparameter to control response size - Default limit is 10 if not specified
- Use returned
offsetvalue for subsequent requests - Check
hasMoreflag to determine if more data exists
Scope Requirements
All endpoints require one of:
contactsscope - Full contact managementcontacts.externalscope - External contact integration
These scopes are enforced via verifyScope middleware.
🚀 Getting Started
1. Configure OAuth App
Create OAuth app in Hubspot developer portal and configure environment variables.
2. Initiate OAuth Flow
Direct users to:
GET /v1/integrations/hubspot/auth/login?forward_url=https://app.dashclicks.com/success
3. Export Data
Once authenticated, export data using:
GET /v1/integrations/hubspot/export/{type}?limit=100&offset=0
Where {type} is one of: contacts, companies, deals, notes
4. Handle Pagination
Use returned pagination.offset for subsequent requests:
GET /v1/integrations/hubspot/export/contacts?limit=100&offset=3412996225
Continue until pagination.hasMore is false.