Skip to content

Monday.com to HubSpot Migration: The CTO's Technical Guide

A CTO-level technical guide to migrating from Monday.com to HubSpot, covering API rate limits, data mapping, object translation, and edge cases.

Raaj Raaj · · 23 min read
Monday.com to HubSpot Migration: The CTO's Technical Guide
TALK TO AN ENGINEER

Planning a migration?

Get a free 30-min call with our engineers. We'll review your setup and map out a custom migration plan — no obligation.

Schedule a free call
  • 1,200+ migrations completed
  • Zero downtime guaranteed
  • Transparent, fixed pricing
  • Project success responsibility
  • Post-migration support included

Migrating from Monday.com to HubSpot is a data-architecture translation problem, not a drag-and-drop exercise. Monday.com stores everything in flexible boards where items are rows, columns are fields, and relationships between boards are opt-in via Connect Boards columns. HubSpot enforces a relational CRM schema where Contacts, Companies, and Deals are connected through an explicit Associations API, and custom objects require an Enterprise subscription.

Every structural gap between these two architectures is where data silently disappears if you don't engineer around it. A CSV export from Monday.com flattens your board relationships, strips file attachments, and leaves orphaned records on the HubSpot side. Monday's board export only covers table views and caps each export at 10,000 items. (support.monday.com)

If your data is flat and small, CSV can work. If you need to preserve account-contact-deal relationships, activity history, or files, plan an API-led migration or use a managed service.

This guide covers the exact API constraints on both sides, concrete object-mapping strategy, a comparison of every realistic migration approach, and the edge cases that cause silent data loss — so your team can choose the right path before writing a single line of migration code.

For a broader look at when CSVs work versus when they break, see Using CSVs for SaaS Data Migrations: Pros and Cons. If you're evaluating whether to separate the migration from your HubSpot implementation work, read Why Data Migration Isn't Implementation.

The Architectural Shift: Monday.com Boards vs. HubSpot's Relational Schema

Monday.com is a Work OS, not a relational database. Its hierarchy runs Workspace → Folders → Boards → Groups → Items → Subitems. CRM data is typically spread across multiple boards — a Leads board, a Contacts board, an Accounts board, and a Deals board — each with its own column schema. Relationships between these boards are created through Connect Boards columns, which link items across boards, and Mirror columns, which reflect data from connected boards. (support.monday.com)

The structural characteristics that affect migration:

  • No enforced schema. Any board can have any columns. Two "Contacts" boards in the same workspace can have entirely different fields.
  • Relationships are opt-in. Connect Boards columns are manually configured. There's no database-level foreign key enforcement. You can add up to 60 Connect Boards columns per board, with a limit of 10,000 linked items per board.
  • Subitems are separate boards. In classic boards, subitems live on a hidden child board with their own column structure. Multi-level boards (newer) support up to five layers of subitems on the same board.

HubSpot is a relational CRM. Standard objects are Contacts, Companies, Deals, Tickets, and Products, connected by an explicit Associations API. Every record has a defined type, a fixed set of default properties, and custom properties you add. Relationships are first-class citizens — a Contact is associated with a Company, a Deal is associated with both.

Monday.com HubSpot
Board = any entity Object = typed entity (Contact, Company, Deal, Custom Object)
Columns = flexible, per-board Properties = typed, per-object
Connect Boards = opt-in links Associations API = explicit, typed relationships
Subitems = nested child board No native nesting — use associations or line items
No hard schema enforcement Schema enforced at the platform level
Custom columns on any board Custom objects require Enterprise (max 10 definitions by default)

Forcing Monday.com's unstructured data into HubSpot's structured environment requires heavy transformation before you load a single record.

Pre-Migration Planning and Board Auditing

Before you map a single field, audit what you're actually migrating. Monday.com accounts accumulate boards, columns, and automations over years. Most migrations move 40–60% of the data that actually exists.

Board Inventory Checklist

  • List all CRM-related boards. Leads, Contacts, Accounts/Companies, Deals, Activities. Include any custom boards used for project tracking or support that feed your sales process.
  • Identify Connect Boards columns. These define your relationship graph. Document which boards link to which, and the cardinality (one-to-many, many-to-many).
  • Audit column types. Monday.com supports 30+ column types (Status, People, Date, Timeline, Formula, Mirror, Connect Boards, File, etc.). Map each to a HubSpot property type.
  • Count subitems. Subitems on classic boards live on a hidden child board. Decide whether they become standalone HubSpot records, line items, or notes.
  • Consolidate redundant columns. Monday users often create multiple columns for the same data point (e.g., "Phone," "Mobile," "Work Phone"). Map these to a single HubSpot property.
  • Document automations. Monday.com automations don't transfer. Catalog them — you'll rebuild them as HubSpot Workflows.
  • Identify unused or redundant data. Archived boards, test items, empty columns. Don't migrate noise.

