Subchapter 19.47
references/domains/analyse-domain.mdMarkdown14 KBView on GitHub
Answers one question: what is the state of a domain in this account? It only reads. It does not buy, connect, assign, renew or change DNS, and it says nothing about domains outside the account.
Every call runs in the user’s own context: as the signed-in user, never as an app, and never with an API
key or an integration token. The account the user is working in is the account for the call. Every domain
in the account, whether registered through Wix or registered elsewhere and connected to Wix, is read from
the account’s two domain lists: assigned (the sites the user’s domains are on) and unassigned (the
domains on no site). The account’s Premium purchases add the expiry and renewal of a domain registered
through Wix. A domain that is in neither list is not in the account, which is an answer, not a failure
(see below).
http://, https://, www. and any
path. Keep the extension the user typed. A subdomain (shop.example.com) is a valid input here.Never name an endpoint, a field or an enum value to the user.
Make this one read-only call, with whatever lets you run a short script over several Wix API requests at
once. Put the domain in domain and the account’s ID in accountId: it is the Account ID in the Wix
context you already read, and the expiry lookup needs it as targetAccountId. Keep the helpers inside the one
function.
It looks at the unassigned list first, then at the assigned list, and when neither holds the domain
the answer is “not found”. Each request is wrapped so that a failure is an answer (“no match”) and never
an error to chase. Do not retry anything yourself, do not try another tool, and do not search the docs.
async function() {
const domain = "example.com";
const accountId = "ACCOUNT_ID";
const lists = "https://manage.wix.com/_api/my-domains/v1/domains";
const renewal = { AUTO_RENEW_ON: true, AUTO_RENEW_OFF: false };
const getList = kind => wix.request({ scope: "account", method: "GET",
url: `${lists}/${kind}?filter.searchTerm=${domain}` }).then(r => r.data).catch(() => ({}));
const fields = d => ({ wixRegistration: d.wixRegistration, managementType: d.managementType,
autoRenew: d.isAutoRenewed });
async function findUnassigned() {
const { domains = [] } = await getList("unassigned");
return domains.find(x => x.domainName === domain);
}
async function findAssigned() {
const { sites = [] } = await getList("assigned");
for (const { site, primary, redirects = [] } of sites) {
if (primary?.domainName === domain) return { where: "primary", siteName: site.siteName, ...fields(primary) };
const r = redirects.find(x => x.domainName === domain);
if (r) return { where: "redirect", siteName: site.siteName, ...fields(r) };
}
return null;
}
async function findPremiumAsset() {
let cursor;
for (let page = 0; page < 5; page++) {
const cursorQuery = cursor ? { cursorPaging: { limit: 100, cursor } }
: { filter: { status: { $in: ["ACTIVE", "NOT_ACTIVE"] } }, cursorPaging: { limit: 100 } };
const { data } = await wix.request({ scope: "account", method: "POST",
url: "https://www.wixapis.com/premium-assets/v2/premium-assets/query",
headers: { targetAccountId: accountId },
body: { cursorQuery, includePermitted: false } });
const hit = (data.premiumAssets || []).find(a => a.domainsData?.domain === domain);
cursor = data.pagingMetadata?.cursors?.next;
if (hit) return hit;
if (!data.pagingMetadata?.hasNext || !cursor) return null;
}
return null;
}
async function withExpiry(match) {
const asset = await findPremiumAsset().catch(() => null);
return asset ? { ...match, expirationDate: asset.domainsData.expirationDate,
autoRenew: match.autoRenew ?? renewal[asset.renewalType] } : match;
}
// With a search term, the unassigned list also returns a domain that redirects on a site.
const listed = await findUnassigned();
let match = listed && !listed.redirectsTo ? { where: "unassigned", ...fields(listed) } : null;
if (!match) match = await findAssigned();
if (!match && listed) {
match = { where: "redirect", siteName: null, redirectsTo: listed.redirectsTo, ...fields(listed) };
}
if (!match) return { where: null };
if (match.wixRegistration === false) {
const { where, siteName, redirectsTo, managementType } = match;
return { where, siteName, redirectsTo, wixRegistration: false, managementType };
}
return withExpiry(match);
}The wrapping is deliberate. The assigned list is not reliably reachable from every session (an
assigned 400 “subject is missing” was seen), so a failed request is read as “not there” and the next
source is tried.
filter.searchTerm matches substrings, so the call keeps only an exact domainName match. With a
search term the unassigned list also returns a domain that redirects on a site (it carries
redirectsTo), so the assigned list is asked for its site; when that list can’t be read, the
result is still a redirect, with siteName null and redirectsTo naming the domain it redirects to.
wixRegistration, managementType and autoRenew come from the list entry. The expiry always comes
from the Premium asset, and only Wix-registered domains have one; for any other domain it is absent. A
later page of Premium purchases carries only the cursor: the query refuses a filter together with a
cursor. The returned object is already trimmed to the exact match: the lists carry far more fields,
including registrant details, and none of them is read or mentioned.
| Result | Say |
|---|---|
where primary | “{domain} is in your account, and it’s the primary domain of {siteName}.” |
where redirect | “{domain} is in your account, and it redirects to {siteName}.” When siteName is null: “…and it redirects to {redirectsTo}.” |
where unassigned | “{domain} is in your account, but it isn’t on a site yet”, plus the rows below. |
wixRegistration false | Start with “{domain} is registered elsewhere and connected to Wix”. Its registrar owns its expiry, renewal and add-ons: never state or guess them, even when the user asks. Never state SSL for it either. |
wixRegistration true | “It’s registered through Wix.” |
expirationDate | The date, written out (“1 March 2027”). |
autoRenew true / false | Auto-renew is on / off. Absent: say nothing about renewal. |
managementType POINTING / DNS | “Its settings stay at its provider” / “Wix manages its settings”. Any other value or none: say nothing about the method. |
where is null, including when a request failed | “I can’t find {domain} in your Wix account.” Do not mention the failed call. A miss is not proof that the user doesn’t own it: these lists see the Wix account, not the registry. Never say someone else owns it, and say nothing about who holds it. If the user then asks whether it can be registered, use Check Domain Availability; to buy it, Domain Search, Purchase and Connect; to connect it from another provider, Connect External Domain or Sub Domain. |
This call is the last source: do not search the docs or call any other API, even when the user asked for an expiry, a renewal or add-ons. Add-ons, SSL, DNS propagation and the contact-verification status are not reported. An expiry or renewal that the result does not carry is never stated or guessed: say Wix can’t report it for this domain. The result carries no price: never state or estimate one.
Make this one read-only call for a question about the account’s domains. It reads both lists in full
(no search term) and the account’s Premium purchases, and returns one row per domain. Put the account’s
ID in accountId, as above, and write the question as the keep filter, so only the matching rows come
back:
row => row.wixRegistration === falserow => row.site === null; on a site: row => row.site !== nullrow => row.site === "Site name"row => row.wixRegistration === true && row.autoRenew === falserow => row.expirationDate && row.expirationDate < "2027-01-01T00:00:00Z"row => trueasync function() {
const accountId = "ACCOUNT_ID";
const keep = row => true;
const lists = "https://manage.wix.com/_api/my-domains/v1/domains";
const renewal = { AUTO_RENEW_ON: true, AUTO_RENEW_OFF: false };
const getList = kind => wix.request({ scope: "account", method: "GET",
url: `${lists}/${kind}` }).then(r => r.data);
// The assigned list can fail in some sessions; the domains on no site still answer.
const [unassigned, assigned] = await Promise.all([getList("unassigned"),
getList("assigned").catch(() => null)]);
const row = (d, site, role) => ({ domain: d.domainName, site, role,
wixRegistration: d.wixRegistration, managementType: d.managementType, autoRenew: d.isAutoRenewed });
const rows = (unassigned.domains || []).filter(d => !d.redirectsTo).map(d => row(d, null, null));
for (const { site, primary, redirects = [] } of assigned?.sites || []) {
if (primary) rows.push(row(primary, site.siteName, "primary"));
for (const r of redirects) rows.push(row(r, site.siteName, "redirect"));
}
const expiry = {};
let expiryRead = true;
try {
let cursor;
for (let page = 0; page < 20; page++) {
const cursorQuery = cursor ? { cursorPaging: { limit: 100, cursor } }
: { filter: { status: { $in: ["ACTIVE", "NOT_ACTIVE"] } }, cursorPaging: { limit: 100 } };
const { data } = await wix.request({ scope: "account", method: "POST",
url: "https://www.wixapis.com/premium-assets/v2/premium-assets/query",
headers: { targetAccountId: accountId },
body: { cursorQuery, includePermitted: false } });
for (const a of data.premiumAssets || []) {
const name = a.domainsData?.domain;
if (!name || expiry[name]?.status === "ACTIVE") continue;
expiry[name] = { status: a.status, expirationDate: a.domainsData.expirationDate,
autoRenew: renewal[a.renewalType] };
}
cursor = data.pagingMetadata?.cursors?.next;
if (!data.pagingMetadata?.hasNext || !cursor) break;
}
} catch (e) {
expiryRead = false;
}
const domains = rows.map(r => {
if (r.wixRegistration !== true) {
return { domain: r.domain, site: r.site, role: r.role, wixRegistration: r.wixRegistration,
managementType: r.managementType };
}
const e = expiry[r.domain] || {};
return { ...r, expirationDate: e.expirationDate, autoRenew: r.autoRenew ?? e.autoRenew };
}).filter(keep);
return { total: rows.length, matched: domains.length, domains,
complete: Boolean(assigned) && assigned.isAllDataReturned !== false, expiryRead };
}Each row has domain, site (the site’s name, or null when it is on no site), role (primary,
redirect or null), wixRegistration and managementType. A Wix-registered row also has
expirationDate and autoRenew when the Premium purchases carry them. Read each row with the table in
Reading the result: a row with wixRegistration false never gets an expiry or a
renewal. The rows have their own shape: site and role stand in for the single lookup’s siteName and
where, and there is no redirectsTo. With complete: false, a redirect domain may be missing, but it
is never listed as on no site.
complete: false: the domains on sites could not all be read. Say the list may be missing some of
the domains that are on a site; a question about domains on no site is still answered in full.expiryRead: false: the expiry and renewal could not be read. Answer a question about them with
“Wix can’t report it right now”; the other columns still stand.Answer a list in one table, one row per domain, with only the columns the question needs. A count is
matched. When more than 25 domains match, give the count, show the first 25, and offer the rest.
No WHOIS, registrant, registrar or owner lookup, no valuation, and nothing about a domain that is not in the account. Anything beyond reading a domain’s state is another skill’s task. Say what you found, then hand over: