Assign Domain

Download skillThe skill is a reference md and part of wix-manage skill. You can use the following command to add the full wix-manage skill to your project:
Copy

Changes which site a domain in the account serves, and in which role. A site has one primary domain (the address visitors land on) and up to 300 redirects (domains that send visitors to the primary domain). A domain is on one site at a time, or on none.

DoesDoes not
Connect (assign) a domain to a site, as primary or as a redirect. A domain that isn't in the account yet is handed back (gate 1)Buy a domain, or bring in a domain registered elsewhere that isn't in the account yet: Domain Search, Purchase and Connect
Make a redirect the site's primary domain, or swap the primary for another of the site's domainsReport a domain's expiry, renewal, DNS or SSL state: Analyse Domain
Move a domain from one site to anotherChange DNS records, or explain DNS, nameservers or propagation
Take a domain off its siteCheck whether a name can be registered: Check Domain Availability

Every call runs in the user's own context, as the signed-in user, at account scope. No API key or integration token. The account ID header is added for you.

Flow

  1. Normalize the domain: lowercase, trim, strip http://, https://, www. and any path. No domain named ("connect a domain I own to my site") → the whole reply is: "What domain would you like to connect?" Nothing can be read or changed without the domain, so this is the answer even when you would otherwise go ahead on assumptions. Don't ask for the site or the role (the read settles those later), don't send any link (no My Domains, no domain settings), don't read another skill, and don't say that nothing was changed.
  2. Know the target site, when the request has one (connect, move, change role). Take it from the site context ("this site"), from the conversation, or by name as Query Sites describes. When several sites match, or none was named and the domain is on no site, list the account's sites by name and ask which one. Taking a domain off its site, or connecting it or changing its role with no site named, needs no target up front: pass null. When the read shows the domain on a site, that site is X for taking it off, and T for anything else (so a domain already there gets the Already answer). Ask which site only when the domain is on no site.
  3. Read the state (next section), silently, in one call.
  4. Pick the row in the decision table that fits the state and the request.
  5. Check the gate against that row's writes. Any condition unmet → no write; the gate table says what to answer instead. All met → send the row's offer and end your turn.
  6. Only after an explicit yes to that offer, run the writes, in one call, and report in one sentence.

Run each script below as one call, with whatever lets you run a short script over several Wix API requests at once. Do not split it into separate requests. Never name an endpoint, field, enum value, error code or tool to the user, and never narrate the calls ("let me check", "running the update").

Read the state

One read-only call. Put the domain in domain, the target site's ID in targetSiteId, or null when no site was named (taking the domain off its site, or a role change on the site it is on), and the Account ID from the Wix context you already read in accountId.

Copy

What comes back, verified live:

FieldMeaning
assignmentnull: the domain is on no site. Otherwise siteId (the site it is on) and role, PRIMARY or REDIRECT.
ownedtrue: the domain is in the account. false: the account doesn't hold this exact domain.
sites[id]For the target site and the site the domain is on now: name, premium, editorType, primary (its primary domain, or null when it has no domains), redirects (its other domains). A target site without a Premium plan has its domains left unread (primary: null, redirects: []): gate 3 answers for it before they matter. A site created moments ago may not be in the site list yet; the call waits for it, then reads its plan from the account's Premium purchases, and then name can be null (say your site) and editorType is null (use the non-Studio upgrade URL). Every site ID passed in comes back here: never look a site up again in a separate call.
failed: trueThe read itself failed. Run it once more, silently. If it fails again, and the request takes a domain off its site or the calling skill passed ownership confirmed, send the dashboard link and stop: {domain settings link} when the site is known, otherwise {My Domains link} (URLs: see Offer copy). Otherwise hand back exactly as gate 1 does (read both skills it names and run the availability check once), with ownership unknown instead of "not in the account". A failed read is never answered with an error message of its own, and never tells the user the domain is not in their account.

A domain on no site and a domain that is not in the account both answer "not found" to the assignment lookup; the domain view and the connected domain tell them apart. The domain view answers for a domain in the account and 404 for any other, but it has also answered 404 for a domain connected from elsewhere that was in the account, so a domain-view 404 is followed by the connected-domain lookup, which answers for every domain connected from elsewhere. For a domain another account holds, that lookup answers 403 with DOMAIN_NOT_PERMITTED: that too means "not in this account", not a failed read. The domain view's first attempt can fail on a missing call scope, so it is tried twice. All of this happens inside the one call: never look the domain up again in a separate call, and never search the docs for another way to find it.

The gate

All four must hold before any write. Check them in this order:

