Members
Tags: data, members, users
A Member is a person in a workspace — a patient or plan member, or a staff member who works with them. These endpoints manage the member roster, the authenticated member's own profile, per-member custom fields, and bulk import and export.
In the product: Members
Resources
Request and response models used by the endpoints on this page.
BulkCreateMembersRequest
| Field | Type | Required | Description |
|---|---|---|---|
members | Array<BulkMemberItem> | ✓ | |
upsert | Boolean | If true, update existing members matched by externalId/email/phone (default: False) |
Example:
{
"members": [],
"upsert": false
}
BulkCreateMembersResponse
| Field | Type | Required | Description |
|---|---|---|---|
conflictedCount | Integer | Default: 0 | |
errors | Array | ||
importedCount | Integer | ✓ | |
results | Array<BulkMemberResult> | ✓ | |
skippedCount | Integer | Default: 0 | |
success | Boolean | ✓ | |
totalCount | Integer | ✓ |
Example:
{
"importedCount": 0,
"totalCount": 0,
"success": false,
"results": [],
"conflictedCount": 0,
"skippedCount": 0
}
BulkMemberItem
| Field | Type | Required | Description |
|---|---|---|---|
conflictResolution | <enum ImportContactConflictPolicy | Default: fail | |
description | String | ||
email | String | ||
externalId | String | ||
labels | Array | ||
locale | String | ||
memberRoleId | Integer | ||
name | String | ||
notifyEmail | Boolean | ||
notifySms | Boolean | ||
notifyVoice | Boolean | ||
notifyWhatsapp | Boolean | ||
phone | String | ||
timezone | String |
Example:
{
"conflictResolution": "fail"
}
BulkMemberResult
| Field | Type | Required | Description |
|---|---|---|---|
conflicts | Array<ImportContactConflict> | null | ||
error | String | ||
externalId | String | ||
index | Integer | ✓ | |
memberId | Integer | ||
sharedContacts | Array | Default: [] | |
status | Literal['created', 'updated', 'failed', 'conflict', 'skipped'] | ✓ |
Example:
{
"index": 0,
"status": "created",
"sharedContacts": []
}
CapabilityRequirementFinding
| Field | Type | Required | Description |
|---|---|---|---|
kind | Literal['feature', 'member_scope'] | ✓ | |
slug | String | ✓ | |
subject | Literal['org', 'workspace', 'member'] | ✓ |
Example:
{
"kind": "feature",
"slug": "string",
"subject": "org"
}
CapabilityStatus
| Field | Type | Required | Description |
|---|---|---|---|
enabled | Boolean | ✓ | |
missing | Array<CapabilityRequirementFinding> | ✓ | |
slug | String | ✓ |
Example:
{
"slug": "string",
"enabled": false,
"missing": []
}
CreateMemberContactPointRequest
| Field | Type | Required | Description |
|---|---|---|---|
capabilities | Array | ||
contactType | Literal['phone', 'email'] | ✓ | |
label | String | ||
observedAt | DateTime | ||
priority | Integer | Default: 0 | |
purpose | Literal['general', 'notification', 'billing'] | Default: general | |
sharing | Literal['shared', 'individual', 'unknown'] | Default: unknown | |
value | String | ✓ | Phone or email value. Normalized server-side; PHI, never logged. |
Example:
{
"contactType": "phone",
"value": "string",
"purpose": "general",
"priority": 0,
"sharing": "unknown"
}
CreateMemberFieldRequest
| Field | Type | Required | Description |
|---|---|---|---|
key | String | ✓ | |
serviceId | Integer | ||
value | String | ✓ |
Example:
{
"key": "string",
"value": "string"
}
CreateMemberRelationshipRequest
| Field | Type | Required | Description |
|---|---|---|---|
relatedMemberId | Integer | ✓ | |
relatedRole | <enum RelatedMemberRole | ✓ |
Example:
{
"relatedMemberId": 1,
"relatedRole": null
}
CreateWorkspaceMemberRequest
| Field | Type | Required | Description |
|---|---|---|---|
accountEnabled | Boolean | ||
accountTosAccepted | Boolean | ||
accountUuid | String | ||
dateOfBirth | Date | ||
description | String | ||
email | String | ||
externalId | String | ||
isOrgOwner | Boolean | ||
labelIds | Array | ||
locale | String | ||
memberRoleId | Integer | ✓ | |
memberType | String | ||
name | String | ||
notifyEmail | Boolean | ||
notifySms | Boolean | ||
notifyVoice | Boolean | ||
notifyWhatsapp | Boolean | ||
phone | String | ||
releaseContactFromMemberId | Integer | ||
timezone | String | ||
title | String | ||
tosAccepted | Boolean |
Example:
{
"memberRoleId": 0
}
CurrentMemberResponse
| Field | Type | Required | Description |
|---|---|---|---|
accountEnabled | Boolean | ||
accountTosAccepted | Boolean | ✓ | |
accountUuid | String | ✓ | |
canLogin | Boolean | Default: True | |
capabilities | Dictionary<String, CapabilityStatus> | Per-member surface-capability decisions. slug → {enabled, missing}. Each capability composes workspace feature availability with this member's scope authorization. See lib/capabilities/surfaces.py for CapabilityStatus and CapabilityRequirementFinding definitions. | |
createdAt | DateTime | ✓ | |
dateOfBirth | Date | ||
description | String | ✓ | |
email | String | ✓ | |
emailVerified | Boolean | Default: False | |
experimentGroup | MemberExperimentGroupSummary | null | ||
externalId | String | ✓ | |
homeFolderId | Integer | ||
id | Integer | ✓ | |
isArchived | Boolean | Default: False | |
isImportProtected | Boolean | Default: False | |
isOrgOwner | Boolean | ||
isSuperuser | Boolean | ||
labels | Array<MemberLabelResponse> | Default: [] | |
locale | String | ✓ | |
memberRoleId | Integer | ✓ | |
memberRoleName | String | ✓ | |
memberRoleSystemKey | String | ||
memberType | String | Default: member | |
name | String | ✓ | |
notifyEmail | Boolean | ✓ | |
notifySms | Boolean | ✓ | |
notifyVoice | Boolean | ✓ | |
notifyWhatsapp | Boolean | Default: False | |
orgRole | String | ||
phone | String | ✓ | |
phoneType | String | ✓ | |
phoneVerified | Boolean | Default: False | |
role | String | ✓ | |
scopes | Array | Default: [] | |
sharedContactPlacements | Array<SharedContactResponse> | Default: [] | |
timezone | String | ||
title | String | ||
tosAccepted | Boolean | ✓ | |
updatedAt | DateTime | ✓ | |
usagePaused | Boolean | Default: False | |
uuid | String | ✓ |
Example:
{
"id": 0,
"uuid": "string",
"role": "string",
"tosAccepted": false,
"accountTosAccepted": false,
"accountUuid": "string",
"createdAt": "2024-01-01T00:00:00Z",
"updatedAt": "2024-01-01T00:00:00Z",
"name": "string",
"description": "string",
"phone": "string",
"phoneType": "string",
"email": "string",
"externalId": "string",
"emailVerified": false,
"phoneVerified": false,
"notifySms": false,
"notifyEmail": false,
"notifyVoice": false,
"notifyWhatsapp": false,
"locale": "string",
"memberRoleId": 0,
"memberRoleName": "string",
"labels": [],
"memberType": "member",
"isArchived": false,
"isImportProtected": false,
"usagePaused": false,
"canLogin": true,
"sharedContactPlacements": [],
"scopes": []
}
DataRecordResponse
| Field | Type | Required | Description |
|---|---|---|---|
accessMode | Integer | ||
createdAt | DateTime | ✓ | |
dataTypeId | Integer | ✓ | |
externalId | String | ||
fieldValues | Dict[str, Any] | ✓ | |
id | Integer | ✓ | |
memberId | Integer | ✓ | |
memberName | String | ||
retirement | DataRecordRetirementResponse | null | ||
updatedAt | DateTime | ✓ | |
uuid | UUID | ✓ |
Example:
{
"id": 0,
"uuid": "00000000-0000-0000-0000-000000000000",
"dataTypeId": 0,
"memberId": 0,
"fieldValues": {},
"createdAt": "2024-01-01T00:00:00Z",
"updatedAt": "2024-01-01T00:00:00Z"
}
DataRecordRetirementResponse
| Field | Type | Required | Description |
|---|---|---|---|
reason | Literal['monday_item_archived', 'monday_item_deleted'] | ✓ | |
source | Literal['monday'] | Default: monday | |
status | Literal['retired'] | Default: retired |
Example:
{
"status": "retired",
"reason": "monday_item_archived",
"source": "monday"
}
DeleteMembershipResponse
| Field | Type | Required | Description |
|---|---|---|---|
message | String | ✓ |
Example:
{
"message": "string"
}
EnumOption
| Field | Type | Required | Description |
|---|---|---|---|
label | String | ✓ | Display label shown to users |
value | str | int | float |
visibleWhen | String | CEL expression that must return true for this option to be visible. Uses record.data.<field_slug> syntax to reference other field values. CONSTRAINT: Can only reference non-FUNCTION fields. |
Example:
{
"label": "string",
"value": "string"
}
ImportContactConflict
| Field | Type | Required | Description |
|---|---|---|---|
accountValue | String | ||
field | Literal['email', 'phone'] | ✓ | |
rowValue | String | ✓ |
Example:
{
"field": "email",
"rowValue": "string"
}
MemberContactPointConfirmationResponse
| Field | Type | Required | Description |
|---|---|---|---|
bindingUuid | String | ||
confirmed | Boolean | ✓ | |
confirmedAt | DateTime | ||
method | String | ||
source | String |
Example:
{
"confirmed": false
}
MemberContactPointListResponse
| Field | Type | Required | Description |
|---|---|---|---|
contacts | Array<MemberContactPointResponse> | ✓ | |
memberId | Integer | ✓ |
Example:
{
"memberId": 0,
"contacts": []
}
MemberContactPointResponse
| Field | Type | Required | Description |
|---|---|---|---|
capabilities | Array | ✓ | |
confirmation | MemberContactPointConfirmationResponse | null | ||
contactType | String | ✓ | |
createdAt | DateTime | ✓ | |
isPrimary | Boolean | Default: False | |
label | String | ✓ | |
memberId | Integer | ✓ | |
observedAt | DateTime | ✓ | |
priority | Integer | ✓ | |
purpose | String | ✓ | |
retiredAt | DateTime | ✓ | |
sharing | String | ✓ | |
sourceRecordId | String | ✓ | |
sourceSystem | String | ✓ | |
updatedAt | DateTime | ✓ | |
uuid | String | ✓ | |
value | String | ✓ |
Example:
{
"uuid": "string",
"memberId": 0,
"contactType": "string",
"value": "string",
"label": "string",
"purpose": "string",
"priority": 0,
"sharing": "string",
"capabilities": [],
"sourceSystem": "string",
"sourceRecordId": "string",
"observedAt": "2024-01-01T00:00:00Z",
"retiredAt": "2024-01-01T00:00:00Z",
"createdAt": "2024-01-01T00:00:00Z",
"updatedAt": "2024-01-01T00:00:00Z",
"isPrimary": false
}
MemberCredentialResponse
| Field | Type | Required | Description |
|---|---|---|---|
appConnectionId | Integer | ||
appConnectionName | String | ||
connectedAt | String | ||
createdAt | String | ✓ | |
displayName | String | ||
emailVerified | Boolean | Default: False | |
externalEmail | String | ||
externalUserId | String | ||
externalUsername | String | ||
icon | String | ||
iconUrl | String | ||
id | Integer | ✓ | |
isDefault | Boolean | Default: False | |
lastUsedAt | String | ||
provider | String | ||
uuid | String |
Example:
{
"id": 0,
"isDefault": false,
"emailVerified": false,
"createdAt": "string"
}
MemberExperimentGroupSummary
| Field | Type | Required | Description |
|---|---|---|---|
groupId | Integer | ✓ | |
groupName | String | ✓ | |
groupSlug | String | ✓ | |
isControl | Boolean | ✓ |
Example:
{
"groupId": 0,
"groupName": "string",
"groupSlug": "string",
"isControl": false
}
MemberFieldDefinitionListResponse
| Field | Type | Required | Description |
|---|---|---|---|
items | Array<MemberFieldDefinitionResponse> | ✓ |
Example:
{
"items": []
}
MemberFieldDefinitionResponse
| Field | Type | Required | Description |
|---|---|---|---|
key | String | ✓ | |
label | String | ✓ | |
serviceName | String | ||
serviceType | String |
Example:
{
"key": "string",
"label": "string"
}
MemberFieldListResponse
| Field | Type | Required | Description |
|---|---|---|---|
items | Array<MemberFieldResponse> | ✓ | |
total | Integer | ✓ |
Example:
{
"items": [],
"total": 0
}
MemberFieldResponse
| Field | Type | Required | Description |
|---|---|---|---|
createdAt | DateTime | ✓ | |
id | Integer | ✓ | |
key | String | ✓ | |
memberId | Integer | ✓ | |
serviceId | Integer | ✓ | |
serviceName | String | ✓ | |
serviceType | String | ✓ | |
updatedAt | DateTime | ✓ | |
value | String | ✓ |
Example:
{
"id": 0,
"memberId": 0,
"key": "string",
"value": "string",
"serviceId": 0,
"serviceName": "string",
"serviceType": "string",
"createdAt": "2024-01-01T00:00:00Z",
"updatedAt": "2024-01-01T00:00:00Z"
}
MemberImportConflictInfo
| Field | Type | Required | Description |
|---|---|---|---|
code | String | ✓ | |
conflicts | Array<ImportContactConflict> | Default: [] | |
fields | Array | ✓ |
Example:
{
"code": "string",
"fields": [],
"conflicts": []
}
MemberImportIdentitySnapshot
| Field | Type | Required | Description |
|---|---|---|---|
dateOfBirth | Date | ||
name | String |
Example:
{}
MemberImportMatchInfo
| Field | Type | Required | Description |
|---|---|---|---|
matchType | Literal['id', 'uuid', 'external_id', 'email', 'phone', 'account_email', 'account_phone'] | ✓ | |
memberId | Integer | ✓ | |
memberUuid | String | ✓ |
Example:
{
"matchType": "id",
"memberId": 0,
"memberUuid": "string"
}
MemberImportPreviewResponse
| Field | Type | Required | Description |
|---|---|---|---|
previewPlanToken | String | ||
rows | Array<MemberImportPreviewRow> | ✓ | |
summary | MemberImportPreviewSummary | ✓ | |
totalRows | Integer | ✓ |
Example:
{
"totalRows": 0,
"summary": null,
"rows": []
}
MemberImportPreviewRow
| Field | Type | Required | Description |
|---|---|---|---|
action | Literal['create', 'update', 'unchanged', 'conflict', 'skipped', 'error'] | ✓ | |
conflict | MemberImportConflictInfo | null | ||
error | String | ||
existingIdentity | MemberImportIdentitySnapshot | null | ||
incomingIdentity | MemberImportIdentitySnapshot | null | ||
match | MemberImportMatchInfo | null | ||
proposedChanges | Array | Default: [] | |
row | Integer | ✓ | |
sharedContacts | Array | Default: [] |
Example:
{
"row": 0,
"action": "create",
"proposedChanges": [],
"sharedContacts": []
}
MemberImportPreviewSummary
| Field | Type | Required | Description |
|---|---|---|---|
conflict | Integer | Default: 0 | |
create | Integer | Default: 0 | |
error | Integer | Default: 0 | |
skipped | Integer | Default: 0 | |
unchanged | Integer | Default: 0 | |
update | Integer | Default: 0 |
Example:
{
"create": 0,
"update": 0,
"unchanged": 0,
"conflict": 0,
"skipped": 0,
"error": 0
}
MemberImportRunItemResponse
| Field | Type | Required | Description |
|---|---|---|---|
detail | String | ||
index | Integer | ✓ | |
memberId | Integer | ||
reasonCode | String | Default: `` | |
status | String | ✓ |
Example:
{
"index": 0,
"status": "string",
"reasonCode": ""
}
MemberImportRunSummaryResponse
| Field | Type | Required | Description |
|---|---|---|---|
completedAt | String | ||
conflicted | Integer | Default: 0 | |
created | Integer | Default: 0 | |
failed | Integer | Default: 0 | |
runId | String | ✓ | |
skipped | Integer | Default: 0 | |
startedAt | String | ✓ | |
status | String | ✓ | |
terminalError | String | ||
total | Integer | Default: 0 | |
unchanged | Integer | Default: 0 | |
updated | Integer | Default: 0 |
Example:
{
"runId": "string",
"startedAt": "string",
"status": "string",
"total": 0,
"created": 0,
"updated": 0,
"unchanged": 0,
"conflicted": 0,
"skipped": 0,
"failed": 0
}
MemberLabelResponse
| Field | Type | Required | Description |
|---|---|---|---|
color | String | ✓ | |
description | String | ✓ | |
id | Integer | ✓ | |
name | String | ✓ | |
slug | String | ✓ | |
uuid | String | ✓ |
Example:
{
"id": 0,
"uuid": "string",
"name": "string",
"slug": "string",
"color": "string",
"description": "string"
}
MemberRelationshipResponse
| Field | Type | Required | Description |
|---|---|---|---|
createdAt | DateTime | ✓ | |
grantsChartAccess | Boolean | ✓ | |
id | Integer | ✓ | |
kind | <enum MemberRelationshipKind | ✓ | |
relatedMemberId | Integer | ✓ | |
relatedMemberName | String | ||
relatedRole | <enum RelatedMemberRole | ✓ | |
updatedAt | DateTime | ✓ | |
uuid | String | ✓ |
Example:
{
"id": 0,
"uuid": "string",
"kind": null,
"relatedRole": null,
"relatedMemberId": 0,
"grantsChartAccess": false,
"createdAt": "2024-01-01T00:00:00Z",
"updatedAt": "2024-01-01T00:00:00Z"
}
MyDataTypeResponse
| Field | Type | Required | Description |
|---|---|---|---|
canCreate | Boolean | ✓ | |
description | String | ||
fields | Array<SchemaField> | ✓ | |
id | Integer | ✓ | |
isCollection | Boolean | ✓ | |
name | String | ✓ | |
slug | String | ✓ | |
uuid | String | ✓ |
Example:
{
"id": 0,
"uuid": "string",
"slug": "string",
"name": "string",
"isCollection": false,
"fields": [],
"canCreate": false
}
PaginatedResponse[DataRecordResponse]
| Field | Type | Required | Description |
|---|---|---|---|
items | Array<DataRecordResponse> | ✓ | |
page | Integer | ✓ | |
pageSize | Integer | ✓ | |
total | Integer | ✓ | |
totalPages | Integer | ✓ |
Example:
{
"items": [],
"total": 0,
"page": 0,
"pageSize": 0,
"totalPages": 0
}
PaginatedResponse[MemberRelationshipResponse]
| Field | Type | Required | Description |
|---|---|---|---|
items | Array<MemberRelationshipResponse> | ✓ | |
page | Integer | ✓ | |
pageSize | Integer | ✓ | |
total | Integer | ✓ | |
totalPages | Integer | ✓ |
Example:
{
"items": [],
"total": 0,
"page": 0,
"pageSize": 0,
"totalPages": 0
}
PaginatedResponse[WorkspaceMemberResponse]
| Field | Type | Required | Description |
|---|---|---|---|
items | Array<WorkspaceMemberResponse> | ✓ | |
page | Integer | ✓ | |
pageSize | Integer | ✓ | |
total | Integer | ✓ | |
totalPages | Integer | ✓ |
Example:
{
"items": [],
"total": 0,
"page": 0,
"pageSize": 0,
"totalPages": 0
}
SchemaField
| Field | Type | Required | Description |
|---|---|---|---|
adminOnly | Boolean | Whether only admins can see this field (default: False) | |
categories | Array<Literal[personal, identifier, phi, credential]> | Regulatory or content categories for audit and policy | |
celFunction | String | CEL expression that computes this field's value. CONSTRAINT: Can ONLY reference regular fields (TEXT, NUMBER, DATE, etc.). Cannot reference other FUNCTION fields. Syntax: record.data.<field_slug>. Example: 'record.data.score1 + record.data.score2' | |
defaultValue | Any | Default value for the field | |
description | String | Optional field description | |
fieldType | Union[Literal[enum, email, phone, text, longtext, number, integer, boolean, date, datetime, time_of_day, us_zip_code, array, object, function], DataFieldType] | Field type (text, email, enum, etc.) (default: text) | |
name | String | ✓ | Display name for the field |
options | Array<EnumOption> | null | Options for enum fields as {label, value} objects. | |
order | Integer | Deprecated: Display order is now determined by array position | |
referencedTypeId | Integer | Referenced DataType ID for reference fields | |
required | Boolean | Whether field is required (default: False) | |
sensitivity | Literal['public', 'internal', 'confidential', 'restricted', 'secret'] | Disclosure severity for audit and access policy (default: confidential) | |
shouldIndex | Boolean | Whether to index this field (default: False) | |
slug | String | ✓ | Unique field identifier |
validateCel | String | CEL expression for cross-field validation. Context: 'value' (current field value), 'record.data.<field_slug>' (other fields). Returns: true if valid, or a string error message if invalid. CONSTRAINT: Can only reference non-FUNCTION fields. Example: 'value >= record.data.min_score' or 'value < record.data.min_score ? "Must be >= " + string(record.data.min_score) : true' |
Example:
{
"slug": "string",
"name": "string",
"fieldType": "text",
"required": false,
"shouldIndex": false,
"adminOnly": false,
"sensitivity": "confidential"
}
SendPhoneConfirmationResponse
| Field | Type | Required | Description |
|---|---|---|---|
status | String | ✓ |
Example:
{
"status": "string"
}
SharedContactResponse
| Field | Type | Required | Description |
|---|---|---|---|
archived | Boolean | Default: False | |
field | Literal['phone', 'email'] | ✓ | |
memberId | Integer | ✓ |
Example:
{
"field": "phone",
"memberId": 0,
"archived": false
}
UpdateMemberContactPointRequest
| Field | Type | Required | Description |
|---|---|---|---|
capabilities | Array | ||
contactType | Literal[phone, email] | ||
label | String | ||
observedAt | DateTime | ||
priority | Integer | ||
purpose | Literal[general, notification, billing] | ||
sharing | Literal[shared, individual, unknown] | ||
value | String |
Example:
{}
UpdateMemberFieldRequest
| Field | Type | Required | Description |
|---|---|---|---|
value | String | ✓ |
Example:
{
"value": "string"
}
UpdateWorkspaceMemberRequest
| Field | Type | Required | Description |
|---|---|---|---|
accountEnabled | Boolean | ||
accountTosAccepted | Boolean | ||
dateOfBirth | Date | ||
description | String | ||
email | String | ||
externalId | String | ||
isImportProtected | Boolean | ||
isOrgOwner | Boolean | ||
isSuperuser | Boolean | ||
labelIds | Array | ||
locale | String | ||
memberRoleId | Integer | ||
name | String | ||
notifyEmail | Boolean | ||
notifySms | Boolean | ||
notifyVoice | Boolean | ||
notifyWhatsapp | Boolean | ||
phone | String | ||
releaseContactFromMemberId | Integer | ||
timezone | String | ||
title | String | ||
tosAccepted | Boolean | ||
usagePaused | Boolean |
Example:
{}
WorkspaceMemberResponse
| Field | Type | Required | Description |
|---|---|---|---|
accountEnabled | Boolean | ||
accountTosAccepted | Boolean | ✓ | |
accountUuid | String | ✓ | |
canLogin | Boolean | Default: True | |
createdAt | DateTime | ✓ | |
dateOfBirth | Date | ||
description | String | ✓ | |
email | String | ✓ | |
emailVerified | Boolean | Default: False | |
experimentGroup | MemberExperimentGroupSummary | null | ||
externalId | String | ✓ | |
homeFolderId | Integer | ||
id | Integer | ✓ | |
isArchived | Boolean | Default: False | |
isImportProtected | Boolean | Default: False | |
isOrgOwner | Boolean | ||
isSuperuser | Boolean | ||
labels | Array<MemberLabelResponse> | Default: [] | |
locale | String | ✓ | |
memberRoleId | Integer | ✓ | |
memberRoleName | String | ✓ | |
memberRoleSystemKey | String | ||
memberType | String | Default: member | |
name | String | ✓ | |
notifyEmail | Boolean | ✓ | |
notifySms | Boolean | ✓ | |
notifyVoice | Boolean | ✓ | |
notifyWhatsapp | Boolean | Default: False | |
orgRole | String | ||
phone | String | ✓ | |
phoneType | String | ✓ | |
phoneVerified | Boolean | Default: False | |
role | String | ✓ | |
sharedContactPlacements | Array<SharedContactResponse> | Default: [] | |
timezone | String | ||
title | String | ||
tosAccepted | Boolean | ✓ | |
updatedAt | DateTime | ✓ | |
usagePaused | Boolean | Default: False | |
uuid | String | ✓ |
Example:
{
"id": 0,
"uuid": "string",
"role": "string",
"tosAccepted": false,
"accountTosAccepted": false,
"accountUuid": "string",
"createdAt": "2024-01-01T00:00:00Z",
"updatedAt": "2024-01-01T00:00:00Z",
"name": "string",
"description": "string",
"phone": "string",
"phoneType": "string",
"email": "string",
"externalId": "string",
"emailVerified": false,
"phoneVerified": false,
"notifySms": false,
"notifyEmail": false,
"notifyVoice": false,
"notifyWhatsapp": false,
"locale": "string",
"memberRoleId": 0,
"memberRoleName": "string",
"labels": [],
"memberType": "member",
"isArchived": false,
"isImportProtected": false,
"usagePaused": false,
"canLogin": true,
"sharedContactPlacements": []
}
Endpoints
List & activity
GET /api/v2/w/{workspace_uuid}/members- MembersGET /api/v2/w/{workspace_uuid}/members/message-activity- Message Activity
Create & manage
POST /api/v2/w/{workspace_uuid}/members- MembersPUT /api/v2/w/{workspace_uuid}/members/by-external-id/{external_id}- Update By External IdPOST /api/v2/w/{workspace_uuid}/members/by-external-id/{external_id}/archive- ArchivePOST /api/v2/w/{workspace_uuid}/members/by-external-id/{external_id}/unarchive- UnarchiveGET /api/v2/w/{workspace_uuid}/members/by-uuid/{uuid}- By UuidDELETE /api/v2/w/{workspace_uuid}/members/{member_id}- Delete MembersGET /api/v2/w/{workspace_uuid}/members/{member_id}- MembersPUT /api/v2/w/{workspace_uuid}/members/{member_id}- Update MembersPOST /api/v2/w/{workspace_uuid}/members/{member_id}/archive- ArchivePOST /api/v2/w/{workspace_uuid}/members/{member_id}/phone-confirmation- Phone ConfirmationPOST /api/v2/w/{workspace_uuid}/members/{member_id}/unarchive- Unarchive
Current member (me)
DELETE /api/v2/w/{workspace_uuid}/me- Delete MeGET /api/v2/w/{workspace_uuid}/me- MePUT /api/v2/w/{workspace_uuid}/me- Update MeGET /api/v2/w/{workspace_uuid}/me/credentials- CredentialsDELETE /api/v2/w/{workspace_uuid}/me/credentials/{credential_id}- Delete Credentials
Custom fields
GET /api/v2/w/{workspace_uuid}/member-field-definitions- Member Field DefinitionsGET /api/v2/w/{workspace_uuid}/members/{member_id}/fields- FieldsPOST /api/v2/w/{workspace_uuid}/members/{member_id}/fields- FieldsDELETE /api/v2/w/{workspace_uuid}/members/{member_id}/fields/{field_id}- Delete FieldsPUT /api/v2/w/{workspace_uuid}/members/{member_id}/fields/{field_id}- Update Fields
Bulk operations
CSV import
POST /api/v2/w/{workspace_uuid}/members/import/preview- PreviewGET /api/v2/w/{workspace_uuid}/members/import/runs- RunsPOST /api/v2/w/{workspace_uuid}/members/import/runs- RunsGET /api/v2/w/{workspace_uuid}/members/import/runs/{run_id}/items- Items
Export
Contacts
GET /api/v2/w/{workspace_uuid}/members/{member_id}/contacts- ContactsPOST /api/v2/w/{workspace_uuid}/members/{member_id}/contacts- ContactsDELETE /api/v2/w/{workspace_uuid}/members/{member_id}/contacts/{contact_uuid}- Delete ContactsPUT /api/v2/w/{workspace_uuid}/members/{member_id}/contacts/{contact_uuid}- Update ContactsPOST /api/v2/w/{workspace_uuid}/members/{member_id}/contacts/{contact_uuid}/promote- Promote
Import Ndjson
My records (me)
GET /api/v2/w/{workspace_uuid}/me/data-types- Data TypesGET /api/v2/w/{workspace_uuid}/me/records- Records
Relationships
GET /api/v2/w/{workspace_uuid}/members/{member_id}/relationships- RelationshipsPOST /api/v2/w/{workspace_uuid}/members/{member_id}/relationships- RelationshipsDELETE /api/v2/w/{workspace_uuid}/members/{member_id}/relationships/{relationship_id}- Delete Relationships
List & activity
List and search the member roster, with message-activity summaries.
Members
GET /api/v2/w/{workspace_uuid}/members
Description:
List all workspace members with filtering and pagination.
Authorization: Requires members:read scope
Parameters:
workspace_uuid(String)memberFilterId(Integer)query(String)search(String)role(String)member_type(String)member_types(String)is_archived(Boolean)is_manager(Boolean)has_account(Boolean)exclude_ids(String)experimentId(Integer)experimentGroupId(Integer)experimentUnassigned(Boolean)page(Integer) — min: 1pageSize(Integer) — min: 1, max: 100sortBy(MemberSortField)sortOrder(SortOrder)
Response: See PaginatedResponse[WorkspaceMemberResponse]
Message Activity
GET /api/v2/w/{workspace_uuid}/members/message-activity
Description:
Get message activity (count per day) for specified members.
Authorization: Requires members:read scope
Parameters:
workspace_uuid(String)member_ids(String)days(Integer) — min: 1, max: 90
Response: dict[int, list[int]]
Create & manage
Create, fetch, update, archive, and delete Members.
Members
POST /api/v2/w/{workspace_uuid}/members
Description:
Create a new workspace member.
Authorization: Requires members:write scope
Parameters:
request- See CreateWorkspaceMemberRequest
Response: See WorkspaceMemberResponse
Update By External Id
PUT /api/v2/w/{workspace_uuid}/members/by-external-id/{external_id}
Description:
Update a workspace member addressed by its external id.
The external-id twin of PUT /members/\{member_id}, for an integrator that
keys on its own external_id and never stores our numeric member id.
Resolution runs on the id route's own pre-write read session, and the write
runs through the id route's own body — so the authorization, validation, and
audit behaviour are identical, and an external-id address is not a weaker
path to the same PHI.
Authorization: Requires members:write scope
Parameters:
external_id(String)request- See UpdateWorkspaceMemberRequest
Response: See WorkspaceMemberResponse
Archive
POST /api/v2/w/{workspace_uuid}/members/by-external-id/{external_id}/archive
Description:
Archive a workspace member addressed by its external id.
Resolves the member through MembersService and delegates to the same
MembersService.archive_member the id route calls, so the archived state,
response body, and post-commit audit event are identical.
Authentication: Requires authenticated user
Parameters:
external_id(String)_body(Object)
Response: See WorkspaceMemberResponse
Unarchive
POST /api/v2/w/{workspace_uuid}/members/by-external-id/{external_id}/unarchive
Description:
Unarchive a member addressed by its external id.
The external-id twin of POST /members/\{member_id}/unarchive; it runs the
same GLB membership invariant through MembersService.unarchive_member.
Authentication: Requires authenticated user
Parameters:
external_id(String)_body(Object)
Response: See WorkspaceMemberResponse
By Uuid
GET /api/v2/w/{workspace_uuid}/members/by-uuid/{uuid}
Description:
Get a workspace member by UUID.
The uuid-addressed twin of GET /members/\{member_id}, added for the
Activity Spine webhook envelope, which addresses a member by uuid.
Resolution and authorization are the integer read's own path: the lookup
runs in the same workspace-bound session and applies the same two gates —
self-access, otherwise MEMBERS_READ. A uuid from another workspace
cannot resolve at all (the session sees one workspace schema), and a
caller without MEMBERS_READ probing another member's uuid gets the
same 403 whether or not the uuid names a row, so the route is not an
existence oracle.
@phi_audit("member") is deliberate: this is a PHI-bearing read path,
and every PHI-bearing read path must be audited. The integer-id twin
predated the decorator; it was re-classified in its own reviewed change
(GH #27182) and now carries the same marker, so the two twins emit the
same event and gate identically when PHI posture enforcement flips from
shadow to enforce.
The audit subject is the numeric member id (via the resource_id
callback), the same spelling the id-addressed member routes record, so
"who read member N" returns both. The path segment is \{uuid} rather
than \{member_uuid} on purpose: @phi_audit auto-records a
\{resource_type}_uuid path parameter as the subject, and that channel
cannot be overridden once the URL has named it.
Authentication: Requires workspace member
Parameters:
uuid(String)
Response: See WorkspaceMemberResponse
Delete Members
DELETE /api/v2/w/{workspace_uuid}/members/{member_id}
Description:
Permanently delete a workspace member and all their associated data.
Important: Members must be archived first before deletion. Use the archive endpoint to safely remove a member from the workspace. Permanent deletion is a destructive operation that cannot be undone.
The force flag allows workspace managers to auto-archive before deletion.
Without force, this endpoint is restricted to superusers for erasure scenarios.
reassign_to_id is accepted for query-shape compatibility and rejected with
422 when set: choosing a replacement Member is not authorization to widen
that Member's access, so ownership must be changed through the owning
resource's own authorized API first. A resource that still blocks erasure
comes back as a 409 naming the blocking table.column.
Authorization: Requires members:admin scope
Parameters:
member_id(Integer)reassign_to_id(Integer)force(Boolean)
Response: See DeleteMembershipResponse
Members
GET /api/v2/w/{workspace_uuid}/members/{member_id}
Description:
Get a workspace member by ID.
Self-access: Users can view their own member profile. Admin access: MEMBERS_READ scope required for viewing other members.
@phi_audit("member") classifies this read and emits the same
PHI_RECORD_VIEWED event as its by-uuid twin below (GH #27182). The
subject is the numeric member id, which the decorator reads straight off
the member_id path parameter — no resource_id callback is needed
here, and the twin's callback exists only because its path names a uuid.
The asymmetry this closes was not cosmetic: PHI posture classification is
read off the @phi_audit marker
(lib/middleware/phi_posture_seam.py), so while this route was
unclassified the two twins would have diverged the moment enforcement
flipped from shadow to enforce — one gated on credential posture, the
other not.
Authentication: Requires workspace member
Parameters:
member_id(Integer)
Response: See WorkspaceMemberResponse
Update Members
PUT /api/v2/w/{workspace_uuid}/members/{member_id}
Description:
Update a workspace member.
Authorization: Requires members:write scope
Parameters:
member_id(Integer)request- See UpdateWorkspaceMemberRequest
Response: See WorkspaceMemberResponse
Archive
POST /api/v2/w/{workspace_uuid}/members/{member_id}/archive
Description:
Archive a workspace member instead of deleting them.
Authentication: Requires authenticated user
Parameters:
member_id(Integer)
Response: See WorkspaceMemberResponse
Phone Confirmation
POST /api/v2/w/{workspace_uuid}/members/{member_id}/phone-confirmation
Description:
Text a member asking them to confirm their phone (member-attested trust).
Authorization: Requires members:write scope
Parameters:
member_id(Integer)
Response: See SendPhoneConfirmationResponse
Unarchive
POST /api/v2/w/{workspace_uuid}/members/{member_id}/unarchive
Description:
Unarchive a previously archived workspace member.
For account-backed members this enforces the GLB membership invariant: the
GLB workspace_memberships link must exist or be recreatable (the account is
still in the workspace's org). When it isn't, unarchive_account_member_by_id
raises ConflictError -> HTTP 409 via the global handler and the member
stays archived.
Authentication: Requires authenticated user
Parameters:
member_id(Integer)
Response: See WorkspaceMemberResponse
Current member (me)
The authenticated member's own profile and credentials.
Delete Me
DELETE /api/v2/w/{workspace_uuid}/me
Description:
Leave a workspace.
Archives the workspace-level Member (so they no longer appear as active to others, while preserving assignments, chats, and audit history) and removes the account-to-workspace association so the user loses access.
Authentication: Requires workspace member
Response: See DeleteMembershipResponse
Me
GET /api/v2/w/{workspace_uuid}/me
Description:
Get the current user's workspace member profile.
This is a self-access endpoint - no special scope required. Includes the effective scopes and org role that the API honors for this user.
Authentication: Requires workspace member
Response: See CurrentMemberResponse
Update Me
PUT /api/v2/w/{workspace_uuid}/me
Description:
Update the current user's workspace member profile.
This is a self-access endpoint - no special scope required.
Authentication: Requires workspace member
Parameters:
request- See UpdateWorkspaceMemberRequest
Response: See WorkspaceMemberResponse
Credentials
GET /api/v2/w/{workspace_uuid}/me/credentials
Description:
Get the current member's connected integration credentials (Discord, etc.).
This is a self-access endpoint - no special scope required.
Authentication: Requires workspace member
Response: List of MemberCredentialResponse
Delete Credentials
DELETE /api/v2/w/{workspace_uuid}/me/credentials/{credential_id}
Description:
Delete/unlink a credential from the current member's account.
This is a self-access endpoint - no special scope required.
Authentication: Requires workspace member
Parameters:
credential_id(Integer)
Response: dict[str, str]
Custom fields
Custom field definitions and per-member field values.
Member Field Definitions
GET /api/v2/w/{workspace_uuid}/member-field-definitions
Description:
Get available field definitions for this workspace.
Returns field keys and labels from active app connections' managed field definitions, plus any distinct user-created field keys.
Authorization: Requires members:read scope
Response: See MemberFieldDefinitionListResponse
Fields
GET /api/v2/w/{workspace_uuid}/members/{member_id}/fields
Description:
Get all fields for a member.
Returns all key-value fields associated with this member, including service-owned fields and placeholder entries for managed field definitions that don't have a value yet.
Authorization: Requires members:read scope
Parameters:
member_id(Integer)
Response: See MemberFieldListResponse
Fields
POST /api/v2/w/{workspace_uuid}/members/{member_id}/fields
Description:
Create a new field for a member.
When serviceId is provided, creates a managed field owned by that app connection. The key must match a managed field definition declared by the connection. Otherwise creates a user-owned field.
Authorization: Requires members:write scope
Parameters:
member_id(Integer)request- See CreateMemberFieldRequest
Response: See MemberFieldResponse
Delete Fields
DELETE /api/v2/w/{workspace_uuid}/members/{member_id}/fields/{field_id}
Description:
Delete a member field.
Only user-created fields (service_id is null) can be deleted. Service-owned fields are read-only.
Authorization: Requires members:write scope
Parameters:
member_id(Integer)field_id(Integer)
Response: dict[str, str]
Update Fields
PUT /api/v2/w/{workspace_uuid}/members/{member_id}/fields/{field_id}
Description:
Update a member field value.
Both user-created and service-owned (managed) fields can have their values updated. The app connection owns the field's existence; the admin owns the value.
Authorization: Requires members:write scope
Parameters:
member_id(Integer)field_id(Integer)request- See UpdateMemberFieldRequest
Response: See MemberFieldResponse
Bulk operations
Bulk member operations.
Bulk
POST /api/v2/w/{workspace_uuid}/members/bulk
Description:
Bulk create or upsert workspace members.
Authorization: Requires members:write scope
Parameters:
request- See BulkCreateMembersRequest
Response: See BulkCreateMembersResponse
CSV import
Preview and run a CSV member import.
Preview
POST /api/v2/w/{workspace_uuid}/members/import/preview
Description:
Preview a Member CSV without changing records. Requires members:admin and a valid new_member_role_id. Returns row classifications and counts for creates, updates, unchanged rows, conflicts, skips and errors. Review contact and identity conflicts before submitting an import; the authorized preview may include existing and incoming values for comparison. Treat those values as sensitive and do not log them.
Authorization: Requires members:admin scope
Parameters:
file(UploadFile)new_member_role_id(Integer)resolutions(String)auto_promote_unique_contacts(Boolean)
Response: See MemberImportPreviewResponse
Runs
GET /api/v2/w/{workspace_uuid}/members/import/runs
Description:
List recent members import runs, newest first.
Authorization: Requires members:admin scope
Parameters:
limit(Integer) — min: 1, max: 100
Response: List of MemberImportRunSummaryResponse
Runs
POST /api/v2/w/{workspace_uuid}/members/import/runs
Description:
Start a durable Member CSV import and stream progress as SSE events: import_run, import_item and done. The import continues if the stream disconnects. Use GET /members/import/runs for run summaries and GET /members/import/runs/{run_id}/items for row outcomes. Requires members:admin, a valid new_member_role_id and an uploaded CSV. Review the preview before choosing identity overwrites. Contact conflicts need an explicit per-row resolution; unresolved conflicts write nothing. A supplied resolutions entry takes precedence over that row's conflict_resolution CSV column. A concurrently running Member import returns 409. The preview is not a reservation: matching is checked again when the import runs.
Authentication: Public endpoint (no authentication required)
Parameters:
file(UploadFile)new_member_role_id(Integer)identity_conflict_policy(IdentityConflictPolicy)resolutions(String)auto_promote_unique_contacts(Boolean)
Response: StreamingResponse
Items
GET /api/v2/w/{workspace_uuid}/members/import/runs/{run_id}/items
Description:
List per-row outcomes for a Member import run in this Workspace. Requires members:admin. Returns 404 when the run is not a Member import owned by this Workspace. Use limit to bound returned rows.
Authorization: Requires members:admin scope
Parameters:
run_id(String)limit(Integer) — min: 1, max: 10000
Response: List of MemberImportRunItemResponse
Export
Export the member roster.
Export
POST /api/v2/w/{workspace_uuid}/members/export
Description:
Export members to CSV, matching the same filters the list view applies.
Authorization: Requires members:admin scope
Parameters:
selected_fields(Array) selected_data_types(Array) member_type(String)member_types(String)search(String)memberFilterId(Integer)query(String)role(String)is_archived(Boolean)
Response: StreamingResponse
Contacts
Contacts
GET /api/v2/w/{workspace_uuid}/members/{member_id}/contacts
Description:
The people in a workspace — roster, profiles, custom fields, and bulk import/export
List a Member's contact points. Self, or members:read.
Authentication: Requires workspace member
Parameters:
member_id(Integer)include_retired(Boolean)
Response: See MemberContactPointListResponse
Contacts
POST /api/v2/w/{workspace_uuid}/members/{member_id}/contacts
Description:
The people in a workspace — roster, profiles, custom fields, and bulk import/export
Add a contact point. Self, or members:write.
Authentication: Requires workspace member
Parameters:
member_id(Integer)request- See CreateMemberContactPointRequest
Response: See MemberContactPointResponse
Delete Contacts
DELETE /api/v2/w/{workspace_uuid}/members/{member_id}/contacts/{contact_uuid}
Description:
The people in a workspace — roster, profiles, custom fields, and bulk import/export
Retire a point (a state change; the row and provenance remain).
Authentication: Requires workspace member
Parameters:
member_id(Integer)contact_uuid(String)request(RetireMemberContactPointRequest)
Response: See MemberContactPointResponse
Update Contacts
PUT /api/v2/w/{workspace_uuid}/members/{member_id}/contacts/{contact_uuid}
Description:
The people in a workspace — roster, profiles, custom fields, and bulk import/export
Change a point's value and/or annotations. Self, or members:write.
Authentication: Requires workspace member
Parameters:
member_id(Integer)contact_uuid(String)request- See UpdateMemberContactPointRequest
Response: See MemberContactPointResponse
Promote
POST /api/v2/w/{workspace_uuid}/members/{member_id}/contacts/{contact_uuid}/promote
Description:
The people in a workspace — roster, profiles, custom fields, and bulk import/export
Make a point the member's primary value.
Self, or members:admin when the target is another member: this is the
one contact-point operation that writes the member's phone/email
scalar, the gate PUT /members/\{id} carries for that field.
Refuses with 409 while another member holds the value as primary, or while another global Account holds it as its credential; with 400 for a retired point or a test/anonymous member. The previous primary is kept as a contact point.
The (empty) JSON body is a deliberate CSRF barrier: authToken defaults
to SameSite=None, so a bodyless POST is forgeable by a cross-site HTML form;
requiring JSON forces cross-origin callers into CORS preflight (GRA-6284).
Authentication: Requires workspace member
Parameters:
member_id(Integer)contact_uuid(String)_body(Object)
Response: See MemberContactPointResponse
Import Ndjson
Import
POST /api/v2/w/{workspace_uuid}/members/import
Description:
The people in a workspace — roster, profiles, custom fields, and bulk import/export
Import members from CSV file with streaming progress updates.
Contact conflicts (a row's email/phone disagreeing with the Account it matches) are resolved per ROW, not per request, over either transport:
- the
conflict_resolutionCSV column (keep_account/skip), for programmatic callers that generate the file; - the
resolutionsform field, for the wizard — it reviews the read-only preview and cannot rebuild the CSV (identity-header aliasing is server-side), and it can also correct a value (replace_values), which no column can express.
The JSON field wins over the column for the same row: the column is a
property of the uploaded file, the JSON is what the operator just decided.
Rows with neither stream a conflict event and write nothing.
A resolution naming a row the file does not contain is a 400 (row numbers
only — never values). See process_import for what a decision means when
the row no longer conflicts at commit time.
identity_conflict_policy='overwrite_identity_fields' is intended to be
sent only after an operator reviews a preview. Two known, accepted limits:
- Preview→commit is not transactional (TOCTOU): the commit re-classifies each
row against live DB state, so under the default
skippolicy a row that became a conflict after the preview is still skipped. Underoverwritethe operator's prior approval is applied to current state, so an identity that changed between preview and commit is overwritten on the stale approval. Closing this would require optimistic locking / a preview token. - Preview-first is advisory, not enforced:
overwriterequires onlyMEMBERS_ADMIN(which can already mutate identity via the member-update API) and every overwrite is audited; there is no backend gate requiring a prior preview call.
Authorization: Requires members:admin scope
Parameters:
file(UploadFile)new_member_role_id(Integer)identity_conflict_policy(IdentityConflictPolicy)resolutions(String)auto_promote_unique_contacts(Boolean)
Response: StreamingResponse
My records (me)
The authenticated member's own DataTypes and records (self-access, no coarse scope).
Data Types
GET /api/v2/w/{workspace_uuid}/me/data-types
Description:
List member-scoped DataTypes the current Member may use.
Self-access — no special scope required, mirroring GET /members/me.
Admin-only Forms are listed only for records:admin, even to their owner;
canCreate runs the same gate record creation enforces, so a client can
offer an Add control only where a create would succeed.
Authentication: Requires workspace member
Response: List of MyDataTypeResponse
Records
GET /api/v2/w/{workspace_uuid}/me/records
Description:
List the current Member's own records for one DataType.
Self-access — no special scope required. Records are hard-filtered to the
session Member (member_id == self); there is no parameter that widens
this. An admin-only Form answers 404 without records:admin, even for
its owner, as the DataRecord policy decides.
Query Parameters:
data_type_id: DataType to list the Member's own records forpage(default 1) /page_size(default 50, max 100): pagination
Authentication: Requires workspace member
Parameters:
data_type_id(Integer) — min: 1page(Integer) — min: 1page_size(Integer) — min: 1, max: 100
Response: See PaginatedResponse[DataRecordResponse]
Relationships
Relationships
GET /api/v2/w/{workspace_uuid}/members/{member_id}/relationships
Description:
The people in a workspace — roster, profiles, custom fields, and bulk import/export
Authorization: Requires members:read scope
Parameters:
member_id(Integer)page(Integer) — min: 1pageSize(Integer) — min: 1, max: 100kind(MemberRelationshipKind)
Response: See PaginatedResponse[MemberRelationshipResponse]
Relationships
POST /api/v2/w/{workspace_uuid}/members/{member_id}/relationships
Description:
The people in a workspace — roster, profiles, custom fields, and bulk import/export
Authorization: Requires members:write scope
Parameters:
member_id(Integer)request_body(CreateMemberRelationshipRequest)
Response: See MemberRelationshipResponse
Delete Relationships
DELETE /api/v2/w/{workspace_uuid}/members/{member_id}/relationships/{relationship_id}
Description:
The people in a workspace — roster, profiles, custom fields, and bulk import/export
Authorization: Requires members:write scope
Parameters:
member_id(Integer)relationship_id(Integer)
Response: See MemberRelationshipResponse