HelloJohn / docs
Users

Update Users

Update user profiles, roles, passwords, and metadata in HelloJohn.

Update Users

Users can update their own profile via the SDK, or admins can update any user via the API.


Update Profile (Self-Service)

Users update their own profile with their session token:

import { useUser } from "@hellojohn/react";

function EditProfile() {
  const { user, update } = useUser();

  const handleSubmit = async (e: React.FormEvent<HTMLFormElement>) => {
    e.preventDefault();
    const data = new FormData(e.currentTarget);

    await update({
      name: data.get("name") as string,
      avatar_url: data.get("avatar_url") as string,
    });
  };

  return (
    <form onSubmit={handleSubmit}>
      <input name="name" defaultValue={user.name} />
      <input name="avatar_url" defaultValue={user.avatar_url ?? ""} />
      <button type="submit">Save</button>
    </form>
  );
}

Update Profile (Admin)

Admins can update any user via secret key:

curl -X PATCH "https://api.hellojohn.dev/v1/users/usr_01HABCDEF123456" \
  -H "Authorization: Bearer sk_live_abc123" \
  -H "X-Tenant-ID: tnt_01HABCDEF654321" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Alice J. Smith",
    "email": "alice.new@example.com",
    "phone_number": "+14155552671",
    "role": "admin"
  }'

Updatable fields:

FieldSelf-ServiceAdmin
name
avatar_url
email✅ (triggers re-verification)
phone_number
role
email_verified
public_metadata
private_metadata

Change Password

User changes own password

Requires the current password for verification:

const { user } = useUser();

await user.updatePassword({
  current_password: "OldPassword123!",
  new_password: "NewPassword456!",
});

Via API:

curl -X POST "https://api.hellojohn.dev/v1/auth/password/change" \
  -H "Authorization: Bearer eyJhbGciOiJFZERTQSJ9..." \
  -H "Content-Type: application/json" \
  -d '{
    "current_password": "OldPassword123!",
    "new_password": "NewPassword456!"
  }'

Admin sets a new password

Admins can set any user's password without knowing the current one:

curl -X POST "https://api.hellojohn.dev/v1/users/usr_01HABCDEF123456/password" \
  -H "Authorization: Bearer sk_live_abc123" \
  -H "X-Tenant-ID: tnt_01HABCDEF654321" \
  -H "Content-Type: application/json" \
  -d '{
    "password": "TemporaryPass123!",
    "sign_out_all_sessions": true
  }'

Setting sign_out_all_sessions: true revokes all existing sessions after the password change.


Update Email

Changing email triggers a new verification email by default. The old email remains active until the new one is verified:

curl -X PATCH "https://api.hellojohn.dev/v1/users/usr_01HABCDEF123456" \
  -H "Authorization: Bearer sk_live_abc123" \
  -H "X-Tenant-ID: tnt_01HABCDEF654321" \
  -H "Content-Type: application/json" \
  -d '{"email": "alice.new@example.com"}'

To skip re-verification (admin only):

{
  "email": "alice.new@example.com",
  "email_verified": true
}

Update Role

Assign or change a user's system-level role:

curl -X PATCH "https://api.hellojohn.dev/v1/users/usr_01HABCDEF123456" \
  -H "Authorization: Bearer sk_live_abc123" \
  -H "X-Tenant-ID: tnt_01HABCDEF654321" \
  -H "Content-Type: application/json" \
  -d '{"role": "admin"}'

System roles differ from organization roles. System roles apply tenant-wide; organization roles apply within a specific org.


Disable / Enable Users

Disabling a user prevents them from signing in. Existing sessions remain until they expire.

# Disable
curl -X POST "https://api.hellojohn.dev/v1/users/usr_01HABCDEF123456/disable" \
  -H "Authorization: Bearer sk_live_abc123" \
  -H "X-Tenant-ID: tnt_01HABCDEF654321"

# Enable
curl -X POST "https://api.hellojohn.dev/v1/users/usr_01HABCDEF123456/enable" \
  -H "Authorization: Bearer sk_live_abc123" \
  -H "X-Tenant-ID: tnt_01HABCDEF654321"

To also revoke sessions immediately when disabling:

curl -X POST "https://api.hellojohn.dev/v1/users/usr_01HABCDEF123456/disable" \
  -H "Authorization: Bearer sk_live_abc123" \
  -H "X-Tenant-ID: tnt_01HABCDEF654321" \
  -H "Content-Type: application/json" \
  -d '{"revoke_sessions": true}'

On this page