Skip to main content

Workspace Subdomains

Every Qefro workspace is reachable at:

https://{slug}.qefro.com

Wildcard DNS and wildcard TLS are already configured. This page documents slug validation, the reserved subdomain policy, availability APIs, and error codes.

Short definition (citation-ready)

Workspace subdomains are unique, lowercase slugs (3–32 characters) that map to {slug}.qefro.com. System, security, infrastructure, and brand names are reserved and cannot be registered.

Slug validation rules

RuleDetail
CaseLowercase only (input is trimmed and lowercased)
CharactersLetters a–z, digits 0–9, hyphen -
Length3–32 characters
StartMust start with a letter
HyphensCannot start or end with -; no consecutive --
Rejected., _, .., and any non-ASCII
ReservedMust not match reserved_subdomains
UniqueMust not match an existing workspace slug

Regex (plus consecutive-hyphen rejection):

^[a-z][a-z0-9-]{2,31}$

Reserved subdomain policy

Reserved names protect:

  • Qefro system routes (www, app, api, admin, …)
  • Authentication endpoints (login, oauth, sso, …)
  • Infrastructure hosts (cdn, assets, gateway, …)
  • Monitoring endpoints (metrics, grafana, health, …)
  • Common phishing / brand names (qefro, adminpanel, localhost, …)

Categories stored in the database:

CategoryPurpose
systemPlatform hosts and billing
securityAuth and anti-phishing
infrastructureCDN, storage, mail transport
internalDev / ops / monitoring
brandPublic brand and marketing hosts

Domain model (future-proof)

Each workspace (tenant) stores:

FieldMeaning
slugSubdomain ({slug}.qefro.com) — unique
custom_domain / custom_hostnameOptional custom portal hostname
domain_typesubdomain (default) or custom
created_atCreation timestamp

Custom domains are covered in Custom Domains.

API: check slug availability

POST /api/v1/workspaces/check-slug

Also available as POST /api/workspaces/check-slug.

Request

{
"slug": "acme"
}

Available

{
"available": true,
"reserved": false,
"reason": null,
"slug": "acme"
}

Reserved

{
"available": false,
"reserved": true,
"reason": "Reserved system subdomain",
"slug": "admin",
"code": "SLUG_RESERVED"
}

Legacy GET (signup UI): GET /api/v1/public/tenant-slug-available?slug=acme — same validation, includes available / reserved / reason.

Workspace creation

Before insert, registration and admin create flows:

  1. Normalize (trim + lowercase)
  2. Validate regex / shape
  3. Check reserved_subdomains
  4. Check uniqueness on tenants.slug
  5. Insert with unique index enforcement

Super Admin: manage reserved names

Only Super Admin JWT (role=super_admin):

MethodPathAction
GET/api/v1/admin/reserved-subdomainsList (optional ?search=&category=)
GET/api/v1/admin/reserved-subdomains/search?search=Search
GET/api/v1/admin/reserved-subdomains/:nameGet one
POST/api/v1/admin/reserved-subdomainsAdd
DELETE/api/v1/admin/reserved-subdomains/:nameRemove

Add example

{
"name": "partners",
"category": "brand",
"description": "Partner portal host"
}

Duplicate names return 409 with code RESERVED_SUBDOMAIN_EXISTS.

Error codes

CodeHTTPWhen
SLUG_INVALID400Shape / regex failure
SLUG_RESERVED409Matches reserved table
SLUG_TAKEN409Already used by a workspace
RESERVED_SUBDOMAIN_EXISTS409Admin tried to reserve a duplicate
NOT_FOUND404Admin delete/get missing name

Friendly messages (examples):

  • “Workspace name must be at least 3 characters”
  • “Use only lowercase letters, numbers, and hyphens”
  • “Reserved system subdomain”
  • “This workspace name is already taken”

Workflow

Claim a workspace subdomain

  1. Pick a nameLetters, numbers, hyphens; 3–32 chars.
  2. Call check-slugPOST /api/v1/workspaces/check-slug
  3. RegisterSignup uses the same validation before insert.
  4. Open portalhttps://{slug}.qefro.com

FAQ

Can I change my slug later?
Slug changes are security-sensitive (bookmarks, widgets, DNS). Prefer custom domains for branding changes; contact support for rare slug migrations.
Why is “demo” reserved?
The platform demo tenant uses that slug. Reserving it prevents customer takeovers of platform hosts.
Who can add reserved words?
Only Super Admins via the admin reserved-subdomains API.