Define Migration Scope

Decide explicitly: big bang (everything at once), phased (object by object over days/weeks), or incremental (migrate historical data, then sync delta). For most Monday.com-to-HubSpot moves, a phased approach works best — migrate Companies first, then Contacts, then Deals, then Activities — because HubSpot's Associations API requires the parent record to exist before you can link a child.

For large or revenue-critical programs, phased or incremental is usually safer because it gives you time to validate associations and workflow behavior before you turn Monday off.

Risk Mitigation

  • Back up everything. Export all boards to CSV and store them. Use the Monday.com API to pull the full dataset including file URLs. Note: the full account export can include all boards and uploaded files, but admins can trigger it only once every 24 hours, and large exports can take up to 24 hours to finish. (support.monday.com)
  • Run in a HubSpot sandbox first. HubSpot sandbox accounts (available on Professional and Enterprise) let you validate the full migration without touching production.
  • Define rollback criteria. What record-count thresholds or data-quality checks must pass before you cut over?

Do not plan your final cutover around a last-minute full-account export. If the backup takes hours, your rollback window is already worse than you think.

For a comprehensive pre-migration checklist tailored to HubSpot, see our HubSpot Service Hub Migration Checklist.

Data Model & Object Mapping: Monday.com → HubSpot

This is the most consequential section of your migration planning. Get the object mapping wrong, and everything downstream breaks.

Core Object Mapping

Monday.com Board/Entity HubSpot Object Notes
Accounts board Companies Map company name, domain, industry, and address fields. Match by domain or explicit external ID, not display name.
Contacts board Contacts Map email (required unique identifier), name, phone, lifecycle stage.
Leads board Contacts (with Lifecycle Stage = Lead) or Leads HubSpot's Leads object requires Sales Hub Professional or Enterprise and must be associated with an existing Contact. If the target portal doesn't support the Leads object, map Monday leads as Contacts with qualification metadata. (knowledge.hubspot.com)
Deals board Deals Map deal name, amount, stage, close date. Pipeline stages must be pre-created in HubSpot.
Activities (items/subitems/updates) Engagements (Notes, Tasks, Calls, Emails, Meetings) Monday.com updates → HubSpot Notes. Tasks → HubSpot Tasks. Choose target activity type deliberately.
Custom boards (e.g., Products, Projects) Custom Objects (Enterprise only) or flattened into existing objects Requires HubSpot Enterprise. Max 10 custom object definitions by default.

Field-Level Mapping Decisions

Monday.com columns don't map 1:1 to HubSpot properties. Key translation challenges:

  • Status columns → HubSpot dropdown/select properties. Create the dropdown options in HubSpot first and use the internal value (not the label) when importing via API.
  • People columns → HubSpot owner properties. Map Monday.com user IDs to HubSpot owner IDs.
  • Timeline columns → Two separate HubSpot date properties (start date, end date). HubSpot has no native date-range property.
  • Formula columns → HubSpot calculated properties (requires Operations Hub Professional+). Or pre-compute the value and store it as a static property.
  • Mirror columns → Read-only reflections of data on connected boards. Don't migrate them — migrate the source data instead.
  • Connect Boards columns → HubSpot Associations. Must be rebuilt using the Associations API after both sides of the relationship exist in HubSpot.
  • File columns → HubSpot file attachments associated with records via the Engagements API. Files in Monday.com are stored as temporary AWS S3 URLs — you must download them before the URLs expire and re-upload to HubSpot.
  • Date columns → Convert to Unix timestamp (midnight UTC). Timezone shifts can silently shift dates by one day if not handled.

Sample Data Mapping Table

