# HubSpot

Sync leads & opportunities with HubSpot for co-sell

---

## Overview

Integration with HubSpot enables the bi-directional referral & syncing between HubSpot opportunities and other partners like [APN Customer Engagements Program](https://aws.amazon.com/partners/programs/ace/) and thus makes co-selling possible.

### How the integration works

| | |
| --- | --- |
| **Direction** | Two-way. Referrals raised in HubSpot are pushed to the cloud partner programs; referral and marketplace state flows back onto the HubSpot records. |
| **Source of truth** | HubSpot owns the deal and company records. Suger owns referrals, offers and marketplace state, and writes them onto the linked HubSpot records. |
| **Scope** | Organization-level — one HubSpot connection per Suger organization, authorized through OAuth. |
| **Scheduled jobs** | CRM enrichment every **2 hours**, processing at most **10,000 records** per run by default. |
| **Credentials** | An OAuth authorization granting the scopes listed below. Suger requests a fixed set of required scopes plus optional ones that unlock individual features — a missing optional scope disables just that feature rather than the whole connection. |

### When something fails

- **Referral-state sync is on-demand, not scheduled.** Unlike enrichment, it runs only when you press **Sync**. If a write fails, the state does not repair itself on a later pass — press Sync again.
- **Enrichment writes go out in batches of 100 and a failed batch does not stop the run.** Failures are counted and the next batch proceeds, so one rejected record cannot block the rest of your deals. HubSpot's per-record errors inside a partially-successful batch are captured individually.
- **HubSpot API calls are not retried.** Requests have a 90-second timeout and a failure surfaces immediately rather than being retried in the background — deliberate for write paths, where a blind retry risks duplicating records. Enrichment activities themselves retry 2 to 3 times with backoff.
- **A very large search returns partial results rather than an error.** Paging stops after 100 pages (up to 20,000 records) and the result is flagged as truncated. Narrow the filter if you expect more.
- **Referrals are de-duplicated by HubSpot deal ID, and contacts by email**, so re-running a sync does not create a second copy of something Suger already linked.

## Prerequisite

It is strongly recommended that you create a user that is dedicated for integration purpose, either for Suger alone or for all integrations.
After integration, all Suger's operation on your HubSpot will be performed by this user.

We need the following permissions:

- `crm.schemas.companies.read`
- `crm.schemas.companies.write`
- `crm.schemas.contacts.read`
- `crm.schemas.contacts.write`
- `crm.schemas.deals.read`
- `crm.schemas.deals.write`
- `crm.objects.companies.read`
- `crm.objects.companies.write`
- `crm.objects.contacts.read`
- `crm.objects.contacts.write`
- `crm.objects.deals.read`
- `crm.objects.deals.write`
- `crm.objects.owners.read`

To satisfy this requirement, you need to ensure the delegation user
has "view" and "edit" permissions on CRM contacts, companies, and deals,
as well as permission to "edit property settings" and "App Marketplace access" for installing the app.

For example, the following permission set would suffice:

> <img src="/img/hubspot/hubspot_user_permissions.png" alt="CRM permissions for contacts, companies, and deals" style="max-width:880px;width:100%;display:inline;margin:0 auto;box-shadow: 5px 5px 5px #eee" />

> <img src="/img/hubspot/hubspot_user_permissions_settings.png" alt="Property settings and App Marketplace access permissions" style="max-width:880px;width:100%;display:inline;margin:0 auto;box-shadow: 5px 5px 5px #eee" />

## Create Integration

We created a HubSpot App called "Suger". You can easily complete the integration with the following steps:

1. Click the "Connect" button on the "Integrations" page.

2. HubSpot authorization page will open up in a new tab, asking you to login (if you haven't yet), and select an account to start the integration.

   > <img src="https://user-images.githubusercontent.com/3139481/224772225-db6d13e6-05ba-4edb-965e-36b3b83a2598.png" alt="HubSpot authorization page for account login" style="max-width:500px;width:100%;display:inline;margin:0 auto;box-shadow: 5px 5px 5px #eee" />

3. Login and select your account, and click "Choose Account".

4. Review the permissions, and click "Connect App".

5. The integration status will become "Created". Now locate the HubSpot integration in the view, and click "Verify".

   > <img src="/img/hubspot/verify_hubspot_integration.png" alt="Verify button on the HubSpot integration" style="max-width:880px;width:100%;display:inline;margin:0 auto;box-shadow: 5px 5px 5px #eee" />

6. Suger will attempt to read a few opportunities to verify the connection, after which the status will become "Verified" and start working.

7. Now you are all set!

## CRM Enrichment

CRM Enrichment allows you to automatically enrich HubSpot records with intelligence signals from Suger. This feature syncs valuable marketplace and engagement data directly to your CRM records, giving your sales team actionable insights without leaving HubSpot.

### Overview

With CRM Enrichment, you can:

- **Automatically populate CRM properties** with intelligence signals (engagement scores, marketplace metrics)
- **Configure multiple record types** (e.g., Deals, Companies) with different enrichment rules
- **Use JSON queries** to target specific records for enrichment
- **Map intelligence fields** to custom HubSpot properties

### Prerequisites

Before configuring enrichment, ensure you have:

1. **Custom properties created** in HubSpot to store the intelligence data

### Creating Custom Properties in HubSpot

You need to create custom properties in HubSpot to store the intelligence signals. For each signal you want to sync:

1. Go to **Settings** → **Data Management** → **Objects** → Select your object (e.g., Deals)
   > <img src="/img/integration/hubspot/enrichment-manage-properties.png" alt="HubSpot Data Management Objects settings page" style="max-width:880px;width:100%;display:inline;margin:0 auto;box-shadow:5px 5px 5px #eee" />

2. Click **Manage Deal properties** (or the equivalent for your object)

3. Click **Create property**
   > <img src="/img/integration/hubspot/enrichment-create-property.png" alt="Create property button in HubSpot" style="max-width:503px;width:100%;display:inline;margin:0 auto;box-shadow:5px 5px 5px #eee" />

4. Enter a **Property label** (e.g., "AZURE Engagement Score") and select the **Object type** and **Group**
   > <img src="/img/integration/hubspot/enrichment-property-details.png" alt="Property label, object type, and group fields" style="max-width:880px;width:100%;display:inline;margin:0 auto;box-shadow:5px 5px 5px #eee" />

5. Choose the appropriate **Field type** (e.g., **Single-line text** for scores and general data)
   > <img src="/img/integration/hubspot/enrichment-field-type.png" alt="Field type selection for the custom property" style="max-width:880px;width:100%;display:inline;margin:0 auto;box-shadow:5px 5px 5px #eee" />

6. Click **Create** to save the property

### Configuring Enrichment

1. Navigate to **Suger Console** → **Settings** →  **Integrations** → **HubSpot**
2. Click **Edit** to open the integration settings
3. Go to the **Enrichment** tab
4. Click **Add CRM Record** to create a new enrichment rule

> <img src="/img/integration/hubspot/enrichment-configuration.png" alt="Add CRM Record enrichment configuration in Suger Console" style="max-width:415px;width:100%;display:inline;margin:0 auto;box-shadow:5px 5px 5px #eee" />

For each configuration, specify:

| Setting | Description |
|---------|-------------|
| **CRM Record Type** | The HubSpot object to enrich (e.g., Deals, Companies) |
| **Field Mappings** | Map intelligence fields to your custom HubSpot properties |
| **HubSpot Search Query (JSON)** | JSON query to filter which records to enrich |
| **Update records that already have enrichment data** | Controls when previously enriched records are refreshed: **Never**, **Immediately**, or **Every N days** (default: 30 days) |
| **Max Records Per Sync** | Maximum number of records to process per sync run (default: 10,000, minimum: 1,000) |

After entering your query, click **Validate Query** to verify it is valid and see how many records match. This helps ensure your enrichment rule targets the right set of records before saving.

### Available Intelligence Fields

Intelligence signals are derived from multiple data sources:

- **Cloud partner data** — Engagement scores sourced directly from cloud partner programs (e.g., AWS Partner Network, Azure Partner Center, GCP Partner Advantage).
- **Marketplace activity** — Public marketplace metrics such as listing counts, review counts, and purchase history across AWS, Azure, and GCP marketplaces.

The following intelligence signals can be mapped to your CRM properties:

**AWS Signals**
- AWS Engagement Score
- AWS Marketplace Count
- AWS Marketplace Review Count
- AWS Marketplace Purchase Count

**Azure Signals**
- Azure Engagement Score
- Azure Event Score
- Azure Usage Score
- Azure Marketplace Count
- Azure Marketplace Review Count
- Azure Marketplace Purchase Count

**GCP Signals**
- GCP Engagement Score
- GCP Marketplace Count
- GCP Marketplace Review Count
- GCP Marketplace Purchase Count

### Example Configuration

To enrich Deals in the "Qualified to Buy" stage with AWS engagement data:

1. **CRM Record Type**: Deals
2. **Field Mappings**:
   - `AWS Engagement Score` → `aws_engagement_score`
3. **HubSpot Search Query (JSON)**:
   ```json
   {
      "filterGroups": [
      {
         "filters": [
            {
            "propertyName": "dealstage",
            "operator": "EQ",
            "value": "qualifiedtobuy"
            }
         ]
      }
      ]
   }
   ```

### How Enrichment Works

#### Sync Schedule

Suger runs a scheduled enrichment sync **every 2 hours**. During each sync, Suger automatically processes all configured enrichment rules for your organization.

#### Enrichment Process

Each sync goes through the following steps:

1. **Query your HubSpot account** using the configured JSON search query to identify records that need enrichment.
2. **Look up intelligence data** for each matching record based on the company's domain.
3. **Update the mapped properties** in HubSpot with the latest intelligence values.

#### Update Mechanism

Suger uses a smart two-step approach to ensure efficient and complete data coverage:

- **Step 1 — Enrich new records**: Every sync prioritizes records that have **not been enriched yet** (where the mapped properties are still empty). This ensures newly added or previously missed records receive intelligence data first.
- **Step 2 — Refresh existing records**: Once all new records have been enriched, Suger begins a **refresh cycle** — rotating through previously enriched records in batches to keep data up to date. This rotation continues across multiple syncs until all records have been refreshed, then a new cycle begins.

The **Update records that already have enrichment data** setting controls how the refresh cycle behaves:

| Setting | Behavior |
|---------|----------|
| **Never** | Only enrich records that have not been enriched before. Previously enriched records are never updated. |
| **Immediately** | Continuously rotate through all records, refreshing data without delay between cycles. |
| **Every N days** | Wait N days after completing a full refresh cycle before starting the next one (default: 30 days). |

#### Records Per Sync

Each sync processes up to a configurable maximum number of records. For HubSpot, the default and maximum is **10,000**. The minimum configurable value is **1,000**.

If your query matches more records than the configured limit, the remaining records are handled automatically:

- **New records (Step 1)**: Unenriched records will be picked up in the next sync since they still have empty fields — no progress tracking is needed.
- **Refresh cycle (Step 2)**: Suger tracks its cursor position across syncs to rotate through all records. For example, with 30,000 records and a limit of 10,000 per sync, the refresh cycle completes in 3 runs. Once a full cycle finishes, the next one starts based on your **Update records that already have enrichment data** setting.

#### Tracking Enrichment Progress

To monitor the status of your enrichment sync:

1. Go to the enrichment configuration for your record type
2. Expand **Advanced Configuration**
3. Click **Check Progress**

The progress panel shows:

| Field | Description |
|-------|-------------|
| **Status** | Current state — *Active* (only enriching new records, refresh disabled), *Not Started*, *In Progress*, or *Waiting* (cycle completed, waiting for next refresh interval) |
| **Cycle Progress** | Percentage of records processed in the current refresh cycle |
| **Records Processed** | Number of records processed out of total matching records |
| **Last Run** | When the last sync ran and how many records it processed |
| **Estimated Runs Remaining** | Approximate number of syncs needed to complete the current cycle |

#### Disabling Enrichment

To stop enrichment for a specific record type, toggle it **off** in the enrichment configuration. This removes the enrichment rule, and no further syncs will process that record type.

To temporarily pause enrichment without removing the configuration, set **Update records that already have enrichment data** to **Never** — this will only enrich new records with empty fields and skip all previously enriched records.

## Suger AI Tools

Suger AI uses a **middleware** strategy — wrapping the HubSpot CRM API directly.

> **Org-level only**: HubSpot tools use the org-level integration credentials.

**Contacts**

| Tool | Description |
|------|-------------|
| `hubspot_list_contacts` | List contacts with pagination |
| `hubspot_get_contact` | Get a contact by ID |
| `hubspot_create_contact` | Create a new contact |
| `hubspot_update_contact` | Update contact properties |

**Companies**

| Tool | Description |
|------|-------------|
| `hubspot_list_companies` | List companies with pagination |
| `hubspot_get_company` | Get a company by ID |
| `hubspot_create_company` | Create a new company |
| `hubspot_update_company` | Update company properties |

**Deals**

| Tool | Description |
|------|-------------|
| `hubspot_list_deals` | List deals with pagination |
| `hubspot_get_deal` | Get a deal by ID |
| `hubspot_create_deal` | Create a new deal |
| `hubspot_update_deal` | Update deal properties |

**Search & Associations**

| Tool | Description |
|------|-------------|
| `hubspot_search` | Search any CRM object type with filters |
| `hubspot_get_associations` | Get associations between CRM objects |

## Delete Integration

To delete the integration, simply click the 🗑️ button in the "Integrations" HubSpot card. We will remove any credentials in our system.
You can also stop the integration by uninstalling the Suger App in your HubSpot account settings.
