Domains
Serve a project on your own hostname, with TLS issued automatically. Attach several, claim a whole domain for your team, or buy one through the API.
Attach a hostname
# Attach (a project can carry several) curl -X POST $API/{slug}/domains \ -H "X-API-Key: $KEY" \ -d '{"domain": "app.example.com"}' # List, with live DNS verification curl $API/{slug}/domains -H "X-API-Key: $KEY" # Verify one hostname curl -X POST $API/{slug}/domains/app.example.com/verify -H "X-API-Key: $KEY" # Make it the project's primary address curl -X PATCH $API/{slug}/domains/app.example.com \ -H "X-API-Key: $KEY" \ -d '{"is_primary": true}' # Remove one hostname curl -X DELETE $API/{slug}/domains/app.example.com -H "X-API-Key: $KEY"
DNS setup, pick one:
- CNAME —
app.example.com → edge.mosaic.site - A record —
example.com → 199.127.108.254(the only option at the bare domain)
edge.mosaic.site, not at the project's own {slug}.mosaic.site name, which sits behind a proxy and won't serve your domain.Let's Encrypt certificates are issued automatically, and domains survive redeploys.
How hostnames work
- Routing matches the exact hostname:
www.example.comdoesn't serveexample.com. Attach both, or add an apex redirect (below). - The project's
{slug}.mosaic.siteaddress stays primary until you promote a verified domain. Then the project's URL and deploy responses use it. - Sign-in redirects and browser (CORS) calls work from every verified hostname, primary or not.
- For many subdomains of one domain, add a wildcard record once (
*.example.comA199.127.108.254), then attach each name to its project. - Domain endpoints answer only to the key of the account that owns the project.
- Pro allows 20 hostnames per project, Teams has no limit (pricing).
Apex redirect
curl -X POST $API/{slug}/domains \ -H "X-API-Key: $KEY" \ -d '{"domain": "example.com", "redirect_to": "www.example.com"}'
Sends a 301 from example.com to a hostname already on the project. The bare domain needs an A record to 199.127.108.254 first. A redirect doesn't count toward the limit and can't be primary.
Move a hostname from another project
Attaching a hostname another project holds returns 409 HOSTNAME_TAKEN. If you control its DNS, detail.takeover in the response gives you a TXT record. Add it, then claim:
# 1. At your DNS host: _mosaic-verify.www.example.com TXT mosaic-verify=... # 2. Claim curl -X POST $API/{slug}/domains/www.example.com/claim -H "X-API-Key: $KEY"
The hostname moves to your project, verified but not primary, and the previous owner is emailed. 409 TXT_NOT_FOUND means the record isn't visible yet; DNS can take a few minutes.
Team domains
Claim a whole domain so only you and the accounts you allowlist can attach its subdomains. Team domains come with Teams (pricing).
# Claim: returns a TXT record to add at your DNS host curl -X POST https://api.mosaic.site/v1/base-domains \ -H "X-API-Key: $KEY" \ -d '{"domain": "example.com"}' # Verify once the record is in place curl -X POST https://api.mosaic.site/v1/base-domains/{id}/verify -H "X-API-Key: $KEY" # Allowlist a teammate (an existing Mosaic account) curl -X POST https://api.mosaic.site/v1/base-domains/{id}/members \ -H "X-API-Key: $KEY" \ -d '{"email": "teammate@company.com"}' # Land new projects on it by default curl -X PUT https://api.mosaic.site/v1/base-domains/default \ -H "X-API-Key: $KEY" \ -d '{"domain": "example.com"}'
- Members attach
label.example.comto their own projects with the attach call above. With a wildcard record in place, the name goes live with no DNS work. - With a default set, a new project called Wayfinder starts at
wayfinder.example.com. Passbase_domainwhen creating a project to choose another, or"mosaic.site"to opt out. - Everyone else gets
403. Subdomains attached by others before your claim keep working and are listed aswarnings[]when you verify.
Buy a domain
Search, quote, buy and attach a domain through the API. You are the registrant, WHOIS privacy is included where the registry allows it, and Mosaic runs the DNS, so a bought domain works with no setup. One-year terms, renewed yearly on your saved card. Prices are in US cents. On Pro and Teams.
# 1. Registrant details, once per account curl -X PUT https://api.mosaic.site/v1/account/registrant \ -H "X-API-Key: $KEY" \ -d '{"first_name": "Alex", "last_name": "Rivera", "email": "alex@example.com", "phone": "+15195550100", "address1": "1 Main St", "city": "Waterloo", "state": "ON", "postal_code": "N2L 3G1", "country": "CA"}' # 2. Search curl "https://api.mosaic.site/v1/domains/search?q=tinymachines" -H "X-API-Key: $KEY" # 3. Quote: locks the price for 15 minutes and charges nothing curl -X POST https://api.mosaic.site/v1/domains/quote \ -H "X-API-Key: $KEY" \ -d '{"domain": "tinymachines.dev", "years": 1, "project_id": "{slug}"}' # 4. Purchase: charges the saved card curl -X POST https://api.mosaic.site/v1/domains/orders/{order_id}/purchase -H "X-API-Key: $KEY" # 5. Poll until status is complete, usually under a minute curl https://api.mosaic.site/v1/domains/orders/{order_id} -H "X-API-Key: $KEY"
you_are_buying and every entry in warnings[] before you purchase: some country domains, such as .ca and .uk, have no WHOIS privacy. Without a saved card, purchase returns 402 with an add_card_url.Up to 5 purchases a day. A failed registration is refunded automatically. For transfers in or out, open a support ticket.
Endpoints
| Endpoint | Method | Description |
|---|---|---|
| /{slug}/domains | GET POST | List hostnames, or attach one (domain, redirect_to?) |
| /{slug}/domains/{domain} | PATCH DEL | Make primary, or remove |
| /{slug}/domains/{domain}/verify | POST | Check DNS points at Mosaic |
| /{slug}/domains/{domain}/claim | POST | Take a hostname over after adding the TXT record |
| /v1/base-domains | GET POST | List or claim team domains |
| /v1/base-domains/{id}/verify | POST | Verify a claim |
| /v1/base-domains/{id}/members | POST | Allowlist a teammate |
| /v1/base-domains/{id}/members/{email} | DEL | Remove a teammate |
| /v1/base-domains/default | PUT | Default team domain for new projects |
| /v1/account/registrant | GET PUT | Registrant contact details |
| /v1/domains/search?q= | GET | Availability and list price |
| /v1/domains/pricing | GET | Register and renew price per TLD |
| /v1/domains/quote | POST | {domain, years, project_id?} → order and exact charge |
| /v1/domains/orders/{id}/purchase | POST | Charge and register |
| /v1/domains/orders/{id} | GET | Order progress, through to complete |
| /v1/domains | GET | Your domains, expiry, auto-renew |
| /v1/domains/{domain} | PATCH | {auto_renew?, project_id?} |
| /v1/domains/{domain}/dns | GET | DNS records Mosaic manages |