Monday.com Column Column Type HubSpot Property Property Type Transformation
Item Name name dealname / firstname Text Direct
Email email email Text Direct; used as unique ID for contacts
Phone phone phone Text Normalize format
Status status dealstage or custom dropdown Enumeration Map labels to internal values
Person (Owner) people hubspot_owner_id Owner Map Monday user IDs → HubSpot owner IDs
Date date Custom date property Date Convert to Unix timestamp (midnight UTC)
Timeline timeline Two date properties (start/end) Date Split into two fields
Numbers numeric Custom number property Number Direct
Long Text long_text Custom textarea property Text Direct
Dropdown dropdown Custom dropdown property Enumeration Map values to internal options
File file Engagement attachment File Download from S3 URL → upload to HubSpot Files API
Connect Boards board_relation Association Association Rebuild via Associations API after both records exist
Mirror mirror (skip) Don't migrate — it's a reflection of source data
Subitems subtasks Notes, Tasks, or Line Items Varies Decide per use case

Handling Custom Objects

HubSpot custom objects are Enterprise-only. An account can have a maximum of 10 custom object definitions by default, with up to 2 million records per custom object on Enterprise. Limit increases add 10 more objects and 1,000,000 more records per pack, up to a platform-wide ceiling of 50,000,000 custom object records per account. (knowledge.hubspot.com)

If your Monday.com account has boards that don't map to Contacts, Companies, Deals, or Tickets, you have three options:

  1. Create a HubSpot Custom Object (Enterprise only). Best for entities with an independent lifecycle and complex relationships.
  2. Flatten into custom properties on an existing object. If a board has a 1:1 relationship with a Deal (e.g., a Project Plan board), add its columns as custom properties on the Deal object.
  3. Use HubSpot Notes or Activities. For unstructured data that needs to be preserved but doesn't need to be queryable.

Use custom objects only when a Monday board represents a real business entity. Do not create a custom object just to preserve board sprawl.

HubSpot custom objects have significant limitations compared to Monday.com's freeform boards: no Timeline API support, no Webhooks API support, and limited AI/reporting integration as of 2026. Plan your schema carefully — restructuring custom objects after migration is expensive.

If you have very wide boards, trim them before migration. HubSpot import files must contain fewer than 1,000 columns. A board with hundreds of one-off columns usually needs normalization before it reaches HubSpot. (knowledge.hubspot.com)

Migration Approaches: CSV vs. API vs. iPaaS vs. Managed Service

1. Native CSV Export/Import

How it works: Export each Monday.com board to CSV. Clean the data in a spreadsheet. Import into HubSpot using the built-in import wizard.

When to use it: Small datasets (<1,000 records), flat data without cross-board relationships, or as a quick proof-of-concept.

Pros:

  • Zero engineering effort
  • Free
  • Easy to rehearse

Cons:

  • Destroys relationships. Connect Boards columns export as text, not as linkable references. You lose all Account → Contact → Deal chains.
  • Drops files. File columns export as URLs that expire. You can't import files into HubSpot via CSV.
  • Drops subitems. Subitems don't export with their parent item in a usable format.
  • No automation migration. Monday.com automations are not exportable.
  • Export cap. Board-to-Excel export covers table views only, capped at 10,000 items per export. (support.monday.com)

HubSpot's import tool can handle files up to 512 MB and up to 1,048,576 rows per file on paid plans. Monday.com's source-side export limits are usually the bottleneck. (knowledge.hubspot.com)

Complexity: Low | Scalability: Small datasets only

2. API-Based Migration (ETL Pipeline)

How it works: Custom scripts extract data from Monday.com's GraphQL API, transform it to match HubSpot's schema, and load it using HubSpot's REST API (CRM v3 endpoints). At its most mature, this becomes a full ETL pipeline with a staging database, checkpoints, dead-letter handling, and audit logs.

When to use it: Any migration where you care about preserving relationships, file attachments, or data fidelity at scale.

Pros:

  • Full control over mapping, transformation, and error handling
  • Preserves relationships by creating records in dependency order and using the Associations API
  • Handles files, subitems, and custom objects
  • Repeatable and testable

Cons:

  • Significant engineering investment (80–200+ hours depending on complexity)
  • Must handle rate limits, pagination, retries, and partial failures on both sides
  • Must maintain and debug the pipeline

Complexity: High | Scalability: Enterprise-grade

3. Middleware / iPaaS (Zapier, Make)

How it works: Configure triggers and actions in Zapier or Make to map Monday.com board events to HubSpot record creation. Make supports Monday.com's GraphQL API via custom HTTP modules with cursor-based pagination. Monday.com also has a native HubSpot integration, but it's designed for ongoing sync of certain non-custom fields, not bulk historical migration. (zapier.com)

