# HubSpot Tutorial: Get the Data Model Right Before You Import

> A HubSpot walkthrough in the order that actually matters: objects before records, unique identifiers before imports, one pipeline before fifty workflows. Every limit here is from HubSpot's own documentation.

_Source: https://professionalstoolkit.com/articles/hubspot-tutorial — The Professional's Toolkit · updated 2026-10-05_

---


**1,048,576** — Maximum rows per import file on a paid HubSpot subscription. Free tools cap at 500,000 rows a day in total, and a larger file simply takes more than one day.



- **20 MB vs 512 MB** — Import file size ceiling on free tools against any paid subscription. Imports per day go from 50 to 500 and rows per day from 500,000 to 10 million.
- **Email, or duplicates** — Without a unique identifier in the file, HubSpot's documentation states the import creates duplicate records instead of associating them. Record ID works for every object; Email for contacts; Company domain name for companies.
- **Professional and up** — Custom association labels require Professional or Enterprise. On Free and Starter you can associate records but not describe the relationship.


Almost every HubSpot tutorial starts by creating a deal. That is the wrong first move, and it is why so many HubSpot accounts end up with duplicate companies, deals with no amount and a contact list nobody trusts.

The work that decides whether your HubSpot is useful happens before the first record exists, in a spreadsheet. This walkthrough follows that order: the data model first, the import file second, the pipeline third, automation last. Every rule and limit here comes from HubSpot's own documentation rather than from the marketing pages.

## The Three Words That Govern Everything

HubSpot's documentation describes the foundation of the account as a database of objects, records and properties.

An **object** is a type of thing: contacts, companies, deals, tickets. A **record** is one instance of that type. A **property** is a field on the record. Objects relate to each other through **associations**, which is how one contact ends up linked to two companies and three deals.

The documentation's own example is the clearest one: John Doe is a contact record, his email address lives in the Email property, his company Orange Inc. is a separate company record, and the two are associated.

That sounds like bookkeeping. It is actually the decision that governs everything downstream, because segmentation, automation and reporting all read associations. An account where contacts were imported without company associations will report on people and never on accounts, and no amount of later configuration fixes it as cleanly as doing it once.

Beyond the four familiar objects, HubSpot's import documentation lists several more with their own required properties, including Appointments, Courses, Listings, Services, Products, Orders and Carts. If your business has a thing that is not a contact, a company or a deal, check that list before you invent a custom property to hold it.

## Step One: Decide Your Objects On Paper

Before opening HubSpot, write down four answers.

**What is a contact here?** Every person, or only people you have spoken to? This decides your import scope and, on paid tiers, your contact-based costs later.

**Do you need companies as records, or only as a text field?** If you sell business to business, you need them as records. The test is whether you will ever want to ask how much you have sold to a given account, because that question reads associations.

**What is a deal, and what are its stages?** You need the pipeline and the stage names before importing, because HubSpot requires that an imported deal's Pipeline and Deal stage match options that already exist in the account, and the stage must be valid for that pipeline.

**What do you need to associate?** Contacts to companies is the minimum. Contacts to contacts, for instance a referrer to a referred client, is a same-object association and has extra rules.


> 💡 **Create the pipeline and its stages before importing deals:** HubSpot requires an imported deal's Pipeline and Deal stage to match options that already exist in the account, and the stage must be valid for that pipeline. So the stage names are not a configuration detail you tidy up afterwards, they are a precondition of the import. Write the stage list on paper, create it in the account, then export one deal to confirm the exact spelling HubSpot expects before you map a thousand rows to it.


## Step Two: Build The Import File To The Documented Rules

HubSpot's requirements for an import file are specific, and most failed imports break one of them.

The file must be a .csv, .xlsx or .xls file, contain only one sheet, include a header row where each column header corresponds to a HubSpot property, and contain fewer than 1,000 columns. If it includes non-English characters, it must be UTF-8 encoded. Excel files importing date or time properties need those cells in Number format.

Then the required columns, by object:

| Object | Required columns |
|---|---|
| Contacts | Email |
| Companies | Name, or Company domain name |
| Deals | Deal name, Pipeline, Deal stage |
| Tickets | Ticket name, Pipeline, Ticket status |
| Listings | Name |
| Services | Name, Pipeline, Pipeline Stage |
| Line items | Name, Quantity, Price, and the deal's Record ID or Deal name |
| Tasks | Task title, Due date |
| Calls | Call notes |
| Meetings | Meeting description, Meeting start time, Meeting end time |

