HelloJohn / docs
Users

Create Users

How to create users in HelloJohn — via sign-up, admin API, and bulk import.

Create Users

Users can be created through self-service sign-up or programmatically via the Admin API. This page covers both patterns.


Self-Service Sign-Up

The most common way: the user creates their own account through your sign-up form.

Via SDK

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

function SignUpForm() {
  const { auth } = useHelloJohn();

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

    await auth.signUp({
      email: data.get("email") as string,
      password: data.get("password") as string,
      name: data.get("name") as string,
    });
  };

  return (
    <form onSubmit={handleSignUp}>
      <input name="name" placeholder="Full name" required />
      <input name="email" type="email" placeholder="Email" required />
      <input name="password" type="password" placeholder="Password" required />
      <button type="submit">Create account</button>
    </form>
  );
}

Via API

curl -X POST https://api.hellojohn.dev/v1/auth/sign-up \
  -H "Authorization: Bearer pk_live_abc123" \
  -H "X-Tenant-ID: tnt_01HABCDEF654321" \
  -H "Content-Type: application/json" \
  -d '{
    "email": "alice@example.com",
    "password": "SecurePassword123!",
    "name": "Alice Smith"
  }'

Response: 201 Created

{
  "user": {
    "id": "usr_01HABCDEF123456",
    "email": "alice@example.com",
    "name": "Alice Smith",
    "email_verified": false,
    "created_at": "2024-01-15T10:00:00Z"
  },
  "access_token": "eyJhbGciOiJFZERTQSJ9...",
  "refresh_token": "rt_01HABCDEF..."
}

Admin-Created Users

Create users server-side without them going through sign-up. Useful for:

  • Inviting users directly (no self-registration)
  • Migrating users from another system
  • Creating test accounts
curl -X POST https://api.hellojohn.dev/v1/users \
  -H "Authorization: Bearer sk_live_abc123" \
  -H "X-Tenant-ID: tnt_01HABCDEF654321" \
  -H "Content-Type: application/json" \
  -d '{
    "email": "alice@example.com",
    "name": "Alice Smith",
    "password": "TemporaryPass123!",
    "email_verified": true,
    "send_welcome_email": true,
    "public_metadata": {"plan": "starter"},
    "role": "member"
  }'

Body:

FieldTypeRequiredDescription
emailstringUser email (must be unique)
namestringDisplay name
passwordstringIf omitted, user must reset via magic link
phone_numberstringE.164 format
email_verifiedbooleanSkip email verification (default: false)
send_welcome_emailbooleanSend welcome email (default: true)
rolestringSystem role (default: member)
public_metadataobjectPublic key/value data
private_metadataobjectPrivate key/value data

Response: 201 Created — Returns user object (without password).


Passwordless User Creation

Create a user without a password. They sign in via magic link or SSO:

curl -X POST https://api.hellojohn.dev/v1/users \
  -H "Authorization: Bearer sk_live_abc123" \
  -H "X-Tenant-ID: tnt_01HABCDEF654321" \
  -H "Content-Type: application/json" \
  -d '{
    "email": "alice@example.com",
    "name": "Alice Smith",
    "email_verified": true
  }'

Send a magic link so they can sign in:

curl -X POST https://api.hellojohn.dev/v1/auth/magic-link \
  -H "Authorization: Bearer pk_live_abc123" \
  -H "X-Tenant-ID: tnt_01HABCDEF654321" \
  -H "Content-Type: application/json" \
  -d '{"email": "alice@example.com"}'

Preventing Duplicate Accounts

POST /v1/users returns 409 Conflict if the email is already taken:

{
  "error": "email_already_exists",
  "message": "A user with this email already exists."
}

To handle this gracefully:

try {
  const user = await hj.users.create({ email, name });
} catch (error) {
  if (error.code === "email_already_exists") {
    // Either update the existing user or use them as-is
    const existing = await hj.users.getByEmail(email);
    return existing;
  }
  throw error;
}

Disabling Sign-Up

To prevent users from self-registering (admin-only creation):

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

POST /v1/auth/sign-up will return 403 for all requests.


On this page