When to use it: Ongoing sync of new records after the bulk migration is complete. Small-volume continuous sync (<500 records/day).

Pros:

  • No code required for basic mappings
  • Good for post-migration sync
  • Visual workflow builder

Cons:

  • Not designed for bulk historical migration. Zapier processes records one at a time. Migrating 50,000 records would require 50,000 task executions.
  • Rate limit collisions. iPaaS tools don't natively respect Monday.com's complexity limits or HubSpot's burst limits. They retry blindly.
  • Expensive at scale. Zapier pricing is per-task. A 50K-record migration could cost hundreds of dollars in task fees alone.
  • Limited transformation. Complex field-type conversions (Timeline → two dates, Status → internal value mapping) are awkward in visual builders.

Complexity: Medium | Scalability: Small ongoing sync only

4. Managed Migration Service

How it works: A specialist team builds and executes the migration pipeline for you, handling API constraints, edge cases, and validation.

When to use it: When engineering bandwidth is limited, when data complexity is high (multi-board relationships, file attachments, custom objects), or when you can't afford a failed migration.

Pros:

  • Fastest time to completion
  • All edge cases handled by experienced engineers
  • Built-in validation and rollback
  • Zero engineering distraction from your team

Cons:

  • External cost
  • Requires trust in the service provider's process

Complexity: Low (for you) | Scalability: Enterprise-grade

Comparison Table

Approach Relationships Preserved Files Migrated Handles Scale Engineering Effort Cost
CSV Export/Import Small only None Free
Custom API/ETL Pipeline Enterprise 80–200+ hours Engineering time
iPaaS (Zapier/Make) Partial Small sync 10–40 hours Platform fees
Managed Service Enterprise Near-zero Service fee

Recommendations by Scenario

  • Small business, <1K records, no cross-board relationships: CSV export/import is fine. Accept the manual cleanup.
  • Mid-market, 1K–50K records, preserving relationships matters: Custom API pipeline or managed service. Budget 2–4 weeks of dev time for DIY.
  • Enterprise, 50K+ records, custom objects, file attachments: Managed service or a senior-engineer-led ETL pipeline with a dedicated QA process.
  • Ongoing sync (not one-time migration): Use an iPaaS for new records, with API pipeline or managed service for historical backfill. Do not treat middleware as the migration engine.

API Rate Limits and Constraints: The Technical Deep Dive

Rate limits define the ceiling of your migration throughput. Ignoring them doesn't just slow you down — it burns API quota on failed retries.

Monday.com API Limits

Monday.com uses a GraphQL API with complexity-based rate limiting, not purely request-based.

Limit Type Value Scope
Complexity limit 10,000,000 points/minute Per account
Per-query complexity ceiling 5,000,000 points Per query
Daily call limit (Free) 200 calls/day Per account
Daily call limit (Basic/Standard) 1,000 calls/day Per account
Daily call limit (Pro) 10,000 calls/day Per account
Daily call limit (Enterprise) 25,000 calls/day Per account
Pagination page size Max 500 items per query Per request
Cursor expiration 60 minutes Per cursor

The daily call limits are the real bottleneck for migration. On a Standard plan, you have 1,000 API calls per day — and every failed request counts toward the limit. Enterprise's 25,000/day is workable for most migrations but still requires careful planning.

In current Monday API versions, older approaches that read Connect Boards relationship data from the generic value payload are brittle. Query linked_item_ids or linked_items directly. On multi-level boards, items_page returns top-level items by default unless you pass hierarchy_scope_config: allItems. (developer.monday.com)

HubSpot API Limits

HubSpot uses a token bucket rate-limiting model with two independent limits:

Limit Type Value Scope
Burst limit (Private apps, Free/Starter) 100 requests/10 seconds Per app
Burst limit (Private apps, Pro/Enterprise) 190 requests/10 seconds Per app
Burst limit (Public/Marketplace apps) 110 requests/10 seconds Per installed account
Daily limit (Free/Starter) 250,000 requests/day Shared across all private apps
Daily limit (Professional) 500,000–650,000 requests/day Shared across all private apps
Daily limit (Enterprise) Up to 1,000,000 requests/day Shared across all private apps
CRM Search API 4 requests/second Shared across all object types
Batch create endpoint 100 records/request Per request
Associations Batch Read 1,000 IDs/request Per request
Associations Batch Create 2,000 per request Per request

The daily limit is shared across all private apps in the account. If you have other integrations running (marketing automation, sales tools), they compete for the same quota. (developers.hubspot.com)

