Help Center Membership Management: Patients and memberships Import patients from a spreadsheet (Import CSV)
Import patients from a spreadsheet (Import CSV)
Where: Members → Import CSV. The same tool is also at Admin → Settings → Data → Import CSV…. Who: people with Add / edit manual patients, review Zenoti matches, and only if your plan has CSV import & export.
A CSV file is a simple spreadsheet file. Excel and Google Sheets can save one ("Save as CSV").
The panel is called Import patients & memberships from CSV. Nothing is saved until you click the final Import button.
Step 1: Get the file ready
- One row per membership. A patient with two memberships is two rows with the same name and date of birth. They become one patient with two memberships.
- Click Download template to get a ready file named patient-import-template.csv. It has every column name in the first row and one example row ("Jane Example"). Replace the example with your patients.
- The file must have a heading row and at least one patient row, or you see "The file needs a header row and at least one patient row."
- Up to 2,000 rows per import.
- Files saved as normal text (UTF-8) or UTF-16 both work.
The columns
Required columns are marked with \* in the "Imports as" list.
| Column | What to put in it |
|---|---|
| fullName \* | "First Last". Or use firstName + lastName instead. |
| membershipType \* | Exactly one of your clinic's membership type names (capital letters do not matter). Or use tags instead (see below). |
| startDate \* | YYYY-MM-DD or MM/DD/YYYY. Not required when you use tags. |
| membershipStatus | Active (default if blank), Paused or Canceled. "Frozen" counts as Paused; "Cancelled" also works. |
| nextAutopayDate | Next billing date. Drives the reorder date. |
| autopayAmount | Dollars, like 299 or 299.00. Dollar signs and commas are fine. |
| autopayRepeats | monthly (default), interval, or none (banked / one-time). "month", "one-time" and "banked" also work. |
| nextReorderDate | Optional. If blank, follows the autopay date or start date + interval. |
| phone | Any format. |
| Must be a real-looking e-mail. | |
| dateOfBirth | Needed for pharmacy orders. |
| sex | F, M, or blank. |
| address1 | Street. Needed for pharmacy shipping. |
| address2, city, zip | |
| state | Two letters (FL) or the full name (Florida). |
| externalPatientId | The patient's id in your EMR. Rows with it never create a duplicate. |
| firstName, lastName | Use these when your file has no single name column. |
| tags | EMR tags, separated by commas or semicolons. Each tag that matches one of your membership-type rules becomes that membership. No membershipType column needed. |
| lastPaymentDate | The last membership payment. If nextAutopayDate is blank, the next due date becomes this date + the type's interval. |
Dates can be YYYY-MM-DD, MM/DD/YYYY, M/D/YY or YYYY/MM/DD.
Step 2: Pick the file and check the columns
- Click Choose file and pick your CSV.
- A table appears: Columns in [file name] (N rows). It has three columns:
- Your column: the heading from your file ((blank) if the heading is empty).
- Imports as: what the portal will use it for. The portal guesses from common names (for example "DOB", "Birthday" → dateOfBirth; "Plan", "Program" → membershipType; "Mobile", "Cell" → phone; "Zip code" → zip). Change any guess with the drop-down. Pick - ignore, to skip a column. A short help line appears under your choice.
- First row: the value from your first patient row, so you can check the match.
- If a required column is missing, a red line says Map these required columns: … and the check button stays greyed out.
If your EMR sends updates to the portal on its own (for example OptiMantra), the panel also says you can upload [EMR]'s patient export as it is. Its patient id, first/last name, date of birth, e-mail, phone and Tags columns are recognized, every tag that matches a membership-type rule becomes that membership, and rows with the patient id are linked to the EMR from day one.
Step 3: Check the file
Click Check the file. Nothing is saved yet. You see a summary:
Ready to import: N memberships for N new patients and N existing · N existing memberships updated · N linked to the EMR by patient id · N unchanged rows skipped · N rows whose tag is not a membership (skipped) · N rows with problems (not imported)
(Parts with zero are left out.)
Below it you may see:
- Tags in the file that match no membership-type rule (red box), each tag and how many rows have it. Add a rule under Membership types for each tag that is a membership, then click Check the file again. Tags that are not memberships can stay unmatched.
- N existing memberships would change, what: click to open a table (Line, Patient, Fields) of what would be updated.
- A problems table (Line, Patient, Problems), rows that will not be imported, and why.
- A skipped table (Line, Skipped), rows left alone, and why.
"Line" is the row number in your spreadsheet. The heading row is line 1, so the first patient is line 2.
Problems that stop a row
- name is required
- membership type "…" is not one of: …
- membership type is required (or a tags column that matches a membership-type rule)
- no tag matches a membership-type rule
- start date is required (YYYY-MM-DD or MM/DD/YYYY) / start date is not a date …
- status "…" must be Active, Paused or Canceled
- next autopay date is not a date, last payment date is not a date, next reorder date is not a date, date of birth is not a date
- autopay repeats "…" must be monthly, interval or none
- autopay amount is not a number
- state "…" not recognized
- email is not valid
How the import decides "new" or "already here"
For each row, the portal looks for the same patient already in the portal, in this order:
- Same EMR patient id (the externalPatientId column).
- Same e-mail, or same phone (last 10 digits).
- Same name and date of birth (hand-entered patients only).
Archived patients are not matched.
- New patient: a new patient is created with the membership(s).
- Patient already here, but not this membership type: a new membership is added to them.
- Patient already has this membership type (not cancelled): the existing membership is updated: only with what the row adds. Blank cells never erase anything. Fields a person locked on the patient page are never changed. Updated: the next due date (only if later, and only on hand-entered memberships), the amount (hand-entered only), the EMR id (if missing), tags, phone, e-mail, date of birth and address.
- Nothing new in the row: the row is skipped with "[name] already has this [type] membership, nothing new in the row".
Rows in the file with the same EMR id (or the same name + date of birth) are treated as one patient.
Step 4: Import
Click Import N memberships (or Import N memberships + update N). The button is greyed out if there is nothing to create or update. When it is done, the summary turns green and starts with Imported:, and the Members list refreshes.
Imported patients are hand-entered (Manual entry) unless they were linked to your EMR by patient id.
Questions people ask
Q: The "Check the file" button is greyed out.
A: A required column is not mapped. Look for the red line Map these required columns and pick the right column in Imports as.
Q: Will importing the same file twice make duplicates?
A: No. Rows that match a patient already in the portal update that patient, or are skipped if nothing changed.
Q: Will a blank cell erase what is in the portal?
A: No. Blank cells never erase anything.
Q: Some rows say "whose tag is not a membership (skipped)".
A: Those rows' tags do not match any membership-type rule. Add rules under Admin → Settings → Membership types, then check the file again. If the tag is not a membership, you can ignore it.
Q: Can I import the file I exported?
A: Yes. The patients export starts with the same columns as the import template, so it imports back unchanged.
Q: My file is from Excel and the names look strange.
A: Save it as "CSV UTF-8" in Excel and try again.
Q: I have more than 2,000 rows.
A: Split the file into parts of 2,000 rows or fewer.
Q: Why did a patient I archived come back as a new patient?
A: Archived patients are not matched during import. Unarchive the old record first, or merge the two afterwards on the Duplicate patient records page.
