The user has a finished website as files — hand-written HTML, a static build, a zip, or the output of an AI site builder — and wants it live on Wix as a static, Wix-hosted site.
Five ways to get the files live; what you have decides which are open to you.
| Option | Needs | Carries | The user ends up with |
|---|---|---|---|
A. curl + CLI token → into the account | A shell; a Wix CLI login | Anything on disk | A site in their account, final URL |
B. ExecuteWixAPI → into the account | The Wix MCP | Small text files already in the conversation | A site in their account, final URL |
C. curl → anonymous | A shell | Anything on disk | A live site for one hour; kept by a claim (through the Wix MCP or a CLI token) or the save link |
| D. The drop page | Nothing | Whatever the user uploads | The same, after they upload it themselves |
| E. The headless skill | A shell; Node; a Wix CLI login | A project folder, source included (built for you) | A site in their account as a Wix Headless project, released with the Wix CLI, ready for Wix Business Solutions |
What sets them apart:
curl -F streams files from disk — the bytes never pass through you: any type, any
number, up to the limits.ExecuteWixAPI has no filesystem. The Wix MCP's tool runs JavaScript whose
wix.request calls carry the user's login — no install, no token — but every
byte is written out inside the call. That costs nothing extra for a page you
generated or the user pasted (it's already in the conversation); for files on
disk it means reading them in and writing them back out, and each change
resends all of it. A string body is sent as UTF-8, so binary files (PNG, JPG,
fonts, zips) arrive corrupted; link images by absolute URL.npx @wix/cli login, have them approve, then npx @wix/cli token prints a
token. It also unlocks later changes from disk and
Keep building.So: a small page already in the conversation, with the Wix MCP connected — B,
shell or not. Static files on disk — A with a CLI login, else C (claimed through
the Wix MCP when it's connected). A framework project (a package.json), or a
site that needs stores, bookings, a CMS or members from the start — E. Files out
of your reach, or nothing above fits — D.
Publishing yourself beats the drop page whenever an option fits — the user gets a live site without uploading anything. Never report an upload you couldn't perform; whenever a route fails partway, hand over the drop page.
The Create Headless Site call with no Wix Business
Solutions. Name it after the page's <title>.
One multipart request uploads and releases. Each file is a part named files
whose filename is its path relative to the site root — that is how
subdirectories survive; with curl, set it with ;filename= whenever it isn't
just the basename. A single .zip part works too — it's unpacked server-side, a
single wrapping folder stripped.
Option B — the same two calls as one ExecuteWixAPI script, for small text files
already in the conversation:
siteUrl is the site's final address — it's already in the user's account. Give
the user two links: siteUrl, and its dashboard at
https://manage.wix.com/dashboard/{metaSiteId}.
Re-run step 2 on the same metaSiteId with the full file set: each drop
replaces the site's files (a file left out is gone), and siteUrl stays the same.
Never create another site for a change. The same call updates any site the user
owns that was published this way, including one claimed from an
anonymous publish. For a site from an earlier conversation,
find its metaSiteId with the Query Sites call
below, matching the site's name or viewUrl.
No identity needed: the site is created under a temporary owner and lives for one hour unless the user keeps it.
Generate anonymousId yourself — any UUID, once per site, not once per
request — and reuse it, with the returned metaSiteId, for every call for that
site. Finish within one hour of step 1: after that the record expires and
every later call, claim included, returns 404.
Keep both: metaSiteId addresses the site, projectId builds the save link.
Same multipart shape as the drop, to the upload path, with the attribution parameters:
Keep campaign=mcp (the referral tag — don't change it) and set agent to your
own identifier: a short, stable, lowercase-hyphenated slug for the coding agent or
tool you are (e.g. claude-code, cursor, codex-cli, windsurf,
github-copilot, or your product's name; unknown-agent if you can't name
yourself). Nothing is live yet; this only stages and validates.
To change it, re-run steps 2–3 with the same anonymousId and metaSiteId and
the full file set; siteUrl stays the same. Never go back to step 1 for a change.
Iterate first, claim last: after a claim, changes are a drop,
which needs the user's identity — a CLI token for files on disk.
When it's final: with the user's identity, claim it.
Without it, stop here — a finished result. Give the user siteUrl plus the save
link, which is how the site survives:
That page shows the site with a countdown and signs the user in to keep it. Treat the link as a secret — whoever opens it while signed in to Wix claims the site into their account — so give it only to the user who asked.
Returns {}. Claim after the release, never before — it consumes the anonymous
record, so the anonymous endpoints stop working for this site; later changes go
through the drop.
The URL changes on claim: the step-3 host stops resolving. Read the new one
with Query Sites,
filtered to the HEADLESS namespace (the default query omits headless sites, and
an id filter is rejected, so match the id yourself):
Take viewUrl from the entry whose id is your metaSiteId (page with
metadata.cursors.next if needed), and give the user it plus
https://manage.wix.com/dashboard/{metaSiteId}.
Keep utm_campaign=mcp and set agent to your own identifier, as in the
upload. The user drags in their files (no login), Wix hosts
them on a live URL at once, and a banner offers to sign in and keep the site. Tell
them the requirements so it doesn't
fail on the first try.
These apply to every route:
index.html must be among them.package.json, React/Vue sources) must be built first;
upload the build output, or take the project to the headless skill (option E).Failures come back as HTTP 400 with a code in details.applicationError.code:
MISSING_INDEX_HTML, FILE_TOO_LARGE, TOTAL_TOO_LARGE. A drop onto a site the
caller doesn't own returns PERMISSION_DENIED. On the anonymous route, a 404
after step 1 means the hour passed or the site was claimed — start again.
If publishing fails for any reason you can't quickly fix, hand the user the drop page. Never leave them with a failed publish and no way forward.
The headless skill, https://wix.com/headless/skill.md, builds and releases a
Wix Headless project with the Wix CLI: it adopts a project folder (a
package.json, or an index.html at its root) into a new site, or takes a
dropped one. A dropped site is static; when it needs a real backend — stores,
payments, bookings, a CMS, members, forms — it moves to a headless project,
keeping the same site, appId and URL. This is a choice the user makes when the
need appears; static changes never need it, they're a drop.
To move a dropped site, in a shell, once it's in the user's account:
Then follow the headless skill from that folder: it turns the files into a headless project bound to the same site, released with the Wix CLI from then on.
Don't create the site from a template — that makes an empty site, not a published copy of the user's files.
Last updated: 4 October 2026