Skip to content
Siteon
Contents Custom domains and allowed origins

Docs

Custom domains and allowed origins

The DNS records (CNAME and TXT) for serving your site on your own domain (www.example.com), what to do with the bare domain, and what each status and error means. How to register the domains your forms accept (allowed origins) and how to fix 403 origin_not_allowed. Includes steps for AI agents.

Siteon is infrastructure for AI-built websites: it adds hosting, a CMS your client can edit, contact forms, analytics and control from AI agents (CLI and MCP) around static HTML built with AI or by hand, so it is ready to ship.

This page covers two things.

You want toRead
Show a site hosted on Siteon on your own domain (www.example.com)Custom domains
Fix forms that fail with 403 / origin_not_allowed, or register the domain of the site your form lives onAllowed origins for forms

When a custom domain becomes active on Siteon hosting, it is added to the allowed origins automatically. If you only put a form on a site hosted elsewhere (Cloudflare Pages, Vercel and so on), you only need the allowed origins.

Custom domains Soon

Custom domain requests are not open yet Soon. This section describes the steps for when they open. Until then you can publish at https://<name>.siteun.com/.

On your own domain, www.example.com is the main host (primary) and example.com (without www) redirects to www.

Before you start

  • The site must be on a paid plan. Lite allows 1, Standard 3 and Business 10. www.example.com and example.com together count as one. Not available on Free (plan_required)
  • Hosting must be enabled for the site (siteon hosting enable; see Hosting and delivery)
  • In the admin, the site's owner can do this. With an API key (CLI, MCP) you need the domains:write scope. It is not granted by default, so choose it explicitly when you create the key (siteon login --scopes +domains:write)
  • You must be able to edit the domain's DNS. The company you bought the domain from (the registrar) is not always where the DNS is edited: edit it where the nameservers point
  • An account can request up to 5 domains a day (days counted in Japan time)

Steps

  1. In the admin, open "Publishing" in the sidebar, type www.example.com in the "Custom domains" box and press "Add" (CLI: siteon domains add www.example.com --site <site-id>)
  2. Add the two records shown on screen (TXT and CNAME) to your domain's DNS (Records to add)
  3. Wait. Siteon checks the DNS and the certificate automatically every 5 minutes; once both are in place the status becomes "Active" and the site is served on your domain. Reopening "Publishing" in the admin checks again on the spot (CLI: siteon domains status)
  4. Redirect example.com (without www) to www.example.com (The bare domain)

If the records cannot be verified within 72 hours of the request, the request is cancelled (the status becomes "Failed"). Add the domain again in that case.

Records to add

For a request for www.example.com you add these two records. The value changes with every request, so always copy exactly what the screen (or the CLI / API response) shows.

TypeName (host)Value
TXT_sitekit-verify.www.example.comThe value shown on screen, starting with sitekit-verify=
CNAMEwww.example.comcname.siteun.com
  • The TXT record proves ownership. It is required for every request and its value changes with each one. Do not delete it after the domain is active: Siteon keeps checking every 5 minutes, and if the TXT record disappears the domain stops being served at once (and drops out of the allowed origins)
  • The CNAME record points traffic at Siteon. Any record that www.example.com has now (A, AAAA, another CNAME) cannot coexist with the CNAME. Remove it, then add the CNAME. The old site disappears as soon as you switch the CNAME, and https:// may not open for a few minutes until the certificate is issued. Add the TXT record first and switch the CNAME at a quiet time to keep the gap short
  • Most DNS screens append the domain (.example.com) to the name field automatically. Then enter only www and _sitekit-verify.www. Entering www.example.com there would create www.example.com.example.com
  • Leave mail (MX) and any other records that are not www alone
  • For internationalized domain names, request and enter the xn-- form (Punycode)

After adding them, you can check that the DNS serves them:

dig +short CNAME www.example.com                  # OK if it prints cname.siteun.com.
dig +short TXT _sitekit-verify.www.example.com    # OK if it prints the value on screen

Examples by DNS provider

