Domains and DNS
Domain access tiers, shared vs custom domains, verification flow, and readiness gating.
Domains and DNS
This guide explains how Nimriz models domains, how domain access tiers work, and how custom domains become ready for live traffic.
Core model
- Domains are stored as host-only lowercase values.
- Host matching is strict.
example.comandwww.example.comare separate records. - Redirect lookup is domain-bound:
Host -> domain_id -> (domain_id, short_code).
Domain access tiers
Nimriz uses domains.custom_settings.api_access to decide who can call control-plane endpoints for a domain.
private: default; requires control-plane authpublic: can allow unauthenticated low-trust create and slug-check flows
Public access does not mean unrestricted access. Expiration policy, quotas, and validation rules still apply.
Shared versus custom domains
Shared Nimriz Built-in domains
Shared domains are org-owned and can be granted to multiple workspaces through account_domains. In those flows:
- the domain belongs to the organization rather than to one workspace
- a specific workspace can be allowed to create links on it through an explicit grant
- delegated access should resolve from the workspace-domain grant model rather than a workspace-owner shortcut
Custom branded domains
Custom domains belong to the organization and must pass verification and Cloudflare activation checks before they are ready for traffic. After verification, org admins decide which workspaces can use them.
Recommended custom-domain flow
- Create the domain record in Nimriz.
- Publish the TXT and routing records Nimriz expects.
- Call
POST /api/domains/verify. - Review
verified,verification_status,ready_for_traffic, anddomain_status. - If needed, call
POST /api/domains/cloudflare-syncto refresh custom-hostname state. - Only start creating or serving production links when the domain is fully ready.
POST /api/domains/verify
Checks DNS ownership, TXT-based certificate validation, routing alignment, and Cloudflare custom-hostname state.
Request body
{
"domain_id": "11111111-1111-4111-8111-111111111111"
}
Successful response
{
"ok": true,
"domain_id": "11111111-1111-4111-8111-111111111111",
"verified": true,
"verification_status": "verified",
"verification_error": null,
"ready_for_traffic": true,
"domain_status": "active",
"txt": {
"name": "_acme-challenge.links.example.com",
"expected_value": "cf-token",
"matched": true,
"source": "cloudflare_dcv"
},
"cname": {
"target": "cname.nimriz.dev",
"matched": true
}
}
Important notes
- First-party domains do not use customer DNS verification.
- The endpoint uses a JSON body with
domain_id; it is not a path-parameter endpoint. - A
200response can still reportverified: falsewhile the domain remains pending.
POST /api/domains/cloudflare-sync
Refreshes Cloudflare custom-hostname state for a customer domain and reports whether traffic can safely start.
Request body
{
"domain_id": "11111111-1111-4111-8111-111111111111",
"create_if_missing": true
}
Response highlights
ready_for_trafficdomain_statuscloudflare.custom_hostname_idcloudflare.hostname_statuscloudflare.ssl_status
Readiness gating
Custom domains are not considered ready just because a domain record exists. Link creation and redirect serving can remain blocked until:
- DNS ownership validation succeeds
- certificate validation TXT records match
- routing points to the expected target
- Cloudflare custom-hostname and SSL statuses are active
If readiness fails, link creation can return custom_domain_not_ready.
Common failure modes
Wrong host
The most common issue is verifying or routing the wrong hostname. links.example.com and www.example.com are not interchangeable.
DNS record mismatch
The TXT value or routing target is stale, truncated, or published on the wrong label.
Cloudflare activation still pending
DNS can be correct while the hostname or SSL state is still pending.
Automation recommendations
- Treat domain verification as a state machine, not a single yes/no check.
- Persist
domain_idin your system and poll or re-run verification untilready_for_trafficis true. - Keep fallback landing pages off the short-link host itself to avoid loops.