#ConditionWhen it fails, answer with
1The user is signed in, and the domain is in the account: owned is true for this exact domain, or the calling skill passed ownership confirmed for it (that counts even when this read does not show it). A root domain in the account does not confirm its subdomain, and the user saying it is theirs confirms nothingTaking a domain off its site: "{domain} isn't in your Wix account, so there's nothing to take off." Stop. Putting a domain on a site: hand back, saying nothing first. A subdomain (shop.example.com) goes to Domain Search, Purchase and Connect §A3.1, with no availability check. Any other domain: read Domain Search, Purchase and Connect and Check Domain Availability, run the availability check once, as that skill describes (never call availability any other way), and follow Domain Search, Purchase and Connect §A4 for the result, with intent CONNECT → a site, the domain, the target site if known, and "not in the account", or ownership unknown when the user is signed out or the read failed twice (its §A4b then skips its own lookup). §A4 then answers with the connect link or the offer to buy. Never say who owns a domain.
2The target site is known (not needed to take a domain off its site)Ask which site, listing the account's sites by name.
3Only when the writes assign a domain to T: T has premium: true. When the calling skill already checked the plan, take its answer. Taking a domain off a site, or promoting one already on it, needs no plan checkThe Free-site answer below. No offer, no question about roles.
4The user said yes to an offer that named every live change: the primary domain it replaces, the site a domain leaves, the redirect promoted in its place, the role it takes on the targetSend the offer from the decision table and end your turn.

Free-site answer — the target site has no Premium plan:

Upgrade {T} with a Premium plan to connect your domain

Connecting a domain is a Premium feature. Upgrade now to let visitors reach you at a custom web address and enjoy Premium benefits.

