# Migrate from spreadsheets to Reply

> Move outreach out of a spreadsheet: what transfers, what is rebuilt, how to carry your do-not-contact list across first, and how to stop sending by hand.

**Contacts and their fields transfer through a CSV import. Sequences are built in Reply rather than imported, and your record of what you already sent stays in the spreadsheet. Carry your do-not-contact list across before anything sends, and keep the spreadsheet as an archive.**

_Status: Reviewed – written against Reply's product documentation on 2026-09-22, not yet confirmed against the running product._

## Why teams move off spreadsheets

### Follow-ups happen on their own

A sequence sends each step on its own schedule and stops the moment someone replies. A spreadsheet needs someone to remember. See [Email outreach](/capabilities/email-outreach/).

### Replies are detected and sorted for you

Reply matches an incoming message to the contact, works out whether it is a real reply, an out-of-office or a bounce, and updates the contact. Nobody has to keep a "replied?" column honest. See [Reply management](/capabilities/reply-management/).

### One sequence can use more than email

Email, LinkedIn, calls, SMS and WhatsApp steps sit in the same sequence, with conditions that branch on what each person does. See [Multichannel outreach](/capabilities/multichannel-outreach/).

### Your sending reputation is looked after

Mailbox warm-up, a gradual volume ramp, pacing between sends and authentication checks all run continuously. Sending a few hundred mail-merge messages in one afternoon is one of the surest ways to damage a domain. See [Deliverability](/capabilities/deliverability/).

### Opt-outs are enforced, not remembered

An unsubscribe puts the contact beyond reach across your whole account, not just in the list you happened to be working from. See [Statuses](/reference/statuses/).

Ready to switch? [{{MIGRATION_CTA_PRIMARY_LABEL}}]({{MIGRATION_CTA_PRIMARY_URL}}) or [{{MIGRATION_CTA_SECONDARY_LABEL}}]({{MIGRATION_CTA_SECONDARY_URL}}).

## Migration at a glance

| | |
| --- | --- |
| **Transfers directly** | Contacts and any columns you map, including custom fields, through a CSV import |
| **Rebuilt in Reply** | Your outreach itself – steps, timing and copy become a sequence |
| **Doesn't transfer** | What you have already sent. There is no import path for message history, so the spreadsheet stays your archive |
| **Do first** | Get your do-not-contact list into Reply's blacklist, before anything sends |
| **What you need** | A mailbox to connect, and a plan that covers the contacts you intend to reach |

## Before you start

- [ ] A mailbox connected and authenticated in Reply ([guide](/how-to/connect-a-mailbox/))
- [ ] Your do-not-contact list identified: a tab, a column, or a separate file
- [ ] One column that uniquely identifies a person, with no blanks
- [ ] A **First Name** column filled for every row
- [ ] Agreement on when manual sending stops

## How a spreadsheet maps to Reply

| In your spreadsheet | In Reply | What changes |
| --- | --- | --- |
| A row | A contact | Matched to any existing contact by the identifier you choose |
| A column | A field | Standard fields map directly; anything else becomes a custom field |
| A "do not contact" tab or flag | A blacklist entry | Enforced account-wide, not per list |
| A "sent on" or "status" column | A contact's status and activity | Maintained by Reply from then on |
| A tab per campaign | A sequence | Rebuilt, not imported |

## Step 1: Clean the spreadsheet

Work on a copy.

- Delete empty trailing columns. Exports often add thousands, and they inflate the file far beyond its visible content.
- Fill **First Name** for every row. Rows without it do not become contacts at all.
- Keep phone numbers, IDs and anything with `+`, spaces or dashes as **text**, not numbers.
- Decide your identifier – Email is the most reliable when your contacts have addresses; use the LinkedIn profile URL for a list without them.
- Remove duplicates in the sheet, or accept that the first occurrence wins.

## Step 2: Carry your opt-outs across

**Do this before you import anything you intend to send to.**

Collect everyone who has asked not to be contacted (an unsubscribe tab, a "do not email" flag, replies you never logged) and add them to Reply's blacklist. You can blacklist individual addresses, or a whole domain when you want to exclude an entire company.

Being unable to reconstruct that list is the single most common reason a migration goes wrong, and it is the one mistake with consequences beyond your own inbox.

## Step 3: Import your contacts

Import from **People → Contacts**, map your columns, and choose:

- your **contact identifier** – the column that decides whether a row is someone you already have
- **Matched Records** – **Update Missing Fields** to enrich existing contacts, or **Skip** to leave them untouched
- **Records Without Emails** – **Add Generated Emails** if you plan LinkedIn, call or SMS outreach, or **Skip**

