Multi-tenancy
Managing Tenants
Create, configure, and manage tenants in HelloJohn — REST API, hjctl CLI, and dashboard. Tenant lifecycle, slugs, custom domains, and metadata.
Creating a tenant
POST /v2/admin/tenants
Authorization: Bearer $ADMIN_TOKEN
Content-Type: application/json
{
"name": "Acme Corp",
"slug": "acme-corp",
"owner_email": "admin@acme.com",
"metadata": {
"plan": "pro",
"salesforce_id": "0015000001AbCdE"
}
}Response 201 Created:
{
"id": "ten_01HX...",
"name": "Acme Corp",
"slug": "acme-corp",
"created_at": "2026-01-15T10:00:00Z",
"owner_id": "usr_01HX...",
"metadata": { "plan": "pro", "salesforce_id": "0015000001AbCdE" }
}hjctl tenants create \
--name "Acme Corp" \
--slug "acme-corp" \
--owner-email "admin@acme.com"tenant, err := hjClient.Tenants.Create(ctx, &hellojohn.CreateTenantParams{
Name: "Acme Corp",
Slug: "acme-corp",
OwnerEmail: "admin@acme.com",
Metadata: map[string]any{
"plan": "pro",
},
})const tenant = await hj.tenants.create({
name: 'Acme Corp',
slug: 'acme-corp',
ownerEmail: 'admin@acme.com',
metadata: { plan: 'pro' }
})Listing tenants
GET /v2/admin/tenants?page=1&limit=20&search=acme{
"tenants": [
{
"id": "ten_01HX...",
"name": "Acme Corp",
"slug": "acme-corp",
"user_count": 42,
"created_at": "2026-01-15T10:00:00Z"
}
],
"total": 1,
"page": 1,
"limit": 20
}Getting a tenant
GET /v2/admin/tenants/{tenantId}
# or by slug:
GET /v2/admin/tenants/slug/{slug}Updating a tenant
PATCH /v2/admin/tenants/{tenantId}
Content-Type: application/json
{
"name": "Acme Corporation",
"metadata": { "plan": "enterprise" }
}Deleting a tenant
DELETE /v2/admin/tenants/{tenantId}Deleting a tenant permanently deletes all users, sessions, and data within it. This cannot be undone. HelloJohn requires confirmation via the X-Confirm-Delete: true header.
DELETE /v2/admin/tenants/{tenantId}
X-Confirm-Delete: trueTenant slugs
Slugs are URL-friendly identifiers. They must be:
- Lowercase alphanumeric + hyphens
- 3-63 characters
- Unique across the instance
Slugs are useful for tenant-specific login pages:
https://yourapp.com/login/{slug}Tenant metadata
Use metadata to store arbitrary data alongside a tenant — Stripe customer IDs, Salesforce IDs, plan names, etc.:
{
"metadata": {
"stripe_customer_id": "cus_Nxxx",
"salesforce_account_id": "0015000001AbCdE",
"plan": "enterprise",
"seats": 100
}
}Metadata is returned in all tenant API responses and can be queried:
GET /v2/admin/tenants?metadata.plan=enterpriseTenant stats
GET /v2/admin/tenants/{tenantId}/stats{
"user_count": 42,
"active_sessions": 18,
"mau": 35,
"created_at": "2026-01-15T10:00:00Z",
"last_activity_at": "2026-03-07T14:00:00Z"
}