Formatting follows the property type, and four of these cause most of the trouble.

**Phone numbers** import and auto-format when written as +[country code][number], with ext[number] for extensions, so a US number looks like +11234567890 ext123.

**Percentages** accept either 25% or .25 for the same value.

**Currency** must use one of HubSpot's accepted currencies, formatted with decimals for USD, as in 123.45.

**Durations**, such as call duration, must be a UNIX timestamp in milliseconds, which is the single most common surprise in this list.

Multiple-checkbox properties take semicolons with no spaces between values, as in value 1;value 2, and the options must exist before the import. Putting a semicolon before the first value appends instead of overwriting, which is a useful trick and an easy accident.

Dates are generous: day-month-year, month-day-year or year-month-day; months as 10, OCT, Oct, OCTOBER or October; years as two or four digits; separators as slash, hyphen or period. Without a timestamp the time defaults to midnight.

## Step Three: Choose Your Unique Identifier Deliberately

This is the step that decides whether you get an import or a mess, and it has one rule with three traps.

The rule: to update existing records and avoid duplicates, your file must include a unique identifier per object. Record ID works for every object, Email works for contacts, Company domain name works for companies.

The first trap is the headline one. Without a unique identifier, the documentation is explicit that the import creates duplicate records instead of associating them to the same record.

The second trap is subtler. If you use a custom unique-value property to deduplicate companies, Company domain name stops requiring unique values, which means duplicate domains can be imported. The fix is to remove duplicate domains from the file beforehand or to use Company domain name as the identifier instead.

The third trap is worth reading twice if you keep secondary emails. A secondary email can identify an existing contact, and it will not replace the primary email, unless you also include the Record ID column, in which case it will.

One more quiet rule: the Company domain name property only accepts values up to the top-level domain. Anything after it, as in a value ending .edu/home, is removed automatically on import.

## Step Four: Import In The Right Order

Import contacts and companies first, then deals, then line items and activities. The reason is the association requirement: deals need existing pipelines and stages, and line items need an existing deal to point at.

For a single object, use the single-object import. For contacts only, HubSpot offers a quick import that skips association and advanced configuration. For anything involving two objects at once, use the advanced import for multiple objects.

Two behaviours in multi-object imports are worth knowing before you run one.

When a single file contains a contact that belongs to two companies, you give that contact two rows with the same identifier and a different company identifier in each. That is how one record gets two associations.

And in a single-file, multi-object import using Create and update, HubSpot treats identical object data across rows as one record even when no unique identifier is supplied for it. If a property differs between the rows, you get two records instead. This does not apply to create-only or update-only imports, so the same file can behave differently depending on the mode you pick.


> ⚠ **The same file behaves differently depending on the import mode:** In a single-file, multi-object import using Create and update, HubSpot treats identical object data across rows as one record even with no unique identifier for it, and creates separate records when a property differs between rows. That behaviour does not apply to create-only or update-only imports. So a file that produced one deal in one mode can produce several in another, which makes the mode selection part of the data design rather than a checkbox.


## Step Five: Associations, Including The Awkward Ones

Cross-object associations are straightforward: put identifiers for both records in the same row, in one file, or use a common column across two files.

Same-object associations, such as contact to contact, have their own constraints. You must tick the same-object association option during the import. At least one record in each pair must already exist in HubSpot, so you cannot create and associate two new contacts in one pass. And only the primary email or primary company domain works as the identifier here; secondary ones are not supported.

To associate several records with one record, separate their identifiers with semicolons in the same cell.

Labelling those relationships, as opposed to merely creating them, is a paid feature. HubSpot's documentation states that a Professional or Enterprise subscription is required for custom association labels. On Free or Starter you can associate records; you cannot describe the relationship.

## Step Six: The First Pipeline

Free and Starter both allow 15 deal pipelines, which is more than almost any small team needs, and the temptation is to build several. Build one.

Name the stages after observable events rather than internal feelings. "Demo booked" is observable. "Interested" is not, and a stage nobody can verify is a stage that stops being updated within a month, which breaks every report built on it.

