Importing Members into Gravity Rail
Members are the users in your Gravity Rail workspace. This guide shows you how to create members, assign roles, and manage their data.
Understanding Accounts, Workspaces, and Members
Gravity Rail has a three-part user model:
graph TB
A["Account<br/>(Global User)<br/>email, phone, name"]
W["Workspace<br/>(Team/Project)<br/>slug, settings"]
M["Member<br/>(User in Workspace)<br/>member_role_id<br/>account_uuid"]
L["Member Role<br/>(Permissions)<br/>granted_scopes"]
A -->|workspace_membership| W
M -->|references| A
M -->|workspace_id| W
M -->|member_role_id| L
style A fill:#e1f5ff
style W fill:#f3e5f5
style M fill:#e8f5e9
style L fill:#fff3e0
Key relationships:
- Account: A global user record (email, phone, name) shared across your organization
- Workspace: A team, project, or customer workspace with its own members and data
- Member: An account's participation in a specific workspace with a role
- Member Role: Defines permissions (manage workspace, access data types, etc.)
A single account can be a member of multiple workspaces with different roles.
Creating Members
Via API (Signup Endpoint)
The /create-signup endpoint creates or updates members and their associated data in a single operation:
curl -X POST https://api.gravityrail.com/api/v2/w/{workspace_uuid}/create-signup \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"member": {
"email": "alice@example.com",
"phone": "+1-555-123-4567",
"name": "Alice Johnson",
"dateOfBirth": "1980-06-15",
"externalId": "user_123",
"role": "Support Agent",
"locale": "en-US",
"tosAccepted": true,
"labels": ["vip", "premium"]
},
"data": {
"patient": {
"externalId": "pat_456",
"values": {
"first_name": "Alice",
"email": "alice@example.com",
"medical_id": "MED123456"
}
}
}
}'
Request fields:
member.email- (optional if phone or externalId provided) Email addressmember.phone- (optional if email or externalId provided) Phone number (will be normalized)member.name- (optional) Display namemember.dateOfBirth- (optional) Date of birth inYYYY-MM-DDformatmember.externalId- (optional) Your system's user ID for easy lookupsmember.role- (optional) Name of the member role. Must be non-admin. Defaults to first non-admin role if omittedmember.locale- (optional) Locale code (e.g., "en-US", "fr-FR")member.tosAccepted- (optional) Whether the user accepted terms of servicemember.labels- (optional) Array of label slugs to assign to the memberdata- (optional) Object with data type slugs mapping to records to create/update
Response:
{
"token": "eyJhbGc...",
"account": {
"uuid": "550e8400-e29b-41d4-a716-446655440000",
"email": "alice@example.com",
"phone": "+1-555-123-4567",
"name": "Alice Johnson"
},
"member": {
"id": 42,
"email": "alice@example.com",
"memberRoleId": 5,
"labels": [
{ "id": 1, "slug": "vip", "name": "VIP" },
{ "id": 2, "slug": "premium", "name": "Premium" }
]
},
"wasCreated": true
}
Requirements:
- Your API key must have the
account:createscope - Either
email,phone, orexternalIdmust be provided - Email format is validated and normalized to lowercase
- Phone format is validated and normalized
- Role names must not have admin privileges (roles with admin-level scopes)
Via Import UI
The Members import interface provides a visual way to bulk create/update members:
- Navigate to your workspace members page
- Click the Import button
- Select a CSV file with member data
- Choose a role for newly created members
- Review the import preview
- Confirm to import
CSV Format:
email,phone,name,date_of_birth,external_id,description,labels,notify_email,notify_sms,notify_voice,form.patient.first_name,form.patient.medical_id
alice@example.com,+1-555-123-4567,Alice Johnson,1980-06-15,user_123,Support specialist,"vip,premium",1,1,0,Alice,MED123456
bob@example.com,+1-555-123-4568,Bob Smith,1991-11-03,user_124,Junior support,standard,1,0,1,Bob,MED123457
CSV Requirements:
- CSV format with headers in the first row
- At least one of:
email,phone, orexternal_idper row date_of_birthacceptsYYYY-MM-DD- Boolean columns (
notify_*) accepttrue/falseor1/0 - Labels are comma-separated; quote the CSV cell when it contains commas
- Form data uses dot notation:
form.{data_type_slug}.{field_slug} - Maximum 10,000 rows per import
- Maximum file size: 10 MB
Via Direct API
Create individual members with the /members endpoint:
curl -X POST https://api.gravityrail.com/api/v2/w/{workspace_uuid}/members \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"email": "alice@example.com",
"phone": "+1-555-123-4567",
"name": "Alice Johnson",
"dateOfBirth": "1980-06-15",
"description": "Support specialist",
"externalId": "user_123",
"memberRoleId": 5,
"labelIds": [1, 2],
"locale": "en-US",
"notifyEmail": true,
"notifySms": true,
"notifyVoice": false
}'
Updating Members
Via API
Update an existing member:
curl -X PUT https://api.gravityrail.com/api/v2/w/{workspace_uuid}/members/{member_id} \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "Alice Johnson",
"email": "alice.johnson@example.com",
"phone": "+1-555-123-4599",
"dateOfBirth": "1980-06-15",
"description": "Senior support specialist",
"memberRoleId": 6,
"labelIds": [1, 3],
"notifyEmail": true
}'
Via CSV Import
Re-importing the same members (matched by email or phone) will update their fields:
# This will update Alice if she already exists
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 import returns progress updates as streaming NDJSON:
{"type":"progress","current":1,"total":100,"success":1,"failed":0,"created":1,"updated":0,"unchanged":0}
{"type":"progress","current":2,"total":100,"success":2,"failed":0,"created":1,"updated":1,"unchanged":0}
{"type":"complete","success":98,"failed":2,"total":100,"created":50,"updated":48,"unchanged":0,"errors":["Row 15: Invalid email..."],"failedRows":[15,27],"updatedMembers":[...]}
Member Roles and Permissions
Member roles control what a member can do in your workspace:
View Available Roles
curl https://api.gravityrail.com/api/v2/w/{workspace_uuid}/member-roles \
-H "Authorization: Bearer YOUR_API_KEY"
Response:
[
{
"id": 1,
"name": "Admin",
"useAdmin": true,
"manageWorkspace": true,
"permissions": ["workspace:admin", "members:manage", "data:manage"]
},
{
"id": 5,
"name": "Support Agent",
"useAdmin": false,
"manageWorkspace": false,
"permissions": ["chats:read", "chats:write", "data:read:patient"]
}
]
Create Custom Roles
curl -X POST https://api.gravityrail.com/api/v2/w/{workspace_uuid}/member-roles \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "Support Agent",
"permissions": [
"chats:read",
"chats:write",
"data:read:patient",
"data:write:patient"
]
}'
Managing Member Data
When you create or update a member, you can simultaneously create/update their associated data records:
curl -X POST https://api.gravityrail.com/api/v2/w/{workspace_uuid}/create-signup \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"member": {
"email": "alice@example.com",
"name": "Alice Johnson",
"role": "Support Agent"
},
"data": {
"employee": {
"externalId": "emp_123",
"values": {
"department": "Support",
"start_date": "2024-01-15",
"manager": "Bob Smith"
}
},
"patient": {
"externalId": "pat_789",
"values": {
"first_name": "Alice",
"medical_id": "MED123456"
}
}
}
}'
Each data record is matched by external ID:
- If a record with that external ID exists: It's updated with new values
- If no record exists: A new record is created
- For non-collection data types: If no external ID match exists but the member has an existing record, that record is updated with the new external ID
See Understanding Data for more on data types and records.
Member Labels
Labels organize members into groups for reporting and filtering:
# Create a label
curl -X POST https://api.gravityrail.com/api/v2/w/{workspace_uuid}/member-labels \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "VIP",
"slug": "vip",
"color": "#FF6B6B"
}'
# Assign labels when creating members
curl -X POST https://api.gravityrail.com/api/v2/w/{workspace_uuid}/members \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"email": "alice@example.com",
"labelIds": [1, 2, 3]
}'
Member Notifications
Control how members are notified of updates:
curl -X PUT https://api.gravityrail.com/api/v2/w/{workspace_uuid}/members/{member_id} \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"notifyEmail": true, # Email notifications enabled
"notifySms": true, # SMS notifications enabled
"notifyVoice": false # Voice notifications disabled
}'
Best Practices
- Use External IDs: Always provide an
externalIdmatching your system's user ID for easy reconciliation and lookups - Validate Phone Numbers: Ensure phone numbers are in E.164 format (e.g.,
+1-555-123-4567) - Batch Operations: Use CSV import for large numbers of members rather than individual API calls
- Handle Duplicates: The system prevents duplicate emails and phones - use the import response to handle conflicts
- Preserve Role Hierarchy: Only admins can assign admin roles; non-admin role assignment via signup API is enforced
Common Workflows
Sync Users from Your CRM
# Export users from your CRM as CSV
csv_data=$(curl https://your-crm.com/api/users/export)
# Import to Gravity Rail
curl -X POST https://api.gravityrail.com/api/v2/w/{workspace_uuid}/members/import \
-H "Authorization: Bearer YOUR_API_KEY" \
-F "file=@-" \
-F "newMemberRoleId=5" \
<<< "$csv_data"
Create Member + Patient Record
curl -X POST https://api.gravityrail.com/api/v2/w/{workspace_uuid}/create-signup \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"member": {
"email": "patient@example.com",
"name": "John Doe",
"role": "Patient"
},
"data": {
"patient": {
"externalId": "patient_789",
"values": {
"date_of_birth": "1990-01-15",
"medical_id": "MED789012",
"insurance": "Blue Cross"
}
}
}
}'
Update Multiple Members
# Export current members
curl https://api.gravityrail.com/api/v2/w/{workspace_uuid}/members/export \
-H "Authorization: Bearer YOUR_API_KEY" \
> members.csv
# Edit members.csv locally (update roles, labels, etc.)
# Re-import
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"
API Reference
For complete API documentation, see API Reference.
Key endpoints:
POST /w/{workspace_uuid}/create-signup- Create or update member with role and dataGET /w/{workspace_uuid}/members- List members with filteringPOST /w/{workspace_uuid}/members- Create individual memberPUT /w/{workspace_uuid}/members/{member_id}- Update memberDELETE /w/{workspace_uuid}/members/{member_id}- Delete memberPOST /w/{workspace_uuid}/members/import- Import members from CSVPOST /w/{workspace_uuid}/members/export- Export members to CSVGET /w/{workspace_uuid}/member-roles- List available rolesPOST /w/{workspace_uuid}/member-roles- Create custom role