HANDLE.check.omh.st for Prod and dev-HANDLE.check.omh.st for Dev. ohmyhost project status reports both. Before you name a specific address to someone, ask whether it is free:
taken, too_short, too_long, invalid_shape or prohibited_word) and returns up to five free alternatives. Agents reach the same answer through MCP project_handle_check or GET /v1/project-handles/{handle}.
Once a handle is free, read the current project status and copy its project.etag value:
$PROJECT_ETAG is project.etag from the CLI status response (etag in the REST or MCP response). Do not construct it yourself. Read it again before another rename; reuse the request key only when retrying the same rename. The command returns an operation: both gateways are re-published at the new address, and the new handle is stored only once Dev and Prod serve it. Follow it with ohmyhost operation get and wait for success before you quote the new URL. Agents use MCP project_handle_set or PUT /v1/projects/{project_id}/handle.
The old address stops answering within about thirty seconds of a successful rename, and the name returns to the pool for any project to claim — links you already shared with it break, so rename before you publish an address, not after. A rename is refused while another operation is running for the project, for an address that is taken or unusable, and for the address the project already has. Update callback URLs, trusted origins and base-URL secrets that name the old host. A Dev share link or ticket from before rename points there; read the share link again after success. Managed Better Auth needs another deployment/promotion to update its platform base URL. If rename ends operation_abandoned, no address changed: read fresh project.etag and retry with a new key.
A custom hostname requires Paid access, or a Free workspace whose project shows the ohmyho.st flag (below), and serves the project’s Prod deployment. Without Paid or the project flag, the custom hostname answers 402 Project execution paused; a funded platform address can keep serving. Use the real hostname you want to publish:
domain_paid_apply or its CLI command. Save the hostname and idempotency key for the whole setup. If Prod is already active, this apply starts domain provisioning: verify the application on its hosting address first.
awaiting_deployment. It creates no DNS records or certificates and starts no custom-hostname charges; the hostname is not a live application URL yet. You can authorize Cloudflare for this reserved domain before deploying.
Asking for Cloudflare authorization before the project has a matching reserved or provisioned domain returns cloudflare_zone_not_bound. Complete the first domain apply, then request authorization.
Cloudflare-hosted DNS
We prefer Cloudflare because the supported authorization flow can apply the required records:domain_dns_conflict. Repeating an unchanged conflict does not help. Review the records for the requested hostname, resolve the stated conflict while preserving mail records, then repeat the original apply with the same hostname and idempotency key. Do not create another deployment to repair DNS. DNS conflict guidance
This flow connects one custom hostname per project. Connecting example.com leaves www.example.com unchanged. Multiple aliases and automatic apex/www canonical redirects are future work.
Other DNS providers
Reserve the hostname before deployment if needed. After Prod works on its hosting address, repeat the original domain apply to obtainvalidation_records: exact type, name and content from paid apply/status. No TTL is returned; use the DNS provider’s default. Add those records with your DNS provider. Preserve existing mailbox MX and unrelated records. You do not need to move your domain to Cloudflare.
Show the ohmyho.st flag
With the owner’s consent, a project can show a small “Powered by ohmyho.st” flag on the right edge of its production site. It loads nothing and links to ohmyho.st. While it shows, a Free workspace may connect its own domain to that project, the custom hostname costs no credits on any plan, and each Paid period bought through Stripe adds 250 credits once per workspace, however many projects show the flag. Granted/referral Paid days add none (25% more monthly credits for a paid period). Hiding the flag is refused withpowered_by_flag_required while a Free workspace’s domain depends on it.
powered_by_flag_set or Show ohmyho.st flag on the portal project card; powered_by_flag_get reads it. On Free, show the flag before applying the hostname. After uncertainty replay the same key/value; every new switch needs a new key. It appears within about thirty seconds on Prod HTML a browser opens, so check it in a browser. Its https://ohmyho.st/?r=flag-<project> link counts as a referral while the flag shows.
Check readiness
next_check_after_seconds (currently 60 seconds while pending); domain status returns no interval, so ask your agent to check again once DNS changes have had time to propagate. Keep the original deployment and do not rebuild to poll DNS. Email · Project context.
When the final hostname is ready, configure it as the application’s trusted public origin and update its auth callback/logout URLs. Verify login and one protected action there. A host-only session cookie may require a fresh login after changing domains; do not widen cookie domains or trust arbitrary request hosts to mask incorrect configuration.
Move or retire a hostname
To move a domain to another project, run confirmedohmyhost domain paid delete --project "$OLD_PROJECT_ID" --hostname "$HOSTNAME" --idempotency-key "$DOMAIN_DELETE_KEY" --yes --json, wait/read deletion, then plan/apply it on the new project. domain_hostname_taken means another project holds the hostname. An interrupted pending connection can also be deleted. This removes only the named connection and its owned DNS records, preserving unrelated mailbox MX.
Deletion first reads the currently owned DNS records and removes only those records. It never creates missing records or adopts an unowned CNAME that you later recreated, even when that CNAME points to the same target. Unrelated MX, TXT and CAA records remain intact. Replay an uncertain deletion with its original key; if it returns domain_dns_conflict, resolve that specific conflict before retrying.