OAuth apps built through a developer account get separate, often higher daily limits. For large migrations, creating a dedicated HubSpot developer app with OAuth2 auth avoids depleting the private app quota that your other integrations depend on.

The CRM Search API at 4 requests/second is often the real bottleneck during migration. If you're using search for deduplication checks before creating records (which you should), this becomes your primary constraint — not the burst limit. Search results also cap at 10,000 total per query and 200 records per page, so don't build your migration around per-record search lookups after every create. Use returned IDs and a staging map instead.

HubSpot also exhibits eventual consistency: reads immediately after writes may return stale data. Build delays into association creation steps to avoid failures caused by records that haven't propagated yet.

Implementing Rate Limit Handling

Both APIs return Retry-After headers when you hit limits. Your migration script must:

  1. Read the Retry-After header and wait the specified duration.
  2. Implement exponential backoff with jitter — not a fixed sleep. A fixed sleep(100) wastes throughput.
  3. Track complexity budget client-side (Monday.com) by adding the complexity field to every query.
  4. Track daily quota consumption to avoid hitting the wall mid-day and losing the rest of the migration window.
  5. Persist checkpoints after each successful batch so a partial failure doesn't force a full rerun. (developer.monday.com)

Step-by-Step Migration with Code Examples

Phase 1: Extract from Monday.com

Use the GraphQL API to pull all items, column values, subitems, and updates from each board. Track complexity budget with every request.

import requests
import time
 
MONDAY_API_URL = "https://api.monday.com/v2"
MONDAY_TOKEN = "your_monday_api_token"
 
def extract_board_items(board_id, limit=500):
    """Extract all items from a Monday.com board with cursor-based pagination."""
    all_items = []
    cursor = None
 
    query = """
    query ($boardId: [ID!]!) {
      complexity { before after reset_in_x_seconds }
      boards(ids: $boardId) {
        items_page(limit: %d) {
          cursor
          items {
            id
            name
            group { title }
            column_values {
              id
              text
              value
              type
              column { title }
            }
            subitems {
              id
              name
              column_values { id text value type }
            }
          }
        }
      }
    }
    """ % limit
 
    headers = {
        "Authorization": MONDAY_TOKEN,
        "Content-Type": "application/json"
    }
 
    response = requests.post(
        MONDAY_API_URL,
        json={"query": query, "variables": {"boardId": [str(board_id)]}},
        headers=headers
    )
    data = response.json()
 
    page = data["data"]["boards"][0]["items_page"]
    all_items.extend(page["items"])
    cursor = page["cursor"]
 
    while cursor:
        next_query = """
        query ($cursor: String!) {
          complexity { before after reset_in_x_seconds }
          next_items_page(cursor: $cursor, limit: %d) {
            cursor
            items {
              id
              name
              column_values { id text value type column { title } }
              subitems { id name column_values { id text value type } }
            }
          }
        }
        """ % limit
 
        response = requests.post(
            MONDAY_API_URL,
            json={"query": next_query, "variables": {"cursor": cursor}},
            headers=headers
        )
        data = response.json()
 
        # Check complexity and back off if needed
        complexity = data.get("data", {}).get("complexity", {})
        if complexity.get("after", 10000000) < 1000000:
            wait = complexity.get("reset_in_x_seconds", 60)
            time.sleep(wait)
 
        next_page = data["data"]["next_items_page"]
        all_items.extend(next_page["items"])
        cursor = next_page["cursor"]
 
    return all_items

Phase 2: Transform

Clean and map the extracted data to HubSpot's property schema. Handle type-specific conversions.

def transform_contact(monday_item, column_mapping):
    """Transform a Monday.com item into a HubSpot Contact payload."""
    properties = {}
    for col in monday_item["column_values"]:
        hs_property = column_mapping.get(col["id"])
        if not hs_property:
            continue
 
        value = col["text"] or ""
 
        # Type-specific transformations
        if col["type"] == "date":
            # Monday: "2024-06-15" → HubSpot: midnight UTC timestamp
            value = date_to_hubspot_timestamp(value)
        elif col["type"] in ("dropdown", "status"):
            # Map Monday label to HubSpot internal value
            value = STATUS_MAP.get(value, value).lower().replace(" ", "_")
        elif col["type"] == "numeric":
            value = str(value) if value else ""
 
        properties[hs_property] = value
 
    return {"properties": properties}

Phase 3: Load into HubSpot

