Manage Domains

Purpose and Scope

Domains are the public hostnames that make Dub links usable outside the default Dub URL space. Managing domains means deciding which hostname a workspace should use, checking whether a new domain can be registered, adding or registering domains, keeping domain metadata current, and removing or archiving domains when they should no longer appear in active workflows. In the hosted product, this spans dashboard settings and the public Domains API. In the developer tooling, it also includes choosing a default workspace domain for CLI-created links so command-line shortening can use the same branded hostnames as the dashboard.

The repository evidence for this page is centered on two public surfaces. The web app contributes the OpenAPI route index for the Domains API, which defines the REST endpoints exposed to API consumers. The CLI contributes an interactive domains command that fetches available domain slugs, prompts the user to select one, and writes the result into local CLI configuration. Together, those files show that domain management is not a single screen-only feature: it is an API resource family plus a local developer workflow for selecting the domain that future CLI actions should prefer.

Sources: apps/web/lib/openapi/domains/index.ts, packages/cli/src/commands/domains.ts, packages/cli/src/api/domains.ts

Relevant Source Files

  • apps/web/lib/openapi/domains/index.ts - assembles the Domains OpenAPI path object and maps each REST path to its operation module, including list, create, update, delete, register, and status checks.
  • packages/cli/src/commands/domains.ts - implements the public dub domains command, including the interactive prompt, validation, cancellation behavior, and configuration update.
  • packages/cli/src/api/domains.ts - implements the CLI-side domain fetcher, combining workspace domains from the generated dub SDK with default domains from https://api.dub.co/domains/default.

Domain Management Surfaces

The Domains API is the canonical programmable surface for workspace domain administration. Its OpenAPI path map exposes /domains for collection-level actions, /domains/{slug} for actions on a specific domain slug, /domains/register for registration, and /domains/status for availability checks. The route names match the first-party API docs: availability checks are GET requests to /domains/status, and registration is separated from ordinary domain creation. That separation matters operationally because checking or registering a purchasable domain is different from adding a domain a workspace already controls.

For a user, the practical sequence usually starts with discovery. If the goal is to buy or reserve a new branded domain, the availability endpoint answers whether one or more candidate domains are available. The official API documentation calls out that domain registration is limited to certain Enterprise customers and that availability checks currently focus on .link domains. The repository path map supports that product split by keeping checkDomainStatus and registerDomain as explicit operations instead of overloading the general create endpoint. This keeps API clients clear about whether they are managing an existing domain record or initiating a registration workflow.

Once a domain exists for a workspace, collection and item operations cover the rest of the lifecycle. POST /domains creates a domain record, GET /domains lists domains, PATCH /domains/{slug} updates a domain, and DELETE /domains/{slug} removes a domain by slug. The same item path uses slug as the path parameter, which reflects how Dub users typically identify branded domains in link-building workflows: by the hostname slug rather than by an opaque database identifier. In dashboard language, archiving is also a domain-management action: archived domains are hidden from active domain lists and link builders while their links continue to work. The supplied route index only proves the update/delete API surfaces, so exact archive fields should be checked in the detailed operation schema before automating that behavior.

Sources: apps/web/lib/openapi/domains/index.ts

API Operations Reference

The OpenAPI index makes the supported Domains route family compact and predictable. Collection actions are mounted under /domains, item actions are mounted under /domains/{slug}, and specialized lifecycle actions have explicit subpaths. This layout gives client authors a stable mental model: use the collection path when no specific domain is being targeted, use the slug path when changing or deleting one domain, and use the status or registration subpaths when interacting with domain availability and purchasing flows.

Operation familyMethod and pathSource operationWhat it is for
List domainsGET /domainslistDomainsRetrieve workspace domains for display or selection.
Create domainPOST /domainscreateDomainAdd a domain record to a workspace.
Update domainPATCH /domains/{slug}updateDomainModify an existing domain identified by slug.
Delete domainDELETE /domains/{slug}deleteDomainRemove a domain identified by slug.
Register domainPOST /domains/registerregisterDomainStart the domain registration workflow.
Check availabilityGET /domains/statuscheckDomainStatusCheck whether one or more domains are available.

Because the snippet is the route assembly layer rather than each operation implementation, this page should be treated as a lifecycle guide rather than a schema-complete API reference. For implementation work, the next step is to open the individual operation modules imported by apps/web/lib/openapi/domains/index.ts. Those modules define request bodies, query parameters, response shapes, validation, and error details. The route index still provides important source-backed guarantees: the names of the endpoint paths, the HTTP verbs attached to those paths, and the fact that all six operations are part of the generated OpenAPI path object consumed by Dub API documentation and SDK tooling.

