Skip to main content

Importing Members

Need to add many members at once? The CSV import lets you bulk-create or update members from a spreadsheet, including their contact info, labels, notification preferences, and form data.

CSV Import (UI)

  1. Go to Members
  2. Click the Import button
  3. Select your CSV file
  4. Choose a role for any newly created members
  5. Review the import preview
  6. Click Confirm to import

CSV Format

Your file must be a standard CSV with headers in the first row. At minimum, each row needs one of: email, phone, or external_id.

email,phone,name,date_of_birth,external_id,description,labels,notify_email,notify_sms,notify_voice
alice@example.com,+1-555-123-4567,Alice Johnson,1980-06-15,user_123,Support specialist,"vip,premium",1,1,0
bob@example.com,+1-555-123-4568,Bob Smith,1991-11-03,user_124,,standard,1,0,1

Column Reference

ColumnRequiredFormat
emailOne of email, phone, or external_idValid email address
phoneOne of email, phone, or external_idE.164 format (e.g. +15551234567)
external_idOne of email, phone, or external_idYour system's user ID
nameNoFree text
date_of_birthNoDate in YYYY-MM-DD format
descriptionNoFree text
labelsNoComma-separated slugs; quote the cell if it contains commas (e.g. "vip,premium")
notify_emailNotrue/false or 1/0
notify_smsNotrue/false or 1/0
notify_voiceNotrue/false or 1/0
form.{type}.{field}NoDot-notation for form data (see below)
field.{namespace}.{key}NoDot-notation for member field data (see below)
salesforce_idNoSalesforce Contact/Lead record ID — links the member to that record (see below)

Including Form Data

To populate form records during import, add columns using dot notation: form.{data_type_slug}.{field_slug}.

email,name,form.patient.first_name,form.patient.medical_id
alice@example.com,Alice Johnson,Alice,MED123456
bob@example.com,Bob Smith,Bob,MED123457

The data type and field slugs must match what's configured in your workspace under KnowledgeForms.

Including Member Fields

To write to a member's key-value field store, add columns using field.{namespace}.{key} notation. The namespace groups related fields (e.g. voice, ehr, fhir) and the key identifies a specific field within that namespace.

email,name,field.voice.language,field.ehr.mrn
alice@example.com,Alice Johnson,es,MED123456
bob@example.com,Bob Smith,fr,MED123457

Member fields imported this way are user-managed (not tied to any integration). If a field with the same namespace and key already exists on a member, it is updated; otherwise a new field is created.

Linking to Salesforce records

If your workspace has a connected Salesforce integration, add a salesforce_id column to link each imported member directly to a Salesforce Contact or Lead. This is the same link the Sync → Reconciliation tab creates manually — once linked, features like Chat-Triggered Tasks can write conversation activity back to the right Salesforce record automatically, with no separate reconciliation step.

email,phone,name,salesforce_id
lead@example.com,+15551234567,Jordan Lee,00QQq00000kAybVMAS

Notes:

  • The column is only accepted when an enabled Salesforce connection exists in the workspace; otherwise the import is rejected with a clear error.
  • Values must be a valid 15- or 18-character Salesforce record ID. A malformed value fails validation up front rather than creating a link that never resolves.
  • Re-importing the same salesforce_id for an already-linked member is a no-op. A row whose salesforce_id conflicts with the member's existing link fails that row (the rest of the import continues) rather than silently re-pointing the member.
  • Linking works even while the connection is in a "needs re-authorization" state — the link is a local record and does not call Salesforce.
  • Each link created by an import is recorded in the audit log, the same as links created from the Sync tab.

Limits

  • Maximum 10,000 rows per import
  • Maximum 10 MB file size

Bulk Import via API

For automated or recurring imports, use the API endpoint directly:

curl -X POST https://api.gravityrail.com/api/v2/w/{workspace_uuid}/members/import \
-H "Authorization: Bearer YOUR_API_KEY" \
-F "file=@members.csv" \
-F "newMemberRoleId=5"

The API streams progress as NDJSON so you can track large imports:

