HelloJohn / docs
Architecture

Control Plane

HelloJohn's Control Plane manages tenants, OAuth2 clients, and CP admins. Learn what the Control Plane is, what it controls, and how to interact with it.

The Control Plane (CP) is the operator layer of HelloJohn. It manages the top-level entities that configure how HelloJohn runs: tenants, clients, and the admins who operate them.

What the Control Plane manages

EntityDescription
TenantA single deployment of HelloJohn — one product or one environment
ClientAn OAuth2 client application (web app, mobile app, backend)
CP AdminAn operator who can create/manage tenants
Billing ☁️Subscription plans and usage (Cloud only)

The Control Plane has its own database (the "global DB") separate from any tenant's user data.

CP vs Data Plane

Control PlaneData Plane
ManagesTenants, clients, billingUsers, sessions, MFA, orgs
Auth requiredCP Admin tokenTenant user JWT
DatabaseGlobal DBPer-tenant DB
Who uses itYou (the operator)Your users

CP Admin

A CP Admin is the operator account used to manage HelloJohn itself. CP Admins are not the same as tenant users — they exist in the global database and can manage any tenant.

Creating your first CP Admin:

On OSS, the first CP Admin is created via hjctl or the seed environment variable:

# Create CP Admin via hjctl
hjctl admin create --email admin@yourcompany.com --password "SecurePassword123"

Or via environment variable on first start:

.env
HELLOJOHN_ADMIN_SEED_EMAIL=admin@yourcompany.com
HELLOJOHN_ADMIN_SEED_PASSWORD=SecurePassword123

Remove HELLOJOHN_ADMIN_SEED_* variables after the first start. Leaving them in place allows repeated seed on restart.

On Cloud, your CP Admin account is created during the onboarding flow.

Authenticating as CP Admin

CP Admin endpoints require a CP Admin access token in the Authorization header:

# Sign in as CP Admin
curl -X POST https://your-instance.com/cp/v1/admin/sign-in \
  -H "Content-Type: application/json" \
  -d '{"email": "admin@yourcompany.com", "password": "SecurePassword123"}'

# Response
{
  "access_token": "eyJhbGci...",
  "refresh_token": "rt_01HABCDEF..."
}

Use the returned access_token for all CP Admin API calls:

curl -H "Authorization: Bearer eyJhbGci..." \
  https://your-instance.com/cp/v1/tenants

Managing tenants

A tenant represents one logical deployment — typically one product, one customer, or one environment.

# Create a tenant
curl -X POST https://your-instance.com/cp/v1/tenants \
  -H "Authorization: Bearer {cp_admin_token}" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Acme Corp",
    "slug": "acme",
    "plan": "pro"
  }'

# Response
{
  "id": "tnt_01HABCDEF123456",
  "name": "Acme Corp",
  "slug": "acme",
  "created_at": "2026-01-15T10:00:00Z"
}

Managing clients

A client is an OAuth2 application within a tenant. Each client gets a publishable_key (safe for browser use) and a secret_key (server-side only).

# Create a client
curl -X POST https://your-instance.com/cp/v1/tenants/tnt_01HABCDEF123456/clients \
  -H "Authorization: Bearer {cp_admin_token}" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Acme Web App",
    "type": "web",
    "redirect_uris": ["https://app.acme.com/callback"]
  }'

# Response
{
  "id": "cli_01HABCDEF111222",
  "publishable_key": "pk_live_XXXXXXXXXXXXXXXX",
  "secret_key": "sk_live_XXXXXXXXXXXXXXXX"
}

The secret_key is only returned once at creation. Store it securely. If lost, rotate it from the dashboard or via the API.

Using hjctl for CP management

For local/self-hosted deployments, hjctl provides a CLI interface to the Control Plane:

# List tenants
hjctl tenant list

# Create a tenant
hjctl tenant create --name "Acme Corp" --slug acme

# Create a client
hjctl client create --tenant acme --name "Web App"

# List CP Admins
hjctl admin list

See CLI Reference → for the full command list.

Cloud: Control Plane dashboard ☁️

On HelloJohn Cloud, the Control Plane is exposed through the web dashboard at hellojohn.dev/dashboard. You can manage tenants, clients, billing, and admins without using the API or CLI.

Next steps

On this page