HubSpot source connector for Airbyte that syncs CRM data including contacts, companies, deals, and marketing activities with support for OAuth and Private App authentication
—
Quality
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Marketing automation and communication data streams including campaigns, emails, forms, workflows, and email events for comprehensive marketing analytics and campaign tracking.
Marketing email campaigns with statistics and performance metrics using HubSpot's v3 API.
marketing_emails:
primary_key: ["id"]
cursor_field: "updatedAt"
sync_mode: incremental
schema:
type: object
properties:
id:
type: string
description: "Unique marketing email identifier"
name:
type: string
description: "Email campaign name"
subject:
type: string
description: "Email subject line"
createdAt:
type: string
format: date-time
description: "Email creation timestamp"
updatedAt:
type: string
format: date-time
description: "Last update timestamp"
publishedAt:
type: string
format: date-time
description: "Email publish timestamp"
state:
type: string
enum: ["DRAFT", "PUBLISHED", "SCHEDULED"]
description: "Email campaign state"
# Email content and settings
type:
type: string
description: "Email type (REGULAR, A_B_TEST, etc.)"
contentTypeCategory:
type: string
description: "Content category"
htmlTitle:
type: string
description: "HTML title"
previewText:
type: string
description: "Email preview text"
fromEmail:
type: string
format: email
description: "Sender email address"
replyTo:
type: string
format: email
description: "Reply-to email address"
# Statistics (merged from v3 statistics endpoint)
counters:
type: object
properties:
sent:
type: integer
description: "Number of emails sent"
delivered:
type: integer
description: "Number of emails delivered"
opens:
type: integer
description: "Number of email opens"
clicks:
type: integer
description: "Number of email clicks"
forwards:
type: integer
description: "Number of email forwards"
unsubscribes:
type: integer
description: "Number of unsubscribes"
bounces:
type: integer
description: "Number of bounces"
spamreports:
type: integer
description: "Number of spam reports"
# Calculated rates
openRate:
type: number
description: "Email open rate percentage"
clickRate:
type: number
description: "Email click rate percentage"
deliveryRate:
type: number
description: "Email delivery rate percentage"Usage Example:
streams:
- name: marketing_emails
sync_mode: incremental
cursor_field: ["updatedAt"]
destination_sync_mode: append_dedupCampaign records with performance statistics and metadata.
campaigns:
primary_key: ["id"]
cursor_field: "lastUpdatedTime"
sync_mode: incremental
schema:
type: object
properties:
id:
type: string
description: "Unique campaign identifier"
name:
type: string
description: "Campaign name"
subject:
type: string
description: "Campaign subject line"
appId:
type: integer
description: "Application ID"
appName:
type: string
description: "Application name"
createdAt:
type: string
format: date-time
description: "Campaign creation timestamp"
lastUpdatedTime:
type: string
format: date-time
description: "Last update timestamp"
type:
type: string
description: "Campaign type"
# Campaign statistics
counters:
type: object
properties:
sent:
type: integer
description: "Total emails sent"
delivered:
type: integer
description: "Total emails delivered"
opens:
type: integer
description: "Total email opens"
clicks:
type: integer
description: "Total email clicks"
processed:
type: integer
description: "Total emails processed"
dropped:
type: integer
description: "Total emails dropped"
bounces:
type: integer
description: "Total bounces"
deferred:
type: integer
description: "Total deferred sends"Individual email interaction events including opens, clicks, bounces, and deliveries.
email_events:
primary_key: ["id"]
cursor_field: "created"
sync_mode: incremental
schema:
type: object
properties:
id:
type: string
description: "Unique email event identifier"
created:
type: string
format: date-time
description: "Event timestamp"
emailCampaignId:
type: string
description: "Associated email campaign ID"
recipient:
type: string
format: email
description: "Recipient email address"
type:
type: string
enum: [
"DELIVERED", "SENT", "DROPPED", "DEFERRED",
"BOUNCE", "OPEN", "CLICK", "PRINT", "FORWARD",
"SPAMREPORT", "UNSUBSCRIBE", "SUPPRESSED"
]
description: "Type of email event"
# Event-specific details
portalId:
type: integer
description: "HubSpot portal ID"
appId:
type: integer
description: "Application ID"
sentBy:
type: object
properties:
id:
type: string
created:
type: string
format: date-time
# Event metadata (varies by event type)
url:
type: string
description: "Clicked URL (for CLICK events)"
response:
type: string
description: "Bounce reason (for BOUNCE events)"
attemptNumber:
type: integer
description: "Delivery attempt number"
# Associated contact information
filteredContactId:
type: string
description: "Associated contact ID"
filteredContactVid:
type: string
description: "Associated contact VID"Form definitions and configurations for lead capture and data collection.
forms:
primary_key: ["id"]
cursor_field: "updatedAt"
sync_mode: incremental
schema:
type: object
properties:
id:
type: string
description: "Unique form identifier"
name:
type: string
description: "Form name"
createdAt:
type: string
format: date-time
description: "Form creation timestamp"
updatedAt:
type: string
format: date-time
description: "Last update timestamp"
cssClass:
type: string
description: "CSS class for form styling"
redirect:
type: string
description: "Redirect URL after form submission"
submitText:
type: string
description: "Submit button text"
followUpId:
type: string
description: "Follow-up email ID"
notifyRecipients:
type: string
description: "Notification recipients"
# Form fields configuration
formFieldGroups:
type: array
items:
type: object
properties:
fields:
type: array
items:
type: object
properties:
name:
type: string
description: "Field name"
label:
type: string
description: "Field label"
type:
type: string
description: "Field type"
fieldType:
type: string
description: "Specific field type"
required:
type: boolean
description: "Whether field is required"
hidden:
type: boolean
description: "Whether field is hidden"
defaultValue:
type: string
description: "Default field value"
options:
type: array
items:
type: object
properties:
label:
type: string
value:
type: string
description: "Field options for select/radio fields"
# Form performance metrics
performanceData:
type: object
properties:
views:
type: integer
description: "Form view count"
submissions:
type: integer
description: "Form submission count"
conversionRate:
type: number
description: "Form conversion rate"Individual form submission records with submitted data and contact associations.
form_submissions:
primary_key: ["id"]
cursor_field: "submittedAt"
sync_mode: incremental
schema:
type: object
properties:
id:
type: string
description: "Unique form submission identifier"
formId:
type: string
description: "Associated form ID"
portalId:
type: integer
description: "HubSpot portal ID"
submittedAt:
type: string
format: date-time
description: "Submission timestamp"
contactId:
type: string
description: "Associated contact ID"
# Submission metadata
pageUrl:
type: string
description: "Page where form was submitted"
pageTitle:
type: string
description: "Page title"
userAgent:
type: string
description: "User agent string"
ipAddress:
type: string
description: "Submitter IP address"
# Submitted form values
values:
type: array
items:
type: object
properties:
name:
type: string
description: "Field name"
value:
type: string
description: "Submitted value"
objectTypeId:
type: string
description: "Object type ID"
description: "Array of submitted field values"Marketing automation workflow definitions and configurations.
workflows:
primary_key: ["id"]
cursor_field: "updatedAt"
sync_mode: incremental
schema:
type: object
properties:
id:
type: string
description: "Unique workflow identifier"
name:
type: string
description: "Workflow name"
type:
type: string
enum: ["DRIP_DELAY", "PROPERTY_ANCHOR", "DATE_ANCHOR"]
description: "Workflow type"
createdAt:
type: string
format: date-time
description: "Workflow creation timestamp"
updatedAt:
type: string
format: date-time
description: "Last update timestamp"
enabled:
type: boolean
description: "Whether workflow is active"
# Workflow enrollment criteria
onlyExecOnBizDays:
type: boolean
description: "Execute only on business days"
onlyExecuteOnBusinessDays:
type: boolean
description: "Execute only on business days (legacy)"
insertedAt:
type: string
format: date-time
description: "Workflow insertion timestamp"
# Workflow actions and triggers
actions:
type: array
items:
type: object
properties:
type:
type: string
description: "Action type"
delayMillis:
type: integer
description: "Delay in milliseconds"
actionId:
type: string
description: "Action identifier"
description: "Workflow actions"
# Performance metrics
contactListIds:
type: object
properties:
enrolled:
type: integer
description: "Number of contacts enrolled"
active:
type: integer
description: "Number of active contacts"
succeeded:
type: integer
description: "Number of successful completions"Email subscription type definitions and preferences.
email_subscriptions:
primary_key: ["id"]
sync_mode: full_refresh
schema:
type: object
properties:
id:
type: string
description: "Unique subscription type identifier"
name:
type: string
description: "Subscription type name"
description:
type: string
description: "Subscription description"
active:
type: boolean
description: "Whether subscription type is active"
createdAt:
type: string
format: date-time
description: "Creation timestamp"
updatedAt:
type: string
format: date-time
description: "Last update timestamp"Timeline of email subscription changes for contacts.
subscription_changes:
primary_key: ["timestamp", "portalId", "recipient", "subscriptionId"]
cursor_field: "timestamp"
sync_mode: incremental
schema:
type: object
properties:
timestamp:
type: string
format: date-time
description: "Change timestamp"
portalId:
type: integer
description: "HubSpot portal ID"
recipient:
type: string
format: email
description: "Contact email address"
subscriptionId:
type: string
description: "Subscription type ID"
change:
type: string
enum: ["SUBSCRIBED", "UNSUBSCRIBED", "NOT_OPTED_IN"]
description: "Type of subscription change"
source:
type: string
description: "Source of the change"
causedByEvent:
type: object
properties:
id:
type: string
created:
type: string
format: date-time
description: "Event that caused the change"Contact list definitions and configurations.
contact_lists:
primary_key: ["id"]
cursor_field: "updatedAt"
sync_mode: incremental
schema:
type: object
properties:
id:
type: string
description: "Unique contact list identifier"
name:
type: string
description: "List name"
createdAt:
type: string
format: date-time
description: "List creation timestamp"
updatedAt:
type: string
format: date-time
description: "Last update timestamp"
listType:
type: string
enum: ["STATIC", "DYNAMIC"]
description: "List type"
size:
type: integer
description: "Number of contacts in list"
# List filters (for dynamic lists)
filters:
type: array
items:
type: object
properties:
filterFamily:
type: string
property:
type: string
type:
type: string
operation:
type: object
description: "List filtering criteria"The marketing_emails stream uses a specialized transformation to merge statistics:
MarketingEmailStatisticsTransformation:
type: RecordTransformation
# Transformation process:
# 1. For each marketing email record
# 2. Make request to /marketing/v3/emails/{emailId}/statistics
# 3. Merge statistics data into email record
# 4. Handle missing statistics gracefully with warning logs
error_handling:
- Log warnings for missing statistics
- Continue processing without failing sync
- Preserve original email data if statistics unavailableThe connector automatically fetches statistics for each marketing email by:
Campaign Performance Analysis:
SELECT
name,
counters.sent,
counters.opens,
counters.clicks,
ROUND((counters.opens::float / counters.sent) * 100, 2) as open_rate,
ROUND((counters.clicks::float / counters.sent) * 100, 2) as click_rate
FROM marketing_emails
WHERE state = 'PUBLISHED'
ORDER BY counters.sent DESC;Email Event Analysis:
SELECT
type,
COUNT(*) as event_count,
DATE(created) as event_date
FROM email_events
WHERE created >= '2024-01-01'
GROUP BY type, DATE(created)
ORDER BY event_date DESC, event_count DESC;Form Conversion Tracking:
SELECT
f.name as form_name,
COUNT(fs.id) as submissions,
f.performanceData.views as views,
ROUND((COUNT(fs.id)::float / f.performanceData.views) * 100, 2) as conversion_rate
FROM forms f
LEFT JOIN form_submissions fs ON f.id = fs.formId
WHERE f.updatedAt >= '2024-01-01'
GROUP BY f.id, f.name, f.performanceData.views
ORDER BY submissions DESC;Install with Tessl CLI
npx tessl i tessl/airbyte-airbyte-source-hubspot