Sources: apps/web/lib/openapi/domains/index.ts

CLI Domain Configuration Flow

The CLI exposes domain management as a configuration task rather than as a full create/update/delete domain administration client. The domains command is registered with Commander, named domains, and described as Configure your workspace domain. When invoked, it starts an Ora spinner with Fetching domains, retrieves candidate slugs through getDomains, presents them in a prompts select list, validates the selected value, and then saves the choice into CLI config as { domain: options.domain }. The success path stops the spinner with Done and prints a green Success! Configuration updated. message.

This behavior is useful after authentication and workspace setup because CLI-created links need a domain default. Instead of requiring the user to remember or type the branded hostname every time, the command lets the user choose from workspace domains and known default domains. A typical workflow is to authenticate the CLI, run the domains command, select the desired slug, and then run link-shortening commands with that configured domain available to downstream commands. The command is intentionally interactive: it prompts with Select a domain, validates that the slug is at least three characters, and exits cleanly with a cancellation warning if the user aborts the prompt.

dub domains
# Fetching domains
# ? Select a domain ...
# Success! Configuration updated.

The CLI implementation also shows how the domain list is populated. getDomains reads the local config to obtain access_token, constructs a Dub SDK client with that token, and calls dub.domains.list(). In parallel, it performs a direct GET request to https://api.dub.co/domains/default with the same bearer token. It then awaits both parsed results, maps workspace domain objects to their slug values, appends default-domain slugs, and deduplicates everything with Array.from(new Set(allSlugs)). That means the prompt can include both custom domains owned by the workspace and default domains made available by Dub.

Sources: packages/cli/src/commands/domains.ts, packages/cli/src/api/domains.ts

Implementation Details and Edge Cases

There are two subtle implementation choices to keep in mind when extending domain workflows. First, the CLI does not call the OpenAPI route index directly; it uses the published dub SDK for workspace domains and a raw node-fetch call for the default-domain endpoint. The response from the SDK is destructured as [{ result: domainsResponse }, defaultDomainsResponse], then domainsResponse and the parsed default-domain response are awaited together. That pattern suggests the SDK list method returns a wrapper whose result is itself promise-like or deferred, while the default endpoint is parsed through the CLI utility parseApiResponse.

Second, CLI validation is intentionally minimal. The Zod schema only asserts that the selected slug is a string with a minimum length of three, which is appropriate because choices come from the API rather than free-form user input. This means correctness primarily depends on getDomains returning valid slugs. If a future command adds manual domain entry, it should not reuse this minimal validation as a full hostname validator. Likewise, because the selected value is persisted with setConfig, any downstream command should treat the configured domain as user-controlled local state and be prepared for stale values if a domain is later deleted, archived, or removed from the workspace.

Operationally, availability, creation, registration, update, deletion, archiving, and CLI selection are related but distinct tasks. Availability and registration answer whether a new domain can be acquired. Creation and update manage records already attached to a workspace. Deletion removes a domain record. Archiving, described in the product docs, changes whether a domain appears in active dashboard lists while preserving link behavior; confirm the exact API field in the update schema before scripting it. CLI selection does none of those administrative changes. It only chooses which existing or default domain the local CLI should use by default.

Sources: packages/cli/src/commands/domains.ts, packages/cli/src/api/domains.ts, apps/web/lib/openapi/domains/index.ts

For dashboard users, start in workspace settings when you need to review or clean up active domains. Use the active and archived views to decide whether a domain should remain visible in link-building workflows. If a domain should be hidden but existing links must continue resolving, use the product’s archive flow rather than treating the domain as disposable. If the goal is to add a new registered domain, check availability first and confirm whether the workspace has access to registration features before designing an automated flow around /domains/register.

For API and CLI users, separate administrative automation from local preference configuration. Use the Domains API family for lifecycle actions such as list, create, update, delete, register, and status checks. Then run dub domains on developer machines or CI-like operator environments where the CLI needs a remembered default. When debugging, verify that the access token in CLI config can list workspace domains and fetch default domains, because the prompt depends on both responses. Next, read the detailed Domains API page for schema-level fields, and read the CLI reference for authentication, config storage, and link commands that consume the configured domain.

Sources: apps/web/lib/openapi/domains/index.ts, packages/cli/src/commands/domains.ts, packages/cli/src/api/domains.ts