Use batch endpoints (100 records per request) to maximize throughput within rate limits.

import time
import random
 
HUBSPOT_API_URL = "https://api.hubapi.com"
HUBSPOT_TOKEN = "your_hubspot_private_app_token"
 
def batch_create_hubspot_records(object_type, records, batch_size=100):
    """Create records in HubSpot with rate limit handling."""
    headers = {
        "Authorization": f"Bearer {HUBSPOT_TOKEN}",
        "Content-Type": "application/json"
    }
    created_ids = []
 
    for i in range(0, len(records), batch_size):
        batch = records[i:i + batch_size]
        payload = {"inputs": batch}
 
        while True:
            response = requests.post(
                f"{HUBSPOT_API_URL}/crm/v3/objects/{object_type}/batch/create",
                json=payload,
                headers=headers
            )
 
            if response.status_code == 429:
                # Exponential backoff with jitter
                retry_after = int(response.headers.get("Retry-After", 10))
                jitter = random.uniform(0, 2)
                time.sleep(retry_after + jitter)
                continue
 
            if response.status_code in (200, 201):
                results = response.json().get("results", [])
                created_ids.extend(
                    [(r["id"], batch[idx]) for idx, r in enumerate(results)]
                )
                break
            else:
                log_error(response.status_code, response.json(), batch)
                break
 
        time.sleep(0.1)  # Minimum breathing room between batches
 
    return created_ids

Phase 4: Rebuild Associations

def create_associations(mapping_table, monday_connections, association_type_id):
    """Rebuild Connect Boards relationships as HubSpot associations."""
    headers = {
        "Authorization": f"Bearer {HUBSPOT_TOKEN}",
        "Content-Type": "application/json"
    }
 
    for monday_from_id, monday_to_id in monday_connections:
        hs_from_id = mapping_table.get(monday_from_id)
        hs_to_id = mapping_table.get(monday_to_id)
 
        if not hs_from_id or not hs_to_id:
            log_warning(f"Missing mapping: {monday_from_id}{monday_to_id}")
            continue
 
        payload = {
            "inputs": [{
                "from": {"id": hs_from_id},
                "to": {"id": hs_to_id},
                "types": [{
                    "associationCategory": "HUBSPOT_DEFINED",
                    "associationTypeId": association_type_id
                }]
            }]
        }
 
        response = requests.post(
            f"{HUBSPOT_API_URL}/crm/v4/associations/contacts/companies/batch/create",
            json=payload,
            headers=headers
        )
        handle_rate_limit(response)

The high-level orchestration follows this pattern:

def migrate(board_ids):
    id_map = {}
 
    # Load base objects in dependency order
    for board_id in board_ids:
        for item in monday.iter_items(board_id, include_all_items=True):
            row = normalize(item)
            record = hubspot.upsert_object(row.object_type, row.properties)
            id_map[item.id] = record.id
 
    # Rebuild relationships from Connect Boards links
    for link in extract_links(board_ids):
        hubspot.create_association(
            from_id=id_map[link.from_item_id],
            to_id=id_map[link.to_item_id],
            label=link.label
        )
 
    # Extract files, upload, and attach
    for file in extract_files(board_ids):
        uploaded = hubspot.upload_file(file.binary)
        hubspot.attach_file_note(id_map[file.parent_item_id], uploaded.id)
 
    validate(id_map)

In production, wrap upsert_object, create_association, and file upload in retry logic with checkpoints so a partial failure doesn't force a full rerun.

Edge Cases: Subitems, Files, Connected Boards, and Duplicates

These are the failure modes that catch teams off guard after the "happy path" works in testing.

Subitems

In classic Monday.com boards, subitems live on a separate hidden board. The parent item's ID links to the subitem board, but the API requires you to query the subitems board separately. In newer multi-level boards, subitems share the same board ID but use parent_item references to define hierarchy.

HubSpot has no native concept of subitems. Your options:

  • Flatten to Engagements (Notes/Tasks). Best for activity-type subitems.
  • Promote to standalone records. If subitems represent real entities (e.g., line items on a deal), create them as HubSpot records and associate them.
  • Concatenate into a property. For low-value subitems, concatenate them into a multi-line text property on the parent record.

File Attachments

Monday.com file columns store files as temporary AWS S3 URLs with an expiration window. Your migration pipeline must:

  1. Extract the file URL from the Monday.com API response (column_valuesFileValue type). (developer.monday.com)
  2. Download the file immediately.
  3. Upload it to HubSpot using the Files API (/files/v3/files).
  4. Associate the file with the correct HubSpot record via the Engagements API (create a Note with the file attached).