[Upgrade →](fallback::https://github.com/wix/skills/blob/4aca3249a3c1a53190c3224ccf5c043cf4e1d590/skills/wix-manage/references/domains/%7Bupgrade%20URL%7D*original::{upgrade URL})

{upgrade URL} is https://manage.wix.com/premium-pricing/studio/select-plan?siteGuid={siteId} when the site's editorType is STUDIO, otherwise https://manage.wix.com/premium-pricing/sunrise/select-plan?siteGuid={siteId}. The block is the same fixed copy Domain Search, Purchase and Connect uses: do not reword it, and never promise to put the domain on the site once they upgrade.

Decision table

{domain} is the domain the user named. T is the target site, {T} its name, {T primary} its primary domain. X is the site the domain is on now, {X} its name. {R} is a redirect on the site being changed.

StateRequestOffer (copy below)Writes after a yes, in order
On no site; T has no domainsAny roleA1assign {domain} to T
On no site; T has a primary domainNo role namedA2per the answer: assign; then promote {domain} if they chose primary
On no site; T has a primary domainRedirectA3assign {domain} to T
On no site; T has a primary domainPrimaryP1assign {domain} to T, promote {domain}
On T, in the role asked for, or no role named—Alreadynone
On T as a redirectPrimaryP1promote {domain}
On T as primaryRedirectP2, or Only when T has no redirectspromote the {R} the user picks
A redirect on another site XPut on TM1assign {domain} to T; promote {domain} if the agreed role is primary and T has a primary
Primary of another site X, which has redirectsPut on TM2promote the {R} the user picks on X; assign {domain} to T; promote {domain} if the agreed role is primary and T has a primary
Primary of another site X, its only domainPut on TM3unassign {domain}; assign {domain} to T; promote {domain} if the agreed role is primary and T has a primary
On a site as a redirectTake it offU1unassign {domain}
Primary of a site with redirectsTake it offU2promote the {R} the user picks, unassign {domain}
Primary of a site with no redirectsTake it offU3unassign {domain}
On no siteTake it offOffnone

"Assign" is always as a redirect. On a site with no domains, a redirect becomes the primary domain; on a site that has one, promoting afterwards makes it primary and turns the old primary into a redirect. Assigning straight in as primary would remove every domain the site already has.

When the user asks for a role on a site with no domains, there is nothing to redirect to: the domain becomes its primary domain, and the offer says so.

When a site has several redirects and the row says "the {R} the user picks", list them by name in the offer and let the user choose. With exactly one, name it and ask for a yes.

Offer copy

Two dashboard links are used in this skill, and only in three places: the failed-read row in Read the state, the "no / I'll do it myself" row in Reading the answer, and On failure under Run the writes. Send one only there, never as a fallback of your own. Their URLs are owned by Domains Dashboard Navigation; take them from there:

  • {domain settings link}: the site's domain settings, labelled Domain settings for {site name}.
  • {My Domains link}: the account's domain list, labelled My Domains.

Every offer is one message and ends the turn. Show every domain in full. Say primary domain and redirect; never "main address", "main domain" or "main URL", even when the user does.

A1 — target site has no domains:

{T} doesn't have a primary domain yet. Want me to make {domain} its primary domain?

A2 — target site has a primary domain, no role asked for:

{T}'s primary domain is {T primary}. Should {domain} become the primary domain instead, or redirect to it?

A3 — redirect asked for:

{T}'s primary domain is {T primary}. Want {domain} to redirect to it?

P1 — replaces a live primary domain:

{T}'s primary domain is {T primary} right now. Making {domain} the primary domain will send visitors to {domain} instead, and {T primary} will redirect to it. Go ahead?

P2 — demote the primary domain:

{domain} is {T}'s primary domain. To make it a redirect, another of the site's domains has to become primary. Should {R} become the primary domain? {domain} will then redirect to it.

Only — the site's only domain:

{domain} is {T}'s only domain, so there's nothing for it to redirect to.

M1 — move a redirect:

{domain} currently redirects to {X}. Moving it to {T} takes it off {X}. {T's role, below}

M2 — move a primary domain whose site has redirects:

{domain} is {X}'s primary domain, so it can't move while it's there. I can make {R} {X}'s primary domain first, then move {domain} to {T}. {T's role, below}

M3 — move a site's only domain:

{domain} is {X}'s only domain, so moving it to {T} leaves {X} with no domain. {T's role, below}

T's role — the end of every move offer, picked by what T has and what the user asked:

T and the requestEnds with
T has no domains"It will become {T}'s primary domain. Go ahead?"
Redirect asked for"It will redirect to {T primary}. Go ahead?"
Primary asked for"It will become {T}'s primary domain instead of {T primary}, which will redirect to it. Go ahead?"
No role named"On {T}, should it become the primary domain instead of {T primary}, or redirect to it?"

U1 — take a redirect off:

{domain} redirects to {X}. Take it off {X}?

U2 — take a primary domain off a site that has redirects:

{domain} is {X}'s primary domain. Taking it off directly would also remove {X}'s other domains. I can make {R} the primary domain first, then take {domain} off. Go ahead?

U3 — take the only domain off:

{domain} is {X}'s only domain. Take it off {X}?

Already:

{domain} is already {T}'s primary domain. / {domain} already redirects to {T}.

Off:

{domain} isn't on any site.

Reading the answer

The user saysDo
yes, to an offer that named a single outcomeRun that row's writes.
primary / redirect, to A2 or a move ending in the role questionPrimary → send P1, or the move offer again ending in the "Primary asked for" line, and end the turn. Redirect → run the writes once every other choice is answered.
a redirect's name, to P2, M2 or U2That is {R}. Run the writes once every other choice is answered.
no, "I'll do it myself", or changes the subjectNo write. Send the dashboard link once and stop: "You can also do it yourself: {domain settings link}"
anything ambiguousAsk the same question once more. Never guess a role.

Run the writes only when every choice the offer left open — {R} and the role on T — has an answer. If one is still open, ask only for that one and end the turn.

Silence, a repeated request or "whatever you think" is not a yes.

Run the writes

One call, after the yes. List the row's writes in steps, in order. Each step is retried once; the first step that still fails stops the call, and the result says which steps ran.

Copy
opCallBody
assignPOST https://www.wixapis.com/domains/v1/domain-assignments/upsert/domain/{domain}{"domainAssignment": {"domain": "{domain}", "siteInfo": {"id": "{siteId}", "assignmentType": "REDIRECT"}}}
promotePATCH https://www.wixapis.com/domains/v1/domain-assignments/{domain}{}
unassignDELETE https://www.wixapis.com/domains/v1/domain-assignments/{domain}none

assign and promote answer with the domainAssignment; siteInfo.assignmentType is the role the domain holds now (PRIMARY after assigning to a site with no domains). unassign answers {}. assign to the site a domain is already on changes nothing, whatever role you send: a role change is always promote. promote on a domain that is already primary changes nothing either. assign on a domain that is another site's primary domain fails, which is why M2 and M3 free it first.

Report

One sentence, from what done shows. Nothing about timing, DNS, SSL or propagation, and nothing about what a site that lost a domain shows now.

DoneSay
{domain} holds PRIMARY"Done — {domain} is now the primary domain of {T}." Add ", and {old primary} redirects to it" when one was replaced.
{domain} holds REDIRECT"Done — {domain} now redirects to {T}."
a moveThe same sentence, ending ", and it's off {X}." After M2, also name {R} as {X}'s primary domain.
{R} promoted alone (P2)"Done — {R} is now {T}'s primary domain, and {domain} redirects to it."
{R} promoted, {domain} unassigned (U2)"Done — {R} is now {X}'s primary domain, and {domain} is off the site."
{domain} unassigned"Done — {domain} is off {X}."

On failure, say what did change, then hand over the dashboard, without naming the error:

{What changed, if anything, as above.} Here's where to finish it: {domain settings link}

When primaryElsewhere is true, the domain became another site's primary domain after the read. Read the state again and send M2 or M3. Do not offer the same write a third time unless the user asks.

Never

  • Write anything before the user's yes to an offer that named every change. A yes to "move it" is not a yes to replacing a primary domain the offer did not name.
  • Assign a domain as PRIMARY. Assign as a redirect, then promote.
  • Unassign a site's primary domain while the site has redirects, unless the user asked to remove every domain from that site and the offer named them all.
  • Write a domain that neither the read nor the calling skill found in the account, on the user's word or on its root domain's.
  • Assign a domain to a site without a Premium plan.
  • Guess a role, or which redirect to promote.
  • Say what happens to a site after it loses a domain: no "it goes back to its Wix address", no "your other domain takes over".
  • Promise timing, propagation, SSL, or "up to 48 hours", or explain DNS, nameservers or records.
  • Look up who owns a domain.
  • Say "main address", "main domain" or "main URL" for primary domain.

Next steps

Last updated: 4 November 2026

Did this help?