Sync behavior & limitations

Stripe and HubSpot model data differently, and HubSpot rejects values that don’t fit its rules. The sync smooths over these differences so a run doesn’t fail on an edge case. Here’s what to expect.

Re-running is always safe (idempotent) #

Every Stripe record is matched to its HubSpot counterpart and updated in place — re-running a backfill or reconcile never creates duplicates, and re-syncing a record you already have is free (it doesn’t count toward your plan).

Customers can de-duplicate to one company #

Depending on your matching settings, multiple Stripe customers that share a domain (or name + domain) can map to a single HubSpot company rather than creating duplicates. Their subscriptions and invoices then associate to that one company.

Read-only HubSpot fields are skipped #

Some HubSpot properties are owned or derived by HubSpot and can’t be set via the API. We intentionally don’t write them, including:

  • the subscription Processor field,
  • the payment status on native invoices,
  • HubSpot’s external invoice id.

Stripe’s equivalents are stored in our own stripe_* properties instead, so the data is still on the record.

Negative line items (credits, discounts) sync at $0 #

Stripe invoice lines can be negative — credits, discounts, and proration adjustments. HubSpot does not allow a negative line price, so those lines sync with a price of $0. The invoice’s true net is always accurate because it’s carried on the invoice itself (stripe_amount_due / stripe_amount_paid), not summed from the line items.

Billing frequency is normalized #

Stripe expresses recurring intervals as an interval + count (e.g. every 3 months). We map these to HubSpot’s billing-frequency enum (monthly, quarterly, annually, …). A few combinations have no HubSpot equivalent — notably daily billing isn’t an option on products or line items — so the frequency is simply left unset on those records.

What happens when a Stripe object is deleted #

When a customer, price/product, or subscription is deleted in Stripe — either via a delete webhook, or detected as gone-from-Stripe during the nightly reconcile — you choose what happens to its HubSpot record. Set this per object on the Mappings page under When deleted in Stripe:

  • Keep (default) — leave the HubSpot record (and its link to Stripe) untouched. The CRM record has independent value, so nothing is changed. This is the default for every object, and matches how customers have always behaved.
  • Archive — soft-delete (archive) the HubSpot record and drop its Stripe link. For a customer this archives both the company and contact role.
  • Mark — keep the record but set a tombstone: stripe_deleted = Yes and stripe_deleted_date = <when>. The Stripe link is kept, so if the object later reappears in Stripe a normal sync clears the tombstone automatically. Marking requires the stripe_deleted / stripe_deleted_date fields to exist first — create them from the Custom fields panel before choosing this policy.

With Keep, reconcile skips the deletion scan for that object entirely (which is also faster).

Invoices are voided, not deleted #

In Stripe an invoice is voided or marked uncollectible rather than deleted, so we keep its HubSpot record and update its status. For that reason invoices are never pruned by reconcile and have no delete policy — the keep/archive/mark choice above applies only to customers, products, and subscriptions. See Running syncs.

Line items are derived #

Line items are never synced on their own — they’re created and kept in sync alongside their parent subscription or invoice, and don’t count toward your plan.

Amounts, dates, and currency #

  • Amounts are converted from Stripe’s smallest currency unit (cents) to the major unit (dollars).
  • Dates are written at UTC midnight for HubSpot date properties.
  • Currency is carried as its ISO code on the record.

Hitting a sync error you don’t see explained here? Open the run on the Sync page — each failed record shows the exact HubSpot message so you can see what happened.