# HubSpot in a lifecycle audit

Where each audit area lives in HubSpot, how to read it without write access, and the behaviour that changes a finding. HubSpot often runs the newsletter, webinars and nurture next to a separate product lifecycle tool, which makes it the usual second sender in FC04, FC08 and MH03. Facts come from the HubSpot pages in `sources.yaml`, read on 2026-11-02 (the MCP integration page and the legacy app sunset again on 2026-11-06); items marked "verify live" were not confirmed that day and must be checked in the account or the live page before quoting.

## Read-only access

- Remote MCP server (`https://mcp.hubspot.com` for custom clients): OAuth 2.1 with PKCE, acting within the signed-in user's existing permissions, generally available since 13 April 2026. The server has write tools and no read-only mode, and new tools appear, so allow only the read tools below and set every other tool to deny (checked 2026-11-06).
- Read tools for the audit: `get_user_details` first (read and write access per object), `get_organization_details`, `discover_hubspot_schema`, `search_properties`, `get_properties`, `search_owners`, `get_campaign_attribution_reports`, `query_crm_data` for aggregate counts (call `tool_guidance` first) and `get_marketing_email_analytics` for aggregate stats only; it can also return per-contact engagement, so never ask for contact rows.
- Denied, among everything else: every `manage_*` tool, `submit_feedback`, and `search_crm_objects`, `get_crm_objects`, `search_conversations` and `read_campaign_data`, which return contact or conversation data.
- HubSpot's per-client connector guides name the approval setting (one guide labels the choices "Needs Approval" and "Always allow"); where a client has no deny setting, choose the ask-every-time option and approve only the listed tools.
- Super Admins and users with App Marketplace Access can connect without prior approval; other users need a Super Admin to approve the connector first.
- Alternative: an existing private app or a Service Key with read scopes only. Creation of legacy private apps was disabled for accounts created from 28 September 2026 and for older accounts from 26 October 2026; existing apps keep working, and HubSpot recommends Service Keys for new in-account integrations.
- After connecting, list the current tools; workflows, subscription types and some settings may still need UI reads or exports.
- Confirm the account (portal) the connection reads is the one the user named.

## Where each area lives

- Journey coverage: workflows (enrolment triggers, re-enrolment, unenrolment and suppression segments, goals), marketing emails, sequences.
- Caps: the account's marketing email frequency limit (label, scope and which emails count: verify live).
- Preferences: subscription types per brand, "Unsubscribed from all email", marketing contact status (a billing setting, not permission), data privacy settings that govern Not Specified.
- Segments: active and static segments (formerly lists) used as enrolment triggers and suppression segments.
- Deliverability: email sending domain connection and DKIM status (menu path: verify live); graymail suppression ("don't send to unengaged contacts"; definition and default: verify live).
- Measurement: attribution reports and their models; marketing email bot filtering status per send.

## Behaviour that changes findings

- Records enter a workflow the first time they meet the triggers and cannot re-enter while enrolled. Re-enrolment needs an eligible later trigger; turning the setting on alone does not re-enrol everyone (JC06).
- In contact-based workflows, unenrolling contacts that no longer meet the criteria is off by default and applies only to filter-based ("when a filter criteria is met") triggers. A suppression segment prevents enrolment and unenrols active contacts; removal from it does not enrol anyone (JC04).
- A workflow continues after a marketing email is skipped for a non-marketing contact, and the email is not resent when the status changes (FC06).
- A workflow's sequence enrolment is skipped when the user exceeds the daily send limit; the contact skips the action. Whether a reply unenrols other contacts at the same company: verify live.
- Subscription states: Subscribed, Unsubscribed, Not Specified; whether Not Specified contacts can be emailed depends on data privacy settings (PC05).
- HubSpot's sending requirements allow marketing email only to contacts who have not opted out of your emails or marked one as spam in another tool, so a missing suppression sync with the lifecycle tool is FC08.
- A data sync's filters only limit which records initially sync; once synced, records keep syncing through the property mapping. A filter that excluded unsubscribed contacts at setup is no evidence that later opt-outs are enforced (PC01).
- Marketing email bot filtering is on by default and configurable; the sent email's performance page shows its status. Record it for every send compared (SG02).
- Without a connected sending domain, mail goes out under a provider signing domain and fails DMARC alignment for the brand's From domain (DL05). Check a received message, not the settings page.

## Exports for the scripts

- Send log: email events through the API or an export (verify the current names live), keyed by contact ID and hashed in the warehouse. Numeric contact IDs are accepted by message_pressure.py but a salted hash is better.
- Preference log: subscription change history with its source, mapped to the script's source names (subscription preferences page to preference_centre, one-click to one_click, imports to import, integration writes to crm_sync).
- Inventory: workflow list with status, enrolment counts for the window and settings; marketing email list for recurring sends.

## Verify live

The frequency limit setting, the graymail definition and default, Automation API read endpoints and scopes, the sending domain menu path, company-wide sequence unenrolment, and the MCP tool list after connecting.