CSV exports include the URL string, but by the time you import into HubSpot, the URL is likely expired and useless.

Connected Boards → Associations

Connect Boards columns define relationships between items on different boards. This is the single biggest reason CSV migration fails — there's no way to preserve these links without the API. Migrating them requires:

  1. Build a mapping table during extraction: {monday_item_id: hubspot_record_id} for every record you create.
  2. Create records in dependency order. Companies first, then Contacts, then Deals.
  3. Create associations using the mapping table. For each Connect Boards link, look up both sides in your mapping table and call HubSpot's Associations API. (developers.hubspot.com)

If Monday has an Account board connected to a Contact board, which is connected to a Deal board, you must extract all three, map the internal Monday Item IDs to their new HubSpot Object IDs, and pass them through the Associations API.

Duplicate Records

Monday.com doesn't enforce uniqueness. You can have five items with the same email address across three boards. HubSpot enforces email uniqueness on Contacts and domain uniqueness on Companies.

Your transform step must:

  • Deduplicate contacts by email before import.
  • Merge or flag duplicate companies by domain.
  • Decide which duplicate is the "winner" and carry over the most complete data.

Updates and Activity Log

Monday.com's item Updates section (threaded comments on each item) contains valuable context — call notes, internal discussions, client communications. The API exposes these via the updates query. Map them to HubSpot Notes associated with the corresponding record.

Monday's Updates support rich text and internal mentions. Parse these into clean HTML before pushing to HubSpot's Engagements API to avoid broken formatting.

Historical Activity

HubSpot can import records and activities together, but existing emails, meetings, notes, and tasks cannot be updated through import. If you care about preserving timestamps, attachments, and associations on old activity, API-led loading is the only safe path. (knowledge.hubspot.com)

Validation, Testing, and Rollback

A migration without validation is a gamble. Build validation into every phase.

Record Count Comparison

Object Monday.com Count HubSpot Count Delta Status
Companies Query items_page count GET /crm/v3/objects/companies 0 expected ✅ / ❌
Contacts Query items_page count GET /crm/v3/objects/contacts 0 expected ✅ / ❌
Deals Query items_page count GET /crm/v3/objects/deals 0 expected ✅ / ❌

Field-Level Validation

Sample 5–10% of records and compare field values between source and target. Pay special attention to:

  • Date fields (timezone shifts can silently shift dates by one day)
  • Dropdown/status values (mismatched internal values)
  • Currency/number formatting (locale differences)
  • Associations (spot-check that Contact → Company → Deal chains are intact)

UAT Process

  1. Create a validation spreadsheet with 50–100 sample records — a mix of easy cases and ugly ones (records with multiple associations, attachments, historical activity, and edge-case status values).
  2. Have sales ops or RevOps compare each record side-by-side.
  3. Test HubSpot workflows that depend on migrated data.
  4. Verify pipeline stages match the original Monday.com status values.
  5. Confirm file attachments are accessible on the correct records.

Rollback Planning

Before cutover:

  • Tag all migrated records with a custom property (e.g., migration_batch = 2026-04-21). If validation fails, you can bulk-delete by that property and re-run.
  • Keep Monday.com boards read-only (not deleted) for at least 30 days post-migration.

Run at least one full test migration in a HubSpot sandbox before final cutover.

Post-Migration Tasks

Rebuild Automations

Monday.com automations don't transfer. For each automation documented during your pre-migration audit:

  • Map the trigger (e.g., "Status changes to Done") to a HubSpot workflow enrollment trigger.
  • Map the action (e.g., "Create item in another board") to a HubSpot workflow action.
  • Test each workflow independently before enabling.

User Training

Your team is switching from a board-based mental model to a relational CRM. The biggest adjustment: in Monday.com, you "look at boards." In HubSpot, you "look at records and their associations." Budget 1–2 weeks for team ramp-up.

Review HubSpot's default activity association settings before go-live so new calls, emails, notes, and meetings land on the records your team expects. (knowledge.hubspot.com)

Monitor for Data Drift

For the first 30 days post-migration:

  • Compare weekly record counts between your backup and HubSpot.
  • Monitor for duplicate creation (especially if you have ongoing integrations feeding HubSpot).
  • Check that association counts match expectations.

Platform Constraints Reference

