HelloJohn / docs
Organizations

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

RoleDescription
ownerFull control — can delete the org, transfer ownership
adminManage members and settings, cannot delete org
memberStandard 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:

ParameterTypeDescription
rolestringFilter by role
qstringSearch by name or email
limitintegerDefault 20, max 100
cursorstringPagination 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:

OperationRequired Role
Promote to adminowner
Demote from adminowner
Promote to ownerowner (transfers ownership)
Change member roleadmin, 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>
  );
}

On this page