A single import accepts up to 100,000 rows. The result notification reports **Imported**, **Updated**, **Skipped** and **Import Errors**: read it rather than assuming. See [Import contacts](/how-to/import-contacts/) and, if the numbers surprise you, [Why were contacts not imported?](/troubleshooting/contacts-were-not-imported/).

## Re-enrich the contacts you bring across

An exported list is a snapshot of the day it was exported. People have changed jobs, companies have been
acquired, and a proportion of the addresses no longer accept mail. Sending to that list from new infrastructure
is the fastest way to damage a domain you have just set up.

Do two things before your first send.

**Validate the addresses.** Validation checks whether an address will accept mail before you send to it. It
costs one credit per address, drawn from a balance kept separately from other enrichment, and it runs one job
at a time. Removing the undeliverable addresses first is the single most valuable thing you can do for a new
domain's reputation.

**Fill the gaps that matter.** Reply can find missing details for contacts you already have: enriching from a
LinkedIn profile costs 1 credit, finding an email address costs 2, and finding a phone number costs 3. Those
three draw on one shared balance, so a phone lookup moves it three times as fast as a profile enrichment.

Two behaviours to know before you run enrichment across a whole imported list:

- **A profile enrichment is charged even when it finds nothing**, because the credit pays for the lookup. An
 email or phone search refunds a miss. Enrich selectively rather than across everything.
- **Your keep-existing choice covers contact fields only.** Company records are always overwritten with what
 the provider returns, and a contact whose employer has changed can be moved to a different company
 altogether. If you curated company data in your old tool, expect it to be replaced.

## Step 4: Build your first sequence

Recreate what you were doing by hand: the first message, the follow-ups, and how long to wait between them. Replace the bits you used to retype with variables, so each message fills from the contact's own fields. See [Create a sequence](/how-to/create-a-sequence/).

Start with one sequence and a small group rather than everything at once.

## Step 5: Stop sending by hand

Agree a date and stop. The failure to avoid is someone continuing a mail merge from the old spreadsheet while the sequence is also running: the same person receives both, and you look careless at best.

If more than one person sends from that list, tell them the date too.

## Step 6: Switch over

1. Add a small first group to the sequence rather than the whole list.
2. Launch it and check the first sends actually went out.
3. Add the rest once you are satisfied.

Contacts enter gradually rather than all at once, which is deliberate. See [Why was the daily limit not reached?](/troubleshooting/daily-limit-was-not-reached/).

## What doesn't transfer

- **Message history.** There is no import path for what you already sent. Keep the spreadsheet as an archive.
- **Open and reply statistics** from before the move. Reply reports on what it sent.
- **Your sequence layout.** It is rebuilt, not imported.

## Check your migration

- [ ] The contact count matches your file, minus duplicates and rows you expected to skip
- [ ] Your do-not-contact list is in the blacklist and a spot check confirms those people cannot be added
- [ ] Nobody is receiving both a manual message and a sequence
- [ ] The first sends went out, and the contacts show the step they are on

## FAQ

### Can I import my sequences too?

No. Sequences are built in Reply. It is usually quick, because you are recreating something you already know works.

### What happens to contacts with no email address?

Choose **Add Generated Emails** during the import and they come in with a placeholder. They work normally for LinkedIn, call, SMS and WhatsApp steps, and email steps skip them.

### Can I keep using the spreadsheet as well?

As an archive, yes. As a second sending channel, no; that is how the same person ends up receiving two messages.

### How many contacts can I import at once?

Up to 100,000 rows in a single import.

## Ready to move to Reply?

[{{MIGRATION_CTA_PRIMARY_LABEL}}]({{MIGRATION_CTA_PRIMARY_URL}})

Want to talk it through first? [{{MIGRATION_CTA_SECONDARY_LABEL}}]({{MIGRATION_CTA_SECONDARY_URL}})

Already moving and stuck on a step? {{MIGRATION_HELP}} Open the
[Reply Help Center](https://support.reply.io/) and send the support team a message.
Include the tool you're moving from, roughly how many contacts and sequences you're
moving, and the step you're on.

Don't send passwords, API keys, or access tokens, and don't attach contact files
unless the support team asks for them.

## Related

- [Switch to Reply](/migration/) – all migration guides
- [Import contacts](/how-to/import-contacts/)
- [Create a sequence](/how-to/create-a-sequence/)
- [Connect a mailbox](/how-to/connect-a-mailbox/)

## Build with Reply

- Bulk import through the API: [Import contacts](https://docs.reply.io/api-reference/contacts/import-contacts) – up to 1,000 contacts per request
