Membership
How to add, update, and remove members from organizations in HelloJohn.
Membership
Organization membership connects users to organizations with a specific role. Members can be added programmatically via the API, through invitations, or directly from the dashboard.
Member Object
{
"user_id": "usr_01HABCDEF123456",
"organization_id": "org_01HABCDEF777666",
"role": "member",
"joined_at": "2024-01-15T10:00:00Z",
"user": {
"id": "usr_01HABCDEF123456",
"email": "alice@example.com",
"name": "Alice Smith",
"avatar_url": null
}
}Roles
| Role | Description |
|---|---|
owner | Full control — can delete the org, transfer ownership |
admin | Manage members and settings, cannot delete org |
member | Standard access, no management capabilities |
Custom roles are available on the Pro plan and above. See Permissions.
Listing Members
Via API
curl "https://api.hellojohn.dev/v1/organizations/org_01HABCDEF777666/members" \
-H "Authorization: Bearer sk_live_abc123" \
-H "X-Tenant-ID: tnt_01HABCDEF654321"Query parameters:
| Parameter | Type | Description |
|---|---|---|
role | string | Filter by role |
q | string | Search by name or email |
limit | integer | Default 20, max 100 |
cursor | string | Pagination cursor |
Response:
{
"data": [
{
"user_id": "usr_01HABCDEF123456",
"role": "owner",
"joined_at": "2024-01-10T09:00:00Z",
"user": {
"email": "alice@example.com",
"name": "Alice Smith"
}
}
],
"total": 12,
"next_cursor": null
}Via SDK (React)
import { useOrganization } from "@hellojohn/react";
function MemberList() {
const { members, isLoading } = useOrganization();
if (isLoading) return <p>Loading...</p>;
return (
<ul>
{members.map((member) => (
<li key={member.user_id}>
{member.user.name} — {member.role}
</li>
))}
</ul>
);
}Adding a Member Directly
Add an existing user to an organization without sending an invitation:
curl -X POST "https://api.hellojohn.dev/v1/organizations/org_01HABCDEF777666/members" \
-H "Authorization: Bearer sk_live_abc123" \
-H "X-Tenant-ID: tnt_01HABCDEF654321" \
-H "Content-Type: application/json" \
-d '{
"user_id": "usr_01HABCDEF789012",
"role": "member"
}'Response: 201 Created — Returns the membership object.
Direct add requires the user to already exist in the tenant. To add external users, use Invitations.
Updating a Member's Role
curl -X PATCH "https://api.hellojohn.dev/v1/organizations/org_01HABCDEF777666/members/usr_01HABCDEF789012" \
-H "Authorization: Bearer sk_live_abc123" \
-H "X-Tenant-ID: tnt_01HABCDEF654321" \
-H "Content-Type: application/json" \
-d '{"role": "admin"}'Access control:
| Operation | Required Role |
|---|---|
| Promote to admin | owner |
| Demote from admin | owner |
| Promote to owner | owner (transfers ownership) |
Change member role | admin, owner |
Removing a Member
curl -X DELETE "https://api.hellojohn.dev/v1/organizations/org_01HABCDEF777666/members/usr_01HABCDEF789012" \
-H "Authorization: Bearer sk_live_abc123" \
-H "X-Tenant-ID: tnt_01HABCDEF654321"Response: 204 No Content
Removing a member does not delete their user account — only the membership is removed. Their active sessions within this organization context are revoked.
Leaving an Organization
Users can remove themselves from an organization via the SDK:
const { organization } = useOrganization();
await organization.leave();Owners cannot leave if they are the only owner. They must transfer ownership first or delete the organization.
Transferring Ownership
To transfer ownership to another member:
curl -X PATCH "https://api.hellojohn.dev/v1/organizations/org_01HABCDEF777666/members/usr_01HABCDEF789012" \
-H "Authorization: Bearer sk_live_abc123" \
-H "X-Tenant-ID: tnt_01HABCDEF654321" \
-H "Content-Type: application/json" \
-d '{"role": "owner"}'This promotes the target user to owner and demotes the current owner to admin.
Building a Members Page
import { useOrganization } from "@hellojohn/react";
function MembersPage() {
const { members, currentUserRole, removeMember, updateMemberRole } =
useOrganization();
const canManage = ["owner", "admin"].includes(currentUserRole);
return (
<table>
<thead>
<tr>
<th>Name</th>
<th>Email</th>
<th>Role</th>
{canManage && <th>Actions</th>}
</tr>
</thead>
<tbody>
{members.map((m) => (
<tr key={m.user_id}>
<td>{m.user.name}</td>
<td>{m.user.email}</td>
<td>{m.role}</td>
{canManage && (
<td>
<button onClick={() => removeMember(m.user_id)}>Remove</button>
</td>
)}
</tr>
))}
</tbody>
</table>
);
}