HubSpot Integration
Sync your HubSpot CRM contacts and companies with Propstreet automatically.
Overview
| Feature | Support |
|---|---|
| Market | Global (Nordic-wide) |
| Sync Direction | Bidirectional |
| Real-time Updates | Yes (customer-managed sync) |
| Contacts | ✅ Full support |
| Companies | ✅ Full support |
| Projects | ✅ Full support (v1.2.0) |
| Prospects | ✅ Full support (v1.2.0) |
| Properties | ⚠️ API available (v1.3.0) |
Data Mapping
Contact Fields
| HubSpot | Propstreet | Notes |
|---|---|---|
| First Name | First Name | |
| Last Name | Last Name | |
| Primary email synced | ||
| Phone / Mobile | Phone | Mobile preferred |
| Job Title | Job Title | Synced to company connection |
| Company | Connection | Links contact to company |
| Lifecycle Stage | Tags | Mapped as tag (e.g., "customer") |
| Avatar | Profile Picture | See profile picture section below |
Note: HubSpot supports additional emails. We sync the primary email to Propstreet's email field.
Company Fields
| HubSpot | Propstreet | Notes |
|---|---|---|
| Company Name | Name | |
| Website URL | Homepage URL | Full URL synced |
| Domain | Domain | Set directly or auto-extracted from URL |
| Country | Country Code | ISO 2-letter code |
| Organization Number | External Reference | Custom property setup |
| Company Logo | Profile Picture | See profile picture section below |
How Sync Works
HubSpot → Propstreet
You control the sync through your own integration layer:
- Configure HubSpot to send webhooks to your middleware (e.g., Zapier, Make, Azure Logic Apps, or custom service)
- Your middleware transforms and pushes data to Propstreet via our API
- Records are matched using email or company domain and created/updated in Propstreet
This gives you full control over sync timing, filtering, and data transformation.
Propstreet → HubSpot
When you update a contact in Propstreet, you have two options:
Option A: Webhooks (Recommended)
- Register a Propstreet webhook for
contact.*andcompany.*events - Propstreet pushes changes to your endpoint in real-time
- Your middleware transforms and pushes to HubSpot
Option B: Polling
- Your integration layer polls the Propstreet API for changes (using
updated_since) - Changes are transformed and pushed to HubSpot via their API
- Your HubSpot records stay in sync
Webhooks provide near real-time sync without polling overhead.
Duplicate Handling
We use smart matching to prevent duplicates:
- Contacts: Matched by email address first, then HubSpot record ID
- Companies: Matched by domain, then organization number (if configured)
If we detect a potential duplicate, we update the existing record rather than creating a new one.
Field Considerations
Multiple Emails
HubSpot supports additional email addresses per contact. Propstreet syncs the primary email only; additional emails remain in HubSpot but are not synced.
Phone Numbers
HubSpot has separate fields for phone and mobile phone. We prefer the mobile number for Propstreet; if mobile is empty, we use the main phone number.
Job Title and Company
HubSpot stores job title directly on the contact record. In Propstreet, job title is part of the company connection. When syncing:
- The contact's job title maps to their primary company connection in Propstreet
- If a contact is associated with multiple companies in HubSpot, the primary association is used
Lifecycle Stage
HubSpot's lifecycle stages (subscriber, lead, customer, etc.) are mapped to Propstreet tags. For example, a "Customer" lifecycle stage becomes a lifecycle-customer tag.
Website URL and Domain
HubSpot has two related company properties:
- Website URL (
website) - The full URL (e.g.,https://www.acme.com/about) - Company Domain Name (
domain) - The root domain only (e.g.,acme.com)
Propstreet mirrors this pattern:
- Homepage URL (
homepageUrl) - Maps to HubSpot's Website URL - Domain (
domain) - Can be set directly or auto-extracted from Homepage URL
When syncing HubSpot → Propstreet:
- If HubSpot has
website, use it forhomepageUrl- domain is auto-extracted - If HubSpot only has
domain(no website), set Propstreet'sdomainfield directly - When both are provided in the same request,
homepageUrltakes precedence for domain derivation
When syncing Propstreet → HubSpot, set HubSpot's website property with the full homepageUrl. HubSpot will auto-populate its domain property from this.
Profile Pictures
Contact avatars:
- HubSpot auto-populates contact avatars from social media (via FullContact) and Gravatar
- Manually uploaded avatars are accessible via
hs_avatar_filemanager_key - HubSpot does not support setting contact avatars via API
- Recommendation: Sync Propstreet → HubSpot only for profile pictures uploaded through Propstreet's UI
Company logos:
- HubSpot stores company logos but API support is limited
- Company logos cannot be reliably set via API
- Recommendation: Manage company logos directly in each system
Note: Due to HubSpot API limitations, profile picture sync is one-way (Propstreet → your display layer) or manual.
Organization Number (Nordic)
HubSpot doesn't have a built-in organization number field. For Nordic markets, create a custom property in HubSpot to store:
- Norway: Organisasjonsnummer
- Sweden: Organisationsnummer
- Denmark: CVR-nummer
- Finland: Y-tunnus
This enables accurate company matching via Propstreet's externalRefs field.
Setup Requirements
To build a HubSpot integration, you'll need:
- HubSpot Account - Professional or Enterprise tier recommended for webhook support
- Propstreet API Credentials - Generate in your account settings
- Integration Layer - Middleware to handle webhooks and API calls (Zapier, Make, Azure Logic Apps, n8n, or custom)
- HubSpot Custom Properties - Create any additional fields you need (e.g., organization number)
Getting Started
- Generate Propstreet API credentials in your account settings (requires login)
- Review the Propstreet API documentation for endpoints and data models
- Set up your integration layer to sync data between HubSpot and Propstreet
- Create any custom properties needed in HubSpot
- Test with a small dataset before full rollout
You're responsible for building and maintaining the integration.
Frequently Asked Questions
Which HubSpot plans support the integration?
The integration works with all HubSpot plans. However, HubSpot webhook support (for real-time sync to your middleware) requires Professional or Enterprise tier.
How often does data sync?
Sync frequency depends on how you configure your integration layer:
- Real-time: Use HubSpot webhooks (Pro/Enterprise) to trigger immediate syncs
- Scheduled: Poll both APIs on a schedule (e.g., every 15 minutes, hourly)
- Manual: Trigger syncs on-demand
What happens to data if I stop syncing?
Your data remains in both systems. No data is deleted. Use externalRefs to maintain record linkage if you resume syncing later.
Can I choose which contacts to sync?
Yes. Your integration layer controls which records to sync. Common filtering approaches:
- HubSpot lists or segments
- Contact properties (e.g., only sync contacts with certain tags)
- Company associations
How should I handle merge conflicts?
Design your integration layer to handle conflicts. Common approaches:
- Last write wins: Use timestamps to determine the most recent change
- Source of truth: Designate one system as authoritative for specific fields
- Manual review: Flag conflicts for human review
Projects & Prospects (v1.2.0)
Sync real estate deals between HubSpot Deals and Propstreet Projects. Track investor prospects through your pipeline with bidirectional classification sync.
Deal to Project Mapping
| HubSpot Deal | Propstreet Project | Notes |
|---|---|---|
| hs_object_id | externalRefs | namespace: "hubspot" |
| dealname | name | Direct mapping |
| dealstage | status | Map to pipeline stages (see below) |
| pipeline | — | Use to filter which deals to sync |
| (custom) is_portfolio | isPortfolio | Create custom boolean property |
| (custom) property_count | propertyCount | Create custom number property |
| createdate | createdUtc | Read-only in Propstreet |
| hs_lastmodifieddate | updatedUtc | For delta sync |
Deal-Contact Associations to Prospect Mapping
| HubSpot Association | Propstreet Prospect | Notes |
|---|---|---|
| Deal-Contact link | contactId | Via Contact external ref lookup |
| Deal-Company link | companyId | Alternative for company prospects |
| Association label | classification | Use custom labels (see below) |
Stage Mapping
Propstreet uses three separate fields for project state. Map HubSpot deal stages to the appropriate combination:
| HubSpot Stage (example) | status |
classification |
teaser.stage |
Notes |
|---|---|---|---|---|
| Draft | open | draft | — | Initial deal setup |
| Marketing | open | active | published | Deal being marketed |
| Under Review | open | active | communicated | Teaser sent to investors |
| LOI Submitted | open | active | communicated | Active negotiations |
| Due Diligence | open | active | communicated | Deep investor engagement |
| Closed Won | closed | — | — | Deal completed |
| Closed Lost | deleted | — | — | Deal fell through |
status: Lifecycle state (open,closed,deleted) — read-only, set by systemclassification: Work stage (draft,active,inactive) — settable via APIteaser.stage: Teaser progress (property_added,drafting,published,verified,communicated) — read-only, set by system
Custom Association Labels for Classifications
Create custom association labels in HubSpot to track prospect classifications:
# Create custom label for Deal-Contact associations
POST /crm/v4/associations/deal/contact/labels
{
"label": "Interested Investor",
"name": "interested_investor"
}
| Propstreet Classification | Suggested HubSpot Label |
|---|---|
| not_contacted | "Not Contacted" |
| contacted | "Contacted" |
| interested | "Interested Investor" |
| not_interested | "Not Interested" |
| bidder | "Bidder" |
Custom Properties to Create
Create these custom properties in HubSpot for real estate deal sync:
POST /crm/v3/properties/deals
{
"name": "propstreet_project_id",
"label": "Propstreet Project ID",
"type": "string",
"fieldType": "text",
"groupName": "dealinformation"
}
Recommended properties:
propstreet_project_id— For reverse lookupis_portfolio— Boolean for multi-property dealsproperty_count— Number of propertiesproperty_type— Office, Retail, Industrial, etc.
Sync Architecture
HubSpot → Propstreet (using Webhooks):
- Create a HubSpot private app with
crm.objects.deals.readscope - Subscribe to
deal.creation,deal.propertyChange,deal.deletionevents - Transform and push to Propstreet Projects API
- Store Propstreet IDs in custom properties
// Handle HubSpot webhook
async function handleHubSpotWebhook(payload) {
const { objectId, propertyName, propertyValue } = payload;
if (payload.subscriptionType === "deal.creation") {
const deal = await hubspot.get(`/crm/v3/objects/deals/${objectId}`);
const project = await propstreet.post("/api/v1/projects", {
name: deal.properties.dealname,
externalRefs: [{ namespace: "hubspot", id: String(objectId) }],
});
// Store Propstreet ID in HubSpot
await hubspot.patch(`/crm/v3/objects/deals/${objectId}`, {
properties: { propstreet_project_id: project.id },
});
}
}
Propstreet → HubSpot (using Webhooks):
- Register webhooks for
project.*andprospect.*events - Look up HubSpot Deal ID from
externalRefs - Update HubSpot via CRM API
// Handle Propstreet webhook
async function handlePropstreetWebhook(payload) {
const hubspotId = payload.data.externalRefs?.find(
(ref) => ref.namespace === "hubspot"
)?.id;
if (payload.event === "project.updated" && hubspotId) {
await hubspot.patch(`/crm/v3/objects/deals/${hubspotId}`, {
properties: { dealname: payload.data.name },
});
}
}
Webhook Events
Subscribe to these Propstreet events for deal sync:
| Event | Description | HubSpot Action |
|---|---|---|
| project.created | New project created | Create Deal |
| project.updated | Project fields modified | Update Deal properties |
| project.deleted | Project soft-deleted | Move to Closed Lost stage |
| prospect.created | Investor added to prospect list | Create Deal-Contact association |
| prospect.updated | Classification changed | Update association label |
| prospect.deleted | Investor deleted from prospect list | Remove Deal-Contact association |
Example: Create Project with HubSpot Reference
curl -X POST "https://app.propstreet.com/api/v1/projects" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "Nordic Office Portfolio",
"isPortfolio": true,
"propertyCount": 3,
"externalRefs": [{ "namespace": "hubspot", "id": "12345678" }]
}'
Example: Lookup Project by HubSpot ID
curl "https://app.propstreet.com/api/v1/projects/external/hubspot/12345678" \
-H "Authorization: Bearer $TOKEN"
Batch Operations
Both platforms support batch operations for efficient sync:
Propstreet: Add up to 100 prospects in a single request:
POST /api/v1/projects/{id}/prospects:batch
HubSpot: Create up to 100 associations per request:
POST /crm/v4/associations/deal/contact/batch/create