{"type":"progress","current":50,"total":200,"success":50,"failed":0,"conflicted":0,"created":30,"updated":20,"unchanged":0}
{"type":"conflict","row":61,"message":"identity_mismatch_on_phone_match","conflict":{"code":"identity_mismatch_on_phone_match","fields":["name","date_of_birth"],"match":{"match_type":"phone","member_id":123,"member_uuid":"..."}},"conflicted":1}
{"type":"complete","success":197,"failed":2,"conflicted":1,"total":200,"created":100,"updated":97,"unchanged":0,"errors":["Row 15: ValueError"],"failedRows":[15,89],"conflictRows":[61]}

By default the API is identity-safe: a phone-only match with different identity fields is skipped and reported under conflicted (never silently overwritten). To preview the classification without writing anything, call POST /api/v2/w/{workspace_uuid}/members/import/preview (same form fields), which returns a JSON summary plus per-row actions. To deliberately overwrite conflicting identities, add identity_conflict_policy=overwrite_identity_fields to the import call.

To find the newMemberRoleId, list your roles at GET /api/v2/w/{workspace_uuid}/member-roles or check MembersRoles in the admin.

For creating individual members with associated data records in one call, see the Importing Members developer guide which covers the /create-signup endpoint.

Duplicates and Update-vs-Create

The import matches existing members by external ID, email, or phone number (in that priority order):

  • New member — If no match is found, a new member is created with the role you selected
  • Existing member — If a match is found, the member's fields are updated with the values from the CSV (blank cells are skipped, not cleared)
  • Role preserved — Existing members keep their current role; the selected role only applies to new members

This means you can safely re-import the same file after making edits — existing members get updated, and new rows create new members.

Identity-conflict protection (preview first)

A phone number can be shared (households, caregivers, a shared office line), so a match by phone alone is treated as weak evidence. When the Preview step runs, any row that matches an existing member only by phone but carries a different name, date of birth, or external ID is flagged as an identity conflict rather than silently overwriting that person's details.

For each conflict you'll see the existing member's identity next to the incoming row, and you choose how to proceed:

  • Skip conflicts (default) — safe rows import normally; conflicting rows are left untouched and listed so you can fix them
  • Overwrite identities — a clearly labelled, destructive action that replaces the existing identity details for every conflicting row (use only when you're sure the rows refer to the same people). Each overwrite is recorded in the audit log.

Matches by external ID or email are treated as strong identity matches and are updated as usual — the conflict guard applies only to phone-only matches.

Using External IDs

If your members originate from another system (CRM, EHR, etc.), populate the external_id column with your system's user ID. This makes it easy to:

  • Look up members by your system's ID via the API
  • Keep members in sync across repeated imports
  • Track which members correspond to records in your other systems

Validation Errors and Troubleshooting

Common Errors

ErrorCauseFix
"Invalid email format"Malformed email addressCheck for typos, extra spaces, or missing @
"Invalid phone format"Phone not in E.164 formatUse full international format: +15551234567
"No identifier provided"Row has no email, phone, or external_idAdd at least one identifier column
"Unknown label"Label slug doesn't exist in workspaceCreate the label first in KnowledgeLabels, or fix the slug
"Unknown form field"form.x.y references a non-existent data type or fieldCheck your data type and field slugs in KnowledgeForms

Tips

  • Check your encoding — Save CSV files as UTF-8 to avoid garbled characters
  • Trim whitespace — Leading/trailing spaces in emails or phone numbers cause validation failures
  • Preview first — The import UI shows a preview before committing; review it for unexpected data in the wrong columns
  • Export then edit — If updating existing members, export your current member list first (GET /api/v2/w/{workspace_uuid}/members/export), edit the CSV, then re-import

Best Practices

  • Start small — Test with 5-10 rows before importing thousands
  • Use external IDs — They make re-imports and API lookups much easier
  • Use ISO datesdate_of_birth must be YYYY-MM-DD
  • Normalize phone numbers — Always use E.164 format (+ followed by country code and number, no spaces or dashes)
  • Create labels first — Set up any labels you reference in the CSV before importing
  • Set up forms first — If including form data columns, make sure the data types and fields exist in your workspace
  • Keep a backup — Save your original CSV before editing, in case you need to start over

For developers