Managing Users
Create, update, disable, and delete users in HelloJohn — REST API, SDK, and hjctl examples. User metadata, profile management, and bulk operations.
Listing users
GET /v2/admin/tenants/{tenantId}/users?page=1&limit=20&search=alice
Authorization: Bearer $ADMIN_TOKENFilter options:
search— partial match on email, first_name, last_namerole— filter by role:adminormemberstatus— filter by status:active,disabled,pendingmfa_enrolled—trueorfalse
{
"users": [{ "id": "usr_01HX...", "email": "alice@acme.com", ... }],
"total": 42,
"page": 1,
"limit": 20
}Getting a user
GET /v2/admin/tenants/{tenantId}/users/{userId}
# or by email:
GET /v2/admin/tenants/{tenantId}/users/email/{email}Creating a user
Admin-created users (no email verification required by default):
POST /v2/admin/tenants/{tenantId}/users
Authorization: Bearer $ADMIN_TOKEN
Content-Type: application/json
{
"email": "bob@acme.com",
"password": "temporary-password-123",
"first_name": "Bob",
"last_name": "Smith",
"roles": ["member"],
"metadata": { "department": "sales" },
"send_welcome_email": true
}Updating a user
PATCH /v2/admin/tenants/{tenantId}/users/{userId}
Content-Type: application/json
{
"first_name": "Robert",
"roles": ["admin"],
"metadata": { "department": "engineering" }
}Metadata is merged (not replaced). To remove a metadata key, set it to null:
{ "metadata": { "old_key": null } }Disabling a user
Disabling a user immediately revokes all their active sessions. They can't log in until re-enabled.
PATCH /v2/admin/tenants/{tenantId}/users/{userId}
{ "status": "disabled" }Re-enable:
PATCH /v2/admin/tenants/{tenantId}/users/{userId}
{ "status": "active" }Deleting a user
DELETE /v2/admin/tenants/{tenantId}/users/{userId}Deleting a user permanently removes their account, sessions, and MFA enrollment. It cannot be undone. All active sessions are revoked immediately.
Resetting a password (admin)
Force a password reset for a user:
POST /v2/admin/tenants/{tenantId}/users/{userId}/password-reset
Content-Type: application/json
{
"send_email": true, // send reset link via email
"temporary_password": null // or set a temporary password directly
}User self-service (SDK)
Users can update their own profile through the SDK:
import { useUser } from '@hellojohn/react'
function ProfileForm() {
const { user, updateProfile } = useUser()
async function handleSubmit(e: React.FormEvent<HTMLFormElement>) {
e.preventDefault()
const form = e.currentTarget
await updateProfile({
firstName: form.firstName.value,
lastName: form.lastName.value,
})
}
return (
<form onSubmit={handleSubmit}>
<input name="firstName" defaultValue={user?.firstName} />
<input name="lastName" defaultValue={user?.lastName} />
<button type="submit">Save</button>
</form>
)
}// Update own profile
await hj.user.updateProfile({
firstName: 'Alice',
lastName: 'Chen',
})
// Change own password
await hj.user.updatePassword({
currentPassword: 'old-password',
newPassword: 'new-password-123',
})
// Update own metadata (only keys explicitly allowed by tenant config)
await hj.user.updateMetadata({ theme: 'dark' })User metadata
metadata is a free-form JSON object for storing arbitrary data alongside a user. Use it for app-specific data like:
{
"metadata": {
"department": "engineering",
"employee_id": "EMP-1234",
"onboarding_completed": true,
"preferred_language": "en"
}
}Public vs. private metadata
| Type | Included in JWT | Editable by user | Use for |
|---|---|---|---|
metadata | If configured in JWT claims | No (admin only) | Internal data, CRM IDs, plan info |
public_metadata | Always | Yes (within allowed keys) | User preferences, display settings |
Configure which public_metadata keys users can self-update:
PATCH /v2/admin/tenants/{tenantId}/auth/config
{
"user_editable_metadata_keys": ["theme", "language", "notifications"]
}hjctl examples
# List users
hjctl users list --tenant acme-corp
# Disable a user
hjctl users disable usr_01HX... --tenant acme-corp
# Reset password
hjctl users reset-password usr_01HX... --tenant acme-corp --send-email