For the complete documentation index, see llms.txt. This page is also available as Markdown.

Preparing Your Member CSV

CrushSuite validates your CSV column by column before anything is imported. This reference lists every column, whether it's required, and the rules each value has to pass.

File format rules

  • Start from the template: on the upload screen, click Download CSV template for a starter file with the right headers and an example row already filled in.

  • Encoding: UTF-8. The byte-order mark some Excel exports add is stripped automatically. If you work in Excel, export as CSV first.

  • Size: up to 4,000 rows and 2 MB per file. A larger list is fine; split it into several files and import them one after another. Members already imported are skipped, so overlap between files is safe.

  • Header row required, plus at least one data row. A file with only headers is rejected with CSV file is empty or has no data rows.

  • Quote cells containing commas: wrap the cell in double quotes and double any literal quotes inside it ("she said ""hi""").

  • Leave optional cells empty, not the word "null" or "none". A placeholder word is treated as a real value.

  • Corrections happen in the file. The preview shows what's wrong with each row, but rows aren't edited on screen. Fix your CSV and click Replace to upload it again.

  • The template includes gateway_customer_token and gateway_payment_token columns. Leave both blank unless you have completed a Stripe payment method transfer. See Migrating Payment Methods from Vinoshipper.


Columns

Only email is required. Every other column has a sensible default, so leave anything you don't have blank rather than inventing a value.

Column
Required
Accepted format

email

Required

Valid email; must be unique in the file

firstName / lastName

Optional (recommended)

Text

phone

Optional

Any common format: +14155552671, (415) 555-2671, 415-555-2671. Must be a real, assigned number, and unique in the file. A number without a + is read against country_code (US if blank)

member_number

Optional

Text, kept for reference. CrushSuite always assigns its own member number regardless

joined_at

Optional

Any parseable date; YYYY-MM-DD (e.g. 2024-06-15) is safest. Anchors the member's first membership fee renewal. Blank defaults to one year before the import

date_of_birth

Optional

YYYY-MM-DD only, e.g. 1985-03-15. Passed to CrushSuite Compliance if installed

preferred_delivery_method

Optional

One of SHIPPING, PICKUP, LOCAL_DELIVERY. Becomes the default on every release order

address1 / address2 / city / province_code / country_code / postcode

Optional, but all-or-nothing

Text. See the address rule below

notes

Optional

Text, shown on the member's record

shopify_customer_id

Optional

Existing Shopify customer ID. CrushSuite uses it directly instead of matching on email

gateway_customer_token

Optional

The member's Stripe customer ID in your Stripe account (starts with cus_). Fill both token columns or neither

gateway_payment_token

Optional

The member's Stripe card ID in your Stripe account (starts with pm_ or card_), taken from the new column of Stripe's mapping file. Tokens are assumed to be Stripe. Never a one-time tok_ value


The address is complete or absent

If any of address1, address2, city, province_code, or postcode is filled in on a row, then address1, city, province_code, and postcode must all be present. A partial address fails with Incomplete address — missing …, naming the columns to add.

country_code doesn't count as "supplying an address". The template ships it as US, and filling it down the whole sheet is fine on rows with no address.

A member with no address at all imports fine. Pickup-only members legitimately have none. If a member with no address turns out to need shipping, their release order is held for your review instead of being billed with no destination.


If you're filling in the token columns

A token on the wrong row bills the wrong member's card, and nothing at import can catch it, because a token is just an ID. Build the file from Stripe's mapping file rather than copying IDs by hand, and check that email, customer ID, and card ID line up on every row before you validate.

Use the new IDs from Stripe's mapping file, not the IDs in Vinoshipper's transfer file. Cards get a fresh ID when they land in your Stripe account, and the old IDs don't exist there.

A token that looks wrong doesn't block the member. The preview warns you when the two columns look swapped, when a value is a one-time tok_ rather than a saved card, or when only one of the pair is filled. In each case the member still imports; they just don't get the transferred card and are asked to add one themselves instead.


Validation messages

After Validate file, every row shows as Ready, Error, or Skipped, with the reason in the Issue column. Rows with errors block the import until they're fixed: click Download rows to fix for a CSV of just those rows and their reasons, correct them in your file (or delete any you can't), and click Replace to upload again. Re-validating is free and creates nothing.

Message
What it means

"…" is not a valid phone number

The number can't exist: unassigned area code, wrong length, or no such country. Check it, write it in full international format (+14155552671), or clear the phone cell for this member

Invalid date format (ISO date expected)

joined_at doesn't parse as a date

Invalid date — use YYYY-MM-DD format (e.g. 1985-03-15)

date_of_birth isn't strict YYYY-MM-DD, or the date doesn't exist. A US-style 03/15/1985fails

Incomplete address — missing …

Some address columns are filled and others aren't. Complete the address or clear every address column on that row

Duplicate email (also on row N)

The same email appears on two rows

Duplicate phone (also on row N)

The same phone appears on two rows, counted after formatting, so (415) 555-2671 and +14155552671 collide. Shopify rejects the second customer. Blank one of them out rather than inventing a number

Already a member of this club

Shown as Skipped, not an error. That email already has a membership here, so the row is left alone

A row with a missing or malformed email fails as well.

Last updated