# HubSpot Audience


<blockquote class="announcement">
  <div class="tip-quote">
    
    <div class="tip-text"><p>The <strong>HubSpot Audience</strong> destination is in <strong>Private Beta</strong>.</p>
<p>Reach out to <a href="mailto:support@rudderstack.com" >Customer Success</a> to enable it for your workspace.</p>
</div>
  </div>
</blockquote>

<p><a href="https://www.hubspot.com/" >HubSpot</a> is a CRM and marketing platform. <strong>HubSpot Audience</strong> keeps a HubSpot static contact list in sync with a warehouse table, SQL model, Audience Builder audience, or Lookout audience. You can attach an existing list or create a new empty list during setup. Incremental syncs add contacts who entered the source and remove contacts who left it.</p>

<html lang="en">
<blockquote class="info">
  <div class="tip-quote">
    
    <div class="tip-text"><p><strong>HubSpot Audience</strong> is separate from the Event Stream <a href="https://www.rudderstack.com/docs/destinations/streaming-destinations/hubspot/" >HubSpot</a> destination.</p>
<ul>
<li>Use <strong>HubSpot</strong> to create and update contacts and send Event Stream traffic.</li>
<li>Use <strong>HubSpot Audience</strong> only to change list membership. This sync does not create or update contacts.</li>
</ul></div>
  </div>
</blockquote>

</html>
<!-- end-chunk -->
<!-- begin-chunk -->
<h2 id="links">Links</h2><p>You can use the HubSpot Audience destination in these ways:</p>
<ul>
<li><a href="https://www.rudderstack.com/docs/destinations/reverse-etl-destinations/hubspot-audience/connect-retl-source/" >Connect a Reverse ETL source to HubSpot Audience</a></li>
<li><a href="https://www.rudderstack.com/docs/audiences/syncs/hubspot-audience/" >Sync from Audience Builder to HubSpot Audience</a></li>
<li><a href="#use-it-from-lookout" >Use it from Lookout</a></li>
</ul>

<blockquote class="announcement">
  <div class="tip-quote">
    
    <div class="tip-text">Syncing from <strong>Audience Builder</strong> to HubSpot Audience is possible only if Audience Builder is enabled for your workspace.</div>
  </div>
</blockquote>

<!-- end-chunk -->
<!-- begin-chunk -->
<h2 id="prerequisites">Prerequisites</h2><p>Authenticate with a HubSpot <a href="https://developers.hubspot.com/docs/apps/developer-platform/build-apps/authentication/account-service-keys" >Service Key</a>. The key needs these scopes:</p>
<table>
  <thead>
      <tr>
          <th>Scope</th>
          <th>Purpose</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><code>crm.lists.read</code></td>
          <td>List static contact lists and read the selected list.</td>
      </tr>
      <tr>
          <td><code>crm.lists.write</code></td>
          <td>Create a new contact list during setup, and add and remove list members.</td>
      </tr>
      <tr>
          <td><code>crm.objects.contacts.read</code></td>
          <td>Find contacts by email and check Record IDs.</td>
      </tr>
      <tr>
          <td><code>crm.objects.contacts.write</code></td>
          <td>Required by HubSpot for list membership changes. This scope also allows contact edits, so use a dedicated Service Key limited to the scopes above.</td>
      </tr>
  </tbody>
</table>
<p>Note that:</p>
<ul>
<li>When you attach an existing list, setup confirms that the list exists and can be read. It does not prove that the key has membership-write or contact-read scopes.</li>
<li>Creating a list during setup also requires <code>crm.lists.write</code>. A missing membership or contact-read scope fails later, during sync.</li>
<li>An existing HubSpot private app token (<code>pat-…</code>) with the same scopes also works for compatibility. Prefer a <a href="https://developers.hubspot.com/docs/apps/developer-platform/build-apps/authentication/account-service-keys" >Service Key</a> for new setups.</li>
</ul>
<!-- end-chunk -->
<!-- begin-chunk -->
<h2 id="how-membership-is-written-to-hubspot">How membership is written to HubSpot</h2><p>RudderStack supports only <a href="https://www.rudderstack.com/docs/data-pipelines/reverse-etl/developer-guides/sync-modes/#mirror-mode" >Mirror mode</a> for this destination.</p>
<table>
  <thead>
      <tr>
          <th>Action</th>
          <th>HubSpot operation</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Insert or update</td>
          <td>Add the resolved contact to the list.</td>
      </tr>
      <tr>
          <td>Delete</td>
          <td>Remove the resolved contact from the list.</td>
      </tr>
  </tbody>
</table>
<p>A full sync runs on the first run for a connection, after a data-mapping change, after a source schema change, and when you manually select <strong>Run full sync</strong>. A full sync adds current members but removes none. Members who left before a full sync can remain on the list after later incremental syncs. To remove them, remove the contacts in HubSpot or recreate the list and create a new RudderStack connection targeting it.</p>
<p>Row outcomes:</p>
<ul>
<li>An empty Record ID falls back to email when email is mapped. A well-formed Record ID that HubSpot does not know fails an add and counts as already gone on a delete.</li>
<li>An email that does not resolve to a HubSpot contact fails on both add and delete.</li>
<li>A failed delete can be retried on later runs when failed-record retry is enabled.</li>
<li>Changing the mapped contact identity can leave the previously resolved contact on the list. Inspect and clean up surviving memberships in HubSpot if needed.</li>
</ul>
<p>Membership requests send at most <strong>1,000</strong> contacts per request. Email lookup runs in groups of at most <strong>100</strong>.</p>
<!-- end-chunk -->
<!-- begin-chunk -->
<h2 id="if-a-sync-fails">If a sync fails</h2><p>Membership updates fail if the key lacks required write scopes, HubSpot rejects the key, or the selected list has been deleted.</p>
<ul>
<li><strong>Missing write permissions</strong>: Restore the <code>crm.lists.write</code> and <code>crm.objects.contacts.write</code> scopes on the key.</li>
<li><strong>Rejected or revoked key</strong>: Update the connected HubSpot account with a valid Service Key that has the required scopes.</li>
<li><strong>Deleted list</strong>: Create a new RudderStack connection targeting an existing or newly created static contact list. The original connection stays fixed to the deleted list ID.</li>
</ul>
<!-- end-chunk -->
<!-- begin-chunk -->
<h2 id="stop-a-sync">Stop a sync</h2><p>Disabling or deleting the RudderStack connection, or deleting a Lookout activation, does not call HubSpot. The list and its members stay as they are, including lists created during setup. Remove members or delete the list in HubSpot if you no longer want them.</p>
<!-- end-chunk -->
<!-- begin-chunk -->
<h2 id="use-it-from-lookout">Use it from Lookout</h2><p>The same HubSpot Audience destination is available when you <a href="https://www.rudderstack.com/docs/activate/lookout/audiences/activate-an-audience/" >activate an audience</a> in Rudder Lookout:</p>
<ol>
<li>Select <strong>HubSpot Audience</strong> as the destination type.</li>
<li>Choose a RudderStack account that uses a HubSpot Service Key. There is no ad-account step; the Service Key identifies the HubSpot portal.</li>
<li>Choose <strong>Use existing list</strong> (default) or <strong>Create new list</strong>. Create new list prefills the Lookout audience name; you can edit it before submitting.</li>
<li>Map identifiers using the same Record ID and email rules. See <a href="https://www.rudderstack.com/docs/destinations/reverse-etl-destinations/hubspot-audience/connect-retl-source/#map-identifiers" >Map identifiers</a>.</li>
<li>Choose a sync schedule and enable the sync.</li>
</ol>

<html lang="en">
<blockquote class="info">
  <div class="tip-quote">
    
    <div class="tip-text"><p><strong>Important considerations</strong></p>
<ul>
<li>Editing an activation keeps the HubSpot list fixed.</li>
<li>Renaming the Lookout audience does not rename the HubSpot list.</li>
</ul></div>
  </div>
</blockquote>

</html>