Keep the stage list short enough that a deal moves at least once a week. If deals sit in one stage for a month, the stage is too wide to be useful for forecasting later.

## Step Seven: One Automation, Inside The Free Limits

Both Free and Starter include 50 workflows, and on Free the triggers and actions are restricted. Fifty is not the constraint. Discipline is.

Build one workflow that does something you currently do by hand every day, and nothing else. Assigning a new contact to an owner based on a property value is the usual first candidate, because it is verifiable: either the owner field fills in or it does not.

Resist the second workflow until the first has run for a week. Automation that nobody has verified is how a CRM becomes a system people work around rather than in.


> 💡 **Generate HubSpot's own example file and diff it against yours:** At the start of an import HubSpot can generate an example file carrying the required properties for the objects you selected. Doing that takes a minute and resolves most column-naming arguments immediately, because it shows the header spellings the tool expects rather than the ones you assumed. It is faster than re-reading the formatting rules and far faster than diagnosing a partial import afterwards.


## Properties: Default, Custom, And The Ones That Fill Themselves

Every standard object arrives with a set of default properties that apply to all records in it, and you can create custom properties for anything the defaults do not hold. That much is obvious. Three things about properties are less obvious and all three save work later.

**Create the custom property before the import, not during it.** Column headers in your file must correspond to properties that exist, and multiple-checkbox options in particular must be created beforehand.

**Some properties and activities update themselves.** The documentation notes that certain properties and activities are logged automatically, including interactions between associated records, while others are manual. Before you build a workflow to maintain a field, check whether HubSpot already maintains it.

**Validation rules silently filter your import.** If a property carries validation rules, imported values that break them are not imported. The record arrives, the field stays empty, and nothing in the file looks wrong. This is the most common cause of an import that appears to have worked and did not.

## After The Import: Views Before Reports

Each object has an index page listing its records, and the first thing to do after an import is to filter that page rather than to build a report.

Filter the contacts index on a property you just imported and see whether the count matches your expectation. That one action catches identifier failures, validation-rule failures and association failures faster than any other check, because it compares a number you know against a number HubSpot computed.

Filters can be saved as views you return to, and HubSpot distinguishes saved views from the segments tool, previously called lists, which filters on property values plus additional criteria. The distinction matters once automation is involved: workflows and reporting read segments, while a saved view is a convenience for the person looking at the screen.

The practical sequence is therefore: import, filter the index to verify, save the views your team needs daily, build segments for anything automation will act on, and only then worry about dashboards.

## The Import Limits You Will Actually Hit

These differ sharply by subscription, and they are rolling 24-hour limits rather than limits that reset at midnight.

| Limit | Free tools | Smart CRM, Starter, Professional or Enterprise |
|---|---|---|
| File size | 20 MB | 512 MB |
| Imports per day | 50 | 500 |
| Rows per day | 500,000 | 10,000,000 |
| Rows per file | Not stated separately | 1,048,576 |
| Rows per day via the imports API | Not applicable | 80,000,000 |
| Simultaneous imports | 3, of which 2 may exceed 10,000 rows | 3, of which 2 may exceed 10,000 rows |

A file above 500,000 rows on free tools will take more than one day, which the documentation states plainly. Starting a fourth simultaneous import queues it rather than failing it.

## What The Documentation Predicts Will Go Wrong

Eight failures, each one a rule from the pages above read backwards:

1. **Duplicates everywhere.** No unique identifier in the file.
2. **Blank cells did not clear anything.** The import tool ignores blank cells, and an existing value stays. Clearing in bulk needs manual editing or an Edit records workflow action.
3. **Deals rejected.** The Pipeline or Deal stage value does not match an existing option, or the stage is not valid for that pipeline.
4. **Deal amounts all zero after importing line items.** Importing line items with deals does not update the deal amount. The documentation says so directly.
5. **Call durations absurd or empty.** Duration was not a UNIX timestamp in milliseconds.
6. **Enumeration values silently missing.** Values must match the internal value or the English label of a defined option.
7. **Activities all dated today.** Activity date was omitted, so it defaulted to the moment of import.
8. **Values rejected with no obvious reason.** A validation rule exists on the property, and values that break it are not imported.

## Debugging, In Order

