AstroBaaS

Customers & accounts

HubSpot CRM Sync

Paid pluginsize Mplanned, not built

Indicative price, not an offer: €34/mo; credential: we maintain HubSpot API integration, daily sync

Generated from docs/plan/paid/hubspot-crm-sync/PLAN.md in the AstroBaaS repository. Nothing described below is implemented — it is the written plan for it.

HubSpot CRM Sync automatically pushes customer profiles, order history, and product interactions to HubSpot, keeping the sales team’s view in sync with ecommerce reality.

The problem

Sales team lives in HubSpot; customer data from ecommerce is manual, stale, and errors accumulate.

What it does

  • OAuth flow to connect HubSpot account
  • Push new customers to HubSpot as contacts
  • Push orders as CRM deals or associations
  • Map custom fields (store customer_id to HubSpot property)
  • Daily sync of order status changes (paid, shipped, refunded)
  • Pull HubSpot notes/tags back into AstroBaaS (optional reverse sync)
  • Track sync status and last-sync timestamp
  • Retry failed syncs with exponential backoff
  • Filter which customer data to sync
  • Audit log every sync attempt and payload

What it deliberately does NOT do

Each boundary carries its reason. A boundary without a reason gets crossed by the next person who reads this.

  • HubSpot account creation (merchants must have HubSpot already) — reduces scope to data sync only
  • Field mapping UI for all HubSpot field types (custom text/int/date only) — no file/rich-text
  • Two-way customer update (HubSpot to AstroBaaS) — reduces latency/conflict; data flows ecom to CRM only
  • Sync frequency < daily (HubSpot API limits) — daily minimum
  • Multi-currency order line items as separate deals (one object per order) — out of scope

Data model

HubSpotConnection: store_id, access_token (encrypted), refresh_token, oauth_scope, installed_at, last_sync_at. HubSpotFieldMapping: connection_id, astrobaas_field, hubspot_property_id, field_type. HubSpotSyncLog: connection_id, entity_type, entity_id, payload (JSON), status, error_msg, synced_at. Migration: add 3 tables; encrypt tokens.

API

  • POST /admin/integrations/hubspot/connect
  • POST /admin/integrations/hubspot/callback
  • GET /admin/integrations/hubspot/status
  • POST /admin/integrations/hubspot/sync-now
  • GET /admin/integrations/hubspot/field-mappings
  • PATCH /admin/integrations/hubspot/field-mappings
  • POST /admin/integrations/hubspot/disconnect

Every route added here must also appear in src/pages/openapi.json.ts — a test fails the build if it does not.

Admin

Integration status card: connection state, last sync, error count. Field mapping builder: select AstroBaaS fields to HubSpot property lookup. Sync log viewer: filter by type/date, view payload and errors. Manual sync trigger. Settings: filter rules (e.g., orders > 100 EUR).

The seam — why this is paid

Core owns: customer database, order data, product/variant structure, order/customer hooks. Paid module owns: HubSpot API OAuth, field mapping UI, sync scheduling, payload templating, retry logic, token encryption.

Credential: HubSpot API key management, custom-property sync, contact dedup

Dependencies

  • customer-profiles

Acceptance checks

Each of these must be able to fail. Before claiming this is done, break the code deliberately and watch each one go red.

  • New customer in AstroBaaS syncs to HubSpot within 24 hours
  • Changing customer email syncs email update to HubSpot within 24 hours
  • Refunded order syncs with deal stage = Closed Lost
  • Syncing 500 orders/day does not exceed HubSpot rate limits
  • Disconnecting revokes token; re-sync fails with auth error
  • Customer created before sync enabled is synced on next daily run (catch-up)

Risks

Plaintext token in logs. HubSpot API outage causes silent failures. Misconfigured field mapping causes silent failures. Duplicate contacts if deduplication wrong. last_sync_at not atomically updated.

Commercial context

Suggested price€34/mo; credential: we maintain HubSpot API integration, daily sync
Rival anchorHubSpot: €0-3200/mo (CRM); integration fee: custom

The anchor is what the nearest equivalent charges on Shopify or Magento today. It is context for a pricing decision, not the decision.


Generated from the commerce plan. See docs/COMMERCE-PLAN.md for the full catalogue and ../../AI-GUIDE.md for how to work on this repository.