Screen and menu names change from time to time. Whatever the provider, you add two rows in its DNS records screen: "type CNAME, host www, value cname.siteun.com" and "type TXT, host _sitekit-verify.www, value as shown on screen".

  • Cloudflare — In the domain's "DNS" → "Records", use "Add record". CNAME: Name www, Target cname.siteun.com, and set Proxy status to "DNS only" (grey cloud). TXT: Name _sitekit-verify.www, Content the value on screen
  • Onamae.com — In Onamae.com Navi's DNS features ("DNS settings", "DNS record settings"), add host www, TYPE CNAME, VALUE cname.siteun.com, and host _sitekit-verify.www, TYPE TXT, VALUE the value on screen. This screen works when the domain uses Onamae.com's nameservers
  • Muumuu Domain — In "Muumuu DNS" custom settings, add subdomain www, type CNAME, content cname.siteun.com, and subdomain _sitekit-verify.www, type TXT, content the value on screen
  • Xserver Domain — In the domain's "DNS record settings", add host www, type CNAME, content cname.siteun.com, and host _sitekit-verify.www, type TXT, content the value on screen. If the nameservers point at a rental server (such as Xserver), use that server's DNS record settings instead
  • Sakura Domain — In the member menu's "zone edit" for the domain, add entry www, type CNAME, value cname.siteun.com. (some screens need the trailing dot), and entry _sitekit-verify.www, type TXT, value the value on screen
  • Squarespace (formerly Google Domains) — In the domain's "DNS" settings, under custom records, add Host www, Type CNAME, Data cname.siteun.com, and Host _sitekit-verify.www, Type TXT, Data the value on screen

With Cloudflare's proxy turned on (orange cloud), requests to www.example.com pass through your own Cloudflare settings before reaching Siteon, which can stall certificate issuance and the checks. Siteon already serves your domain and its certificate through Cloudflare, so there is no need to turn the proxy on.

The bare domain (example.com)

Ordinary DNS does not allow a CNAME on example.com itself (the apex). Redirect it to www.example.com in one of these two ways.

A. Your DNS can do CNAME flattening (ALIAS, ANAME)

  1. Add www.example.com first (if you add only example.com with no primary host, there is nothing to redirect to and it answers 404)
  2. Add example.com as well. Together with www.example.com it counts as one, so it uses no extra slot. It becomes "Redirects to primary" automatically
  3. Add the TXT record shown (_sitekit-verify.example.com) and a CNAME on the apex (name @ or blank) → cname.siteun.com. Remove any A / AAAA records on the apex (MX and TXT can stay)
  4. Once active, https://example.com/… redirects to https://www.example.com/… (path and query preserved)

Cloudflare flattens apex CNAMEs as standard, so this method works there. For other providers, check their documentation for whether they offer ALIAS / ANAME.

B. Your registrar's URL forwarding

Use your DNS provider's "URL forwarding" (web forwarding, redirect settings and so on) to forward example.com to https://www.example.com. Do not add example.com to Siteon (it uses no slot). Forwarding is the provider's own service, so whether https://example.com opens without a certificate error and whether the path is carried over depends on that provider.

You can also make example.com the main host instead of www (mark it primary when you add it; --primary in the CLI). We recommend www as the main host because it has fewer DNS restrictions.

What the statuses mean

Status (API value)MeaningWhat to do / how long
Received (requested)The request was received and serving is being preparedJust wait. Usually seconds to a few minutes until "Waiting for DNS"
Waiting for DNS (pending_dns)The CNAME or TXT record cannot be verified yetAdd both records. DNS changes take from minutes to a few hours to show up (depends on the provider and the TTL); the next 5-minute check then moves it on
Waiting for the certificate (pending_ssl)DNS is verified and the https:// certificate is being issuedJust wait. Usually minutes to tens of minutes
Active (active)The site is served on this domain, and the domain is in the allowed origins automaticallyKeep the TXT and CNAME records. Each passing 5-minute check extends it by 72 hours
Failed (failed)Not verified within 72 hours of the request, so the request was cancelledAdd it again (the TXT value is new, so replace the old TXT record with the new value)
  • If the TXT or CNAME record disappears after "Active", the status goes back to "Waiting for DNS" at once and the domain stops being served (it also leaves the allowed origins). Put the record back and the next check makes it "Active" again, with no new request
  • If the check cannot run because of a temporary problem on Siteon's or Cloudflare's side, serving does not stop (for up to 72 hours since the last successful check)
  • Times are rough guides. With slow DNS providers it can take around half a day