When an import looks wrong, check in this sequence, because it moves from cheapest to most expensive to fix.

First, confirm the file passed the structural rules: one sheet, header row, under 1,000 columns, UTF-8 if it has accents.

Second, confirm the identifier. Export the records you believe you updated and check whether their Record ID matches what you sent.

Third, check one record by hand against one row of the file, property by property. Formatting failures are property-type specific, so one record tells you which type broke.

Fourth, check associations separately from properties. A record can import perfectly and still be associated with nothing, and the index page will look fine.

HubSpot can generate an example file with the required properties for the objects you selected at the start of an import. Generating one and comparing it to yours is faster than reading the rules again.

## What You Cannot Do Without Paying

Working through this on the free tier is realistic, and three ceilings will eventually stop you.

Two users is the hard one. Free allows two seats, and the third person is the moment the decision becomes commercial.

Custom association labels require Professional or Enterprise, so relationship modelling beyond simple association is a paid capability.

And custom reporting does not exist on Free or Starter at all. You get 10 dashboards with 50 reports each from the standard library; building a report that answers a question the library does not ask begins at Professional.


## FAQ

**How do I import contacts into HubSpot?**

Prepare a .csv, .xlsx or .xls file with one sheet, a header row whose columns match HubSpot properties, fewer than 1,000 columns, and UTF-8 encoding if it contains non-English characters. Email is the required column for contacts. Include a unique identifier so the import updates rather than duplicates. For contacts alone, HubSpot offers a quick import that skips association and advanced settings; for contacts plus companies in one pass, use the advanced multi-object import.

**Why did my HubSpot import create duplicates?**

Almost always because the file carried no unique identifier. HubSpot's documentation is explicit that without identifiers such as Email, Company domain name or Record ID, the import creates duplicate records instead of associating them to the same record. There is also a specific company trap: if you deduplicate companies with a custom unique-value property, Company domain name stops requiring unique values, so duplicate domains can be imported. Remove duplicate domains first, or use Company domain name as the identifier.

**Why are my deal amounts zero after importing line items?**

Because importing line items alongside deals does not update the deal amount. HubSpot's documentation states this directly. To get the amount populated you edit the line items manually or associate the line items with the deal inside HubSpot afterwards. Plan for it rather than discovering it in a forecast report.

**Can I clear a property for many records by leaving cells blank?**

No. The import tool ignores blank cells, so an existing value stays as it is. That design protects you from wiping data by accident, and it means bulk clearing needs a different route: editing the values manually, or using an Edit records workflow action. Leaving a column out of the file entirely has the same effect as leaving it blank.

**How do I associate one contact with two companies?**

Give the contact two rows in the same file, using the same contact identifier in both, with a different company identifier in each row. For associations between records of the same object, such as contact to contact, you must tick the same-object association option, at least one record in each pair must already exist in HubSpot, and only primary emails or primary domains work as identifiers. Several records can be associated to one by separating their identifiers with semicolons in a single cell.

**What can I not do on the free HubSpot plan?**

Three ceilings matter. Free allows two users, so the third person makes the decision commercial. Custom association labels need Professional or Enterprise, so you can associate records but not describe the relationships. And custom reporting does not exist on Free or Starter at all: you get 10 dashboards with 50 standard reports each, and building a report that answers a question the library does not ask starts at Professional.




## Sources

[1] HubSpot documentation: objects, records, properties and associations, including the Professional and Enterprise requirement for custom association labels. Updated 18 September 2026 — https://knowledge.hubspot.com/getting-started-with-the-crm-and-sales
[2] HubSpot documentation: file requirements, per-subscription import limits, formatting by property type, required columns per object and the deduplication and association rules. Updated 11 September 2026 — https://knowledge.hubspot.com/import-and-export/set-up-your-import-file
[3] HubSpot documentation: the quick import route for contacts only — https://knowledge.hubspot.com/import-and-export/import-contacts-quick-import
[4] HubSpot documentation: importing records for multiple objects with advanced settings — https://knowledge.hubspot.com/crm-setup/import-objects
[5] HubSpot Sales Hub pricing: the tier quotas referenced here, including 15 pipelines and 50 workflows on Free and Starter, and the absence of custom reporting below Professional — https://www.hubspot.com/pricing/sales