Constraint Impact
HubSpot custom objects: Enterprise only, max 10 definitions Monday.com boards that don't map to standard objects require Enterprise or schema compromise
HubSpot associations: 500 per record max Monday.com items with hundreds of Connect Boards links may hit this ceiling
Monday.com daily API limits: 1,000 calls/day on Standard Extraction of large datasets requires Pro or Enterprise plan, or multi-day extraction windows
HubSpot CRM Search: 4 requests/second, 10,000 results max Deduplication checks during import are bottlenecked here
Monday.com cursor expiration: 60 minutes Long-running extractions must handle cursor refresh
HubSpot eventual consistency Reads immediately after writes may return stale data — build delays into association creation
HubSpot import: max 1,048,576 rows, 512 MB, <1,000 columns Applies to CSV import path only
Monday.com board export: 10,000 items per export Applies to CSV export path only

When to Use a Managed Migration Service

Build in-house when:

  • You have a senior engineer with 2–4 free weeks
  • Your data model is simple (≤3 boards, no files, no subitems)
  • You want to own the pipeline for future re-runs

Use a managed service when:

  • You have 10+ boards with complex Connect Boards relationships
  • File attachments must be preserved
  • Your Monday.com plan has restrictive daily API limits
  • Engineering bandwidth is committed to product work
  • You cannot afford a failed migration or extended downtime

The hidden cost of DIY migration is rarely the code — it's the debugging. Rate limit collisions, cursor expiration mid-extraction, HubSpot's eventual consistency causing association failures, file URLs expiring between extraction and upload. Each edge case costs 4–16 hours of engineering time to diagnose and fix. Multiply that across 10–15 edge cases, and you've spent an engineer-month on what was supposed to be a "two-week project."

For a deeper analysis of this cost dynamic, see The Data Migration Risk Model: Why DIY AI Scripts Fail.

At ClonePartner, we handle CRM migrations with complex multi-board relationships. Our scripts manage Monday.com's complexity budgeting and HubSpot's burst limits automatically, extract and re-upload file attachments before S3 URLs expire, and rebuild every Connect Boards relationship as a typed HubSpot association — with full validation and zero downtime.

Best Practices Checklist

  • Back up all Monday.com boards (CSV + API extraction) before starting.
  • Run a test migration in a HubSpot sandbox environment first.
  • Create HubSpot properties and pipeline stages before importing records.
  • Migrate in dependency order: Companies → Contacts → Deals → Activities → Associations.
  • Track the ID mapping table (monday_item_idhubspot_record_id) throughout — you need it for associations.
  • Monitor API quota consumption on both sides during the migration window.
  • Validate incrementally — don't wait until the end to check record counts.
  • Keep Monday.com boards read-only for 30 days post-migration as a safety net.
  • Document every field mapping decision for future reference and audit trail.

Frequently Asked Questions

Can I migrate Monday.com to HubSpot using CSV export?
Yes, but only for small, flat datasets. CSV export from Monday.com strips Connect Boards relationships, drops file attachments, and flattens subitems. Board export is also capped at 10,000 items per export. For anything beyond 1,000 records or if cross-board relationships matter, use the API.
What are Monday.com's API rate limits for data migration?
Monday.com enforces a complexity limit of 10,000,000 points per minute and daily call limits that vary by plan: 1,000 calls/day on Basic/Standard, 10,000 on Pro, and 25,000 on Enterprise. Cursor-based pagination returns up to 500 items per query, and cursors expire after 60 minutes.
How do I migrate Monday.com Connect Boards relationships to HubSpot?
Use the HubSpot Associations API. During extraction, build a mapping table of Monday.com item IDs to HubSpot record IDs. Create records in dependency order (Companies → Contacts → Deals), then loop through your Connect Boards data to create associations using the mapped IDs. CSV import cannot do this.
Does HubSpot support custom objects from Monday.com boards?
HubSpot custom objects require an Enterprise subscription and are limited to 10 custom object definitions by default, with up to 2 million records per custom object. If you're on Professional or lower, flatten custom board data into properties on standard objects like Contacts, Companies, or Deals.
Can Monday.com Leads become HubSpot Leads?
Only if the target HubSpot portal supports the Leads object (requires Sales Hub Professional or Enterprise), and each Lead must be associated with an existing Contact. Otherwise, map Monday leads as Contacts with lifecycle stage set to Lead, or as Contacts with early-stage Deals.

More from our Blog