# Ops Hubspot Property Mapper Stripe Sync

> Use when synchronizing Stripe billing data into HubSpot CRM contacts and deals. Defines the canonical field mapping from Stripe customer, subscription, and invoice objects to HubSpot contact and deal properties — ensuring AEs and CSMs always see current MRR, plan, renewal date, and payment health without manual data entry.

- Skill: `sboghossian-mini-claude-for-legal/ops-hubspot-property-mapper-stripe-sync` (Agent Skill)
- Install (CLI): `npx skillmds@latest add sboghossian-mini-claude-for-legal/ops-hubspot-property-mapper-stripe-sync`
- Raw SKILL.md: https://api.skillmd.com/api/skills/sboghossian-mini-claude-for-legal/ops-hubspot-property-mapper-stripe-sync/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Finance & Business
- License: MIT
- Author: sboghossian (https://skillmd.com/u/sboghossian-mini-claude-for-legal)
- Updated: 2026-09-10
- Page: https://skillmd.com/skills/sboghossian-mini-claude-for-legal/ops-hubspot-property-mapper-stripe-sync

---


# Ops — HubSpot Property Mapper (Stripe Sync)

## Purpose

Stripe is the source of truth for billing; HubSpot is the source of truth for sales and customer relationships. Without an automated sync, these systems drift apart — AEs quote the wrong renewal date, CSMs don't know a payment failed, and finance can't reconcile ARR against CRM data. This skill defines the exact field mapping and sync rules between the two systems.

## Architecture

**Direction**: Stripe → HubSpot. Stripe is always authoritative for billing data. HubSpot data is updated from Stripe; never the reverse (to avoid billing data corruption).

**Sync trigger**: Stripe webhooks. Every relevant Stripe event fires a sync to HubSpot. Additionally, a daily reconciliation job sweeps for any missed events.

**Relevant Stripe webhook events**:
- `customer.created`, `customer.updated`
- `customer.subscription.created`, `customer.subscription.updated`, `customer.subscription.deleted`
- `invoice.paid`, `invoice.payment_failed`
- `customer.subscription.trial_will_end`

## Field mapping

### Contact-level fields (Stripe Customer → HubSpot Contact)

| Stripe field | HubSpot property name | Type | Notes |
|--------------|----------------------|------|-------|
| `customer.id` | `stripe_customer_id` | Text | Immutable; set once |
| `customer.email` | Standard email field | Email | Used for deduplication |
| `customer.created` | `stripe_customer_since` | Date | When they first became a Stripe customer |

### Deal-level fields (Stripe Subscription → HubSpot Deal)

| Stripe field | HubSpot property name | Type | Notes |
|--------------|----------------------|------|-------|
| `subscription.status` | `subscription_status` | Dropdown | `trialing / active / past_due / canceled / unpaid` |
| `subscription.plan.nickname` | `product` | Text | Plan name (e.g., "Pro Monthly", "Business Annual") |
| `subscription.items.data[0].price.unit_amount / 100` | `mrr` | Currency | Monthly recurring revenue; annualize for annual plans |
| `subscription.current_period_end` | `renewal_date` | Date | When the current subscription period ends |
| `subscription.cancel_at_period_end` | `cancel_at_renewal` | Checkbox | True if user has requested cancellation effective at renewal |
| Latest `invoice.payment_failed` event | `at_risk` | Checkbox | Set to true on payment failure; cleared on successful payment |
| `subscription.trial_end` | `trial_end_date` | Date | When the trial expires; triggers trial-end workflow |

### Invoice-level properties (Stripe Invoice → HubSpot Activity)

- On `invoice.paid`: log a note on the deal with invoice amount, date, and Stripe invoice ID.
- On `invoice.payment_failed`: set `at_risk: true` on the deal and create a HubSpot task: "Follow up on failed payment within 24 hours."

## MRR calculation

- **Monthly plan**: `unit_amount / 100` directly.
- **Annual plan**: `unit_amount / (100 * 12)` for the monthly equivalent.
- **Multi-seat plans**: `unit_amount * quantity / 100` (monthly equivalent).

Store MRR as a USD amount in HubSpot regardless of the customer's billing currency. Currency conversion uses the Stripe invoice's exchange rate at the time of payment.

## Deduplication

Match Stripe customers to HubSpot contacts by email address (primary key). If a match is found, update the existing contact. If no match is found, create a new contact with the Stripe customer data and flag it for AE review (the customer may have signed up through a back-channel not tracked in HubSpot).

## Failure handling

- If a HubSpot API call fails during a sync, log the failure and enqueue for retry.
- After 3 retries, escalate to the ops Slack channel `#crm-sync-alerts`.
- The daily reconciliation job is the backstop — it resolves any events that were missed by failed webhook deliveries.

## Pair with

[[ops-hubspot-deal-stage-router]] updates deal stages based on product events; this skill keeps the financial properties of those deals current. The two skills together give AEs and CSMs a complete picture: where the customer is in their lifecycle (stage router) and what they are worth and whether they are at risk (property mapper).

## Related skills

- [[ops-hubspot-deal-stage-router]] — deal stage transitions that run alongside this property sync
- [[ops-subscription-erd-validator]] — validates the underlying data model for consistency
- [[ops-churn-risk-detector]] — uses `at_risk` and `subscription_status` as churn signals

