Migrating from HubSpot

HubSpot’s contact/company/deal model maps cleanly onto Primicornis when you treat objects as canonical and pipelines as opportunity graphs.

Source → Primicornis mapping

HubSpotPrimicornis target
Contactperson (or custom)
Companycompany or startup depending on thesis
Dealopportunity with stage ↔ pipeline mapping
OwnerMap to workspace members via email before import
AssociationsUse relation properties; maintain association labels as text metadata

Property mapping checklist

  1. Export HubSpot properties with internal names (hs_*, custom keys) — not display labels.
  2. Build a dictionary { hubspot_internal_name → primicornis_property_key }.
  3. Coerce enumerations (e.g., deal stage) to Primicornis select options before bulk insert.

Relationship order

  1. person, company / startup
  2. Link people ↔ companies (roles like founder, board)
  3. opportunity records with foreign relations to company + champion contact

Deduplication

  • Prefer HubSpot record id stored in a dedicated text property (hubspot_id).
  • Upsert strategy: IF EXISTS hubspot_id THEN PATCH ELSE POST.

CSV vs API migration

ModeWhen
CSVInitial bulk load, historic archives
APIIncremental sync, nightly delta pulls from HubSpot (private apps)

Gotchas

  • Multi-currency deals — normalize to workspace currency before import.
  • Marketing contacts — decide if they become person records or stay in a marketing object; mixing inflates CRM noise.
  • Automated sequences — disable HubSpot workflows during cut-over week to avoid ghost updates.

API-flavored sketch

bash
# Pseudocode: create startup with external ref
curl -X POST "$API/ws/$WS/object-definitions/$STARTUP_ID/records" \
  -H "Authorization: Bearer $PRIM_TOKEN" -H "Content-Type: application/json" \
  -d '{"properties":{"name":"Nova Labs","hubspot_company_id":"123456"}}'

Validate each batch with GET queries filtered by your external ID field before moving stages in pipeline imports.