HubSpot Integration — Overview
Connecting HubSpot is the first step to using FlowState. Once connected, FlowState reads your deals continuously and surfaces insights about stalled deals, data quality issues, win/loss trends, and rep performance — without you needing to export anything or open a separate dashboard.
For AWS Partners, the HubSpot connection is also how FlowState syncs your deals with AWS Partner Central automatically.
What the integration does
Reads from HubSpot
FlowState reads the following data from your HubSpot portal to power AI analysis and the deal pipeline view:
- Deals — all properties on each deal record, including stage, close date, amount, owner, and all associated contacts.
- Pipeline and stage definitions — used to map deal stages to APN lifecycle stages.
- Deal activities — notes, emails, calls, and tasks associated with deals (used for stalled-deal detection and action-item extraction).
- Contacts associated with deals — names and job titles used to populate APN opportunity contact fields. FlowState does not store contact personal data beyond what is needed to construct the APN payload.
Pipeline data is fetched once per day, at a per-tenant time FlowState assigns automatically when you enable the integration (a random time between 01:00 and 05:59 UTC, so every tenant’s fetch doesn’t land in the same minute) — and on demand right after you connect, or whenever you trigger a manual refresh.
Writes to HubSpot
On the deal record, FlowState writes only to the 10 custom properties in the flowstate_apn property group. These properties carry the status and result of each deal’s APN synchronisation. No other deal properties are modified. See Custom properties for the full list.
The property group is not created automatically when you connect — connecting only stores your OAuth tokens. Provisioning the properties is a separate, explicit step: click Provision properties on the HubSpot integration page (or call the provision_hubspot_properties MCP tool) after connecting.
After each APN outbound write, FlowState updates apn_sync_status on the deal record so your sales team can see sync state directly in HubSpot without needing to open FlowState. A sync error itself is not mirrored to a HubSpot property — it is shown live on the FlowState card (syncError) instead.
AWS opportunity team as HubSpot contacts
When AWS adds people to your opportunity (account owner, sales rep, partner sales manager, ISV success manager, etc.), FlowState mirrors each of them into HubSpot as a contact and associates that contact with the deal — so the AWS people working the co-sell appear directly in the deal’s contact list.
- Upsert by email — the member’s email is the unique key. If a contact with that email already exists in your portal, FlowState updates it; otherwise it creates a new one. Duplicates are never created.
- Properties set —
email,firstnameandlastname(only when AWS supplies a name — an email-only member is created with just the email and job title; names are never invented), andjobtitlederived from the AWS business title (e.g.AWSAccountOwner→ “AWS Account Owner”,AWSSalesRep→ “AWS Sales Representative”,PSM→ “AWS Partner Sales Manager”,ISVSM→ “ISV Success Manager”). Unrecognised titles fall back to the raw AWS value. - Association — the contact is linked to the deal via HubSpot’s default contact-to-deal association.
- Idempotent — the team is re-synced only when it actually changes, so repeated AWS events do not churn your contacts.
- Best-effort — contact sync never blocks the core deal-field sync; a failure on one contact is logged and skipped.
The apn_aws_* deal fields (account manager / sales rep / partner sales manager name + email) are still written as before — the contact sync is in addition to, not a replacement for, those fields.
Webhooks received from HubSpot
Once connected via OAuth, HubSpot sends real-time webhook events to FlowState for deal creation, deal deletion, and property changes on a fixed list of properties registered in FlowState’s HubSpot app. That list is kept identical, property for property, to the trigger set described below.
Every subscribed property triggers an outbound sync — the properties your team edits directly: apn_sync_with_aws_enabled, apn_business_problem, apn_aws_account_id, apn_mrr, apn_closed_lost_reason, apn_postal_code — plus the native dealname, dealstage, closedate, and amount. This set is derived automatically from the HubSpot→APN field mapping, not hand-maintained — a newly mapped, partner-editable field becomes reactive automatically. The AWS-mirrored writeback properties (apn_opportunity_id, apn_sync_status, apn_review_status, apn_lifecycle_stage) hold no webhook subscription at all — subscribing to them would only spend webhook deliveries on events that get discarded, and treating FlowState’s own writeback as a trigger would create an infinite webhook → sync → writeback loop. apn_partner_need, apn_use_case, apn_delivery_model, apn_sales_activity, apn_client_industry, apn_client_country, apn_currency and apn_state_region are excluded too, for a third reason: they are no longer HubSpot deal properties at all — a rep sets them through the FlowState card instead, into FlowState’s own store rather than a HubSpot property, so no webhook can ever fire for them (see Custom properties).
Each webhook event is HMAC-verified, deduplicated (HubSpot fans out one event per changed property; FlowState collapses these to one sync message per deal), and dispatched for outbound APN sync.
Data that is never accessed
- Contact email addresses beyond what is required to build APN contact payloads.
- Contact phone numbers, deal notes content, marketing email engagement data, company revenue fields outside of the APN field mapping, or any CRM object type other than deals and their directly associated contacts.
- Any data from HubSpot portals other than the one linked to your FlowState tenant.
Integration lifecycle
| State | Meaning |
|---|---|
connected | OAuth token validated. Webhooks active. Real-time APN sync enabled. |
disconnected | Either never connected, or intentionally disconnected by a tenant admin. Token deleted (if it existed); sync paused. |
These are the only two integration status values FlowState ever writes. There is no distinct not_connected or token_expired state: an integration that has never been connected reports disconnected the same way one that was explicitly disconnected does, and a HubSpot refresh-token failure does not change the stored status at all — see Permissions & scopes for what actually happens when a refresh fails.
The apn_sync_status property on each deal reflects the current sync state
independently of the integration status — historical sync state is preserved
even when the integration is disconnected.
Technical Reference
Webhook dispatch
FlowState uses a single shared HubSpot App that receives webhooks for all connected tenants. When a webhook arrives, the handler:
- Verifies the HubSpot HMAC v3 signature. Requests with invalid or missing signatures are rejected with 401.
- Extracts the portal ID from the payload and resolves it to your tenant.
- Records a short-lived idempotency marker so concurrent retries of the same event are deduplicated at this step.
- Fans out one sync message per logical change-set (HubSpot fires one event per changed property; FlowState collapses these).
Tenant isolation is enforced at the portal-to-tenant resolution step: a payload for one portal can only affect the tenant that owns it. FlowState verifies the authenticity of every webhook before processing it.