Removing a domain and changing the main host

  • Remove — "Remove" under "Publishing" → "Custom domains" in the admin (CLI: siteon domains remove www.example.com --yes). The domain stops being served at once and this cannot be undone. To use it again, add it and verify the DNS again (with a new TXT value). The slot frees up once Siteon has finished cleaning up (usually a few minutes). Delete DNS records you no longer need yourself. If you remove the main host, a domain set to redirect (example.com) has nowhere to go and answers 404
  • Change the main host — siteon domains primary <domain> --yes (MCP: domains_primary). Choose an active domain. The other domains redirect to the new main host at once, and the pages' canonical URL changes
  • While a custom domain is the active main host, the shared subdomain (<name>.siteun.com) keeps serving, but it is set to stay out of search (noindex) and names the custom domain as the canonical URL

Errors

The admin shows a plain-language message; the CLI, API and MCP put a code in error.

CodeMeaningFix
plan_required (402)The site's plan has no custom domains (Free)Move the site to a paid plan (Lite or higher)
quota_hostnames (402)The plan's slots are used up (limit and used are returned)Remove a domain you do not use, or upgrade. A just-removed domain still counts for a few minutes until clean-up finishes
invalid_hostname (400)The domain is malformed (reason is bad_format), or it is a siteun.com name (base_domain)Enter it as www.example.com, without https://, a trailing / or a path. Allowed characters are lowercase letters, digits and hyphens (internationalized names in their xn-- form)
hostname_blocked (400)Names that combine a brand name with words like login or verify (shapes common in impersonation) cannot be registeredUse a different domain
hostname_reserved (409)Another account has requested or is using the domain (reserved_until shows the deadline of a pending request)If the domain is yours, request it after the deadline (72 hours from that request). If no deadline is shown (it is active elsewhere), contact Siteon
hostname_in_use (409)It is registered on another site in the same account (site_id)Remove it from that site first
too_many_domain_requests (429)An account can request up to 5 domains a dayTry again the next day (after the date changes in Japan time)
hosting_disabled (409)Hosting is not enabled for the siteRun siteon hosting enable first
billing_inactive (402)Payment could not be confirmedCheck billing in the admin
account_held / transferring (409)Publishing is held for the account / the site is being transferredCheck the hold notice email / try again after the transfer
hostname_not_live (409)The domain you tried to make primary has failed or was removedStart again by adding it
site_changed (409)Another operation got there firstRead the state again and retry
insufficient_scope (403)The API key lacks domains:writeCreate a key with domains:write (siteon login --scopes +domains:write)
confirmation_required (400)Removing a domain or changing the main host with an API key needs confirmationAsk the person first, then pass confirm: true (--yes in the CLI)

Allowed origins for forms

The allowed origins (allowed_origins in the API) are the domains of the pages that may carry this site's forms. Submissions sent from pages on any other domain are refused. This stops other people from putting your form on their own site and using up your submission quota. Page-view counting uses the same list.

  • In the admin: the site's "Settings" → "Domains and site name", under "Domains that may submit forms". One per line, then "Save". The site's owner can change it. It takes effect as soon as you save
  • In the admin you can leave out https:// (localhost is taken as http://). If you type a path, only the domain part is registered
  • Up to 20 entries
  • Only exact matches are accepted. https://www.example.com and https://example.com are different, so add both if you use both. http:// versus https:// and different port numbers are different too. Wildcards like * cannot be used (preview URLs that change every time, such as Cloudflare Pages' <hash>.<project>.pages.dev, must be added one by one, or use a fixed preview URL)
  • Submissions without an Origin header (curl, servers) are accepted regardless of the allowed origins

Origins added automatically

These two are accepted without being in the list (they do not appear in the admin's box):

  • The site's shared subdomain on Siteon hosting (https://<name>.siteun.com)
  • Custom domains that are "Active" (https://www.example.com, and a redirecting https://example.com too). They drop out automatically when they stop being active. auto_origins in siteon domains status shows what is in right now

What Free sites can register

A Free site can only register development and preview domains. Anything else (your own domain) is refused with 402 upgrade_required; move the site to a paid plan first.

localhost
127.0.0.1
*.pages.dev
*.vercel.app
*.netlify.app
*.github.io
*.workers.dev

*.pages.dev here means "names of this shape can be registered". What is accepted is still only the individual domains you put in the list.

Changing them with the API

With an API key (scope sites:write) you replace the site's allowed origins. The list you send becomes the new list, so send the current list (readable with GET, scope sites:read) plus your additions.

curl -X PATCH "https://cdn.siteon.dev/v1/accounts/<account-id>/sites/<site-id>" \
  -H "Authorization: Bearer stk_..." \
  -H "Content-Type: application/json" \
  -d '{"allowed_origins":["https://www.example.com","https://example.com","https://my-shop.pages.dev"]}'
  • Write each one as https://www.example.com. A trailing /, a path or uppercase letters are refused (400), as are more than 20 entries
  • With a personal key (one made by siteon login), you must be an owner or admin of the account
  • Sending a non-development domain for a Free site gives 402 upgrade_required

Fixing 403 origin_not_allowed

If you see either of the following, the domain of the page with the form is not in the allowed origins. The submission is not saved and does not count toward your quota.

  • The form says it could not be sent, and the browser's developer tools console shows a CORS error (no Access-Control-Allow-Origin header, for example). For submissions from the Siteon script, the browser stops at its pre-flight check, so the submission is never sent
  • With your own sending code (fetch, a plain <form> post and so on), the response is 403 with {"ok":false,"error":"origin_not_allowed"}
  1. Open the page with the form and run location.origin in the developer tools console to get the page's exact domain (for example https://www.example.com)
  2. Compare it with "Settings" → "Domains and site name" → "Domains that may submit forms" in the admin. Check www or not, http versus https, and the port
  3. If it is missing, add it and save. It takes effect at once, so reload the page and submit again
  4. If you cannot add it
    • "Production domains are available on a paid plan" (402 upgrade_required) — the site is on Free. Move it to a paid plan, then add the domain
    • "Up to 20 domains" — remove the ones you do not use
  5. For a custom domain on Siteon hosting, you do not need to add it: it is added automatically once "Active". If it is still "Waiting for DNS" or similar, see What the statuses mean and fix the domain instead

When an AI agent uses this page

Steps for when a person asks "set up my custom domain" or "my form returns 403". The MCP tools are in preparation Soon (until then, walk the person through the admin).

When asked to set up a custom domain

  1. Confirm with the person: the domain (as www.example.com), that they own it, which company hosts its DNS (Cloudflare, Squarespace and so on), and that the site is on a paid plan with hosting enabled. Never request a domain the person does not own
  2. Call domains_add (site, hostname: "www.example.com"). If the key lacks domains:write you get insufficient_scope; ask the person to create a new key with siteon login --scopes +domains:write
  3. Show the person dns.txt (name, value) and dns.cname (name, target) from the response exactly as returned. Add the form the name field takes at their provider (_sitekit-verify.www and www; see Records to add and Examples by DNS provider). On Cloudflare, tell them to use "DNS only". Tell them to add the records before expires_at (72 hours later)
  4. If the response contains next_steps, follow next_steps over this page
  5. When the person says the records are in, call domains_status (it checks on the spot). Leave 1 to 5 minutes between repeated calls
  6. Next step by status (What the statuses mean)
    • requested — wait a little and call domains_status again
    • pending_dns — look at last_check_detail. txt of mismatch / nxdomain means the TXT name or value was copied wrong; cf of ok with a cf_status other than active means the CNAME does not point at us. Ask the person for the dig output. If the records are fresh, wait for DNS to update
    • pending_ssl — wait (minutes to tens of minutes)
    • active — done. Ask the person to open https://www.example.com/ to check, and to keep the TXT and CNAME records
    • failed — 72 hours passed. After confirming with the person, call domains_add again and have them replace the TXT record with the new value
  7. Ask about the bare domain (The bare domain). If their DNS can do CNAME flattening (Cloudflare and others), confirm www is already added, then call domains_add with hostname: "example.com". Otherwise, guide them to forward it to https://www.example.com with the registrar's URL forwarding
  8. Look up error codes in Errors. Call domains_remove and domains_primary only after telling the person what will happen and getting an explicit yes, with confirm: true

When told a form returns 403

  1. Check that the symptom is 403 / origin_not_allowed or a CORS error in the console (Fixing it). 429 or 400 has a different cause (Common errors)
  2. Ask the person for the exact domain (location.origin) of the page with the form
  3. Read the site's allowed_origins with list_sites and look for an exact match (www or not, http / https, port)
  4. If it is missing, ask the person to add it under "Settings" → "Domains and site name" in the admin. To add it through the API, confirm with the person first and PATCH the current list plus the new entry (Changing them with the API). A Free site cannot take your own domain (upgrade_required), so explain that a paid plan is needed
  5. For a custom domain on Siteon hosting, do not add it to the allowed origins; check its state with domains_status instead (it is added automatically once active)

This page is also available as Markdown. For AI agents, pass llms.txt (contents) or llms-full.txt (full text).