> ## Documentation Index
> Fetch the complete documentation index at: https://docs.opal.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# Hubspot

> Learn how to connect Opal to Hubspot to manage access.

With Opal's integration with HubSpot, you can manage access to **HubSpot users, teams, and roles (permission sets)**.

* **End users** can request just-in-time, time-bound access to HubSpot roles and teams from Opal's catalog, Slack, or the CLI.
* **Admins** can grant and revoke access, provision and deprovision HubSpot users, and delegate approvals with full audit trails.
* **Auditors and security teams** can run access reviews over HubSpot roles and team membership, and see every change as an event.

## Requirements

* You must be an Opal admin to set up the integration.
* You need a HubSpot **Super Admin** to create the legacy app and its access token.
* For self-hosted deployments, you must be on version \[fill in exact release] or later.
* Opal associates HubSpot users with Opal users through their **primary email address**.

## 1. Create a legacy app in HubSpot

In HubSpot, go to **Settings > Integrations > Legacy Apps** and select **Create a legacy app**. Give the app a name (for example, `Opal`). On the **Scopes** tab, add the following scopes:

```
settings.billing.write (to remove users from paid roles)
settings.users.read
settings.users.teams.read
settings.users.teams.write (to add and remove users from teams)
settings.users.write
```

These scopes let Opal read your users, teams, and roles, and (if enabled) provision users, manage team membership, and assign roles. If you only want read-only visibility and access reviews, you can omit `settings.users.write`.

**\[Optionally]** Add `settings.billing.write` if you want Opal to be able to deprovision users who hold paid seats. Without this scope, deprovisioning such a user fails with a clear error telling you to unassign the seat first.

<Note>
  These scopes cover HubSpot's user and account settings only. **Opal cannot read your CRM data** — contacts, companies, deals, tickets, and marketing content are outside what this token can access.
</Note>

Finally, select **Create app** and copy the access token.

## 2. Create the HubSpot app in Opal

In Opal, go to **Inventory > +App** and select the **HubSpot** tile.

| Field                    | Value                                     |
| ------------------------ | ----------------------------------------- |
| App name                 | A display name, for example `HubSpot`     |
| App admin                | The Opal owner responsible for this app   |
| Description              | Optional description shown in the catalog |
| Private app access token | The token from Step 1                     |
| Visibility               | Who can see this app in the catalog       |

Fill in the fields, then select **Create**. Opal validates the token and each scope immediately; results appear under the app's **Setup** tab (App Validations), and you can re-run them there any time.

## 3. Import assets

After the first sync completes, select the app's **... menu > Import items** to bring your HubSpot teams and roles into the Inventory. Your HubSpot users appear under the app's **Accounts** tab automatically.

## User provisioning

With provisioning enabled on the app, granting access to a person who doesn't yet have a HubSpot account creates one for them (they receive HubSpot's standard invite). If an account with the same email already exists, Opal uses it rather than creating a duplicate. With deprovisioning enabled, removing a user's last access removes their HubSpot account. Provisioning and deprovisioning are both opt-in settings on the app's edit page.

## Teams

HubSpot teams are mapped to Opal Groups: membership syncs into Opal, and adding or removing members in Opal updates HubSpot.

<Note>
  HubSpot's API has no way to remove a user from a single team. When Opal removes a team membership, it briefly clears the user's team list and immediately rebuilds the remaining memberships. During that short window the user may appear team-less in HubSpot; the next sync reconciles any difference. We would recommend making team changes all in one place.
</Note>

<Warning>
  In order to deprovision a Super Admin from Opal, they must first be demoted in Hubspot.
</Warning>

## Roles

HubSpot roles (permission sets) are available on\*\* HubSpot Enterprise plans\*\*. Two behaviors to know:

* A HubSpot user holds **one role at a time** — assigning a role through Opal replaces the user's existing role, matching how HubSpot's own admin UI behaves.
* Opal **refuses any assignment that would demote your account's last Super Admin**. A HubSpot account with zero Super Admins cannot be recovered from the HubSpot UI, so Opal fails that request with a clear error instead. (Super Admin itself can't be granted through the API — that always happens in HubSpot's settings.)

## FAQ

<AccordionGroup>
  <Accordion title="A grant failed with 'User could not be matched with an account on HubSpot'">
    The person has no HubSpot account with their Opal primary email. Either create their HubSpot user (or enable provisioning on the app) or correct the email mismatch, then retry.
  </Accordion>

  <Accordion title="Why don't I see any roles?">
    Roles require HubSpot Enterprise. Hubspot's role API is not available on other plans. Opal takes this into consideration on connection and continues syncing users and teams normally.
  </Accordion>

  <Accordion title="How do I rotate the token?">
    Create a new token in HubSpot (Private Apps > your app > rotate), then paste it in the app's **Setup** tab in Opal and re-run validations.
  </Accordion>

  <Accordion title="I changed a user's permissions in HubSpot but Opal doesn't show it.">
    Opal tracks named permission sets. Editing a user's individual permissions through HubSpot's **Edit access** flow creates custom per-user permissions, not a permission set, and HubSpot's API does not expose those — so they don't appear in Opal. Use **Assign permission set** in HubSpot for changes you want reflected in Opal.
  </Accordion>

  <Accordion title="What data does Opal store?">
    User IDs, names, and email addresses; team names and membership; role names and assignments — the minimum needed to show who has access to what. No CRM records are read or stored.
  </Accordion>
</AccordionGroup>
