# Move sites between zones

> Merge a zone that holds a single subdomain into the zone of its domain without changing what the edge serves, and undo the merge if needed.

OpenWAF works best with **one zone per registrable domain**: `www`, `api` and `shop` are names inside `example.com`,
each with its own settings when needed. If you added a subdomain as a zone of its own (for example `api.example.com`)
and the domain also has its zone (`example.com`), **merge** the subdomain zone into the domain's zone. Its names, records
and certificates move, and the edge keeps serving exactly the same configuration for each name.

You need the `admin` role for the whole organization. Both zones must be in the same organization, active, with the
same DNS mode and the same client (or none).

## What moves

- **Records** move to the parent zone with the same ids, and **certificates** move with them.
- **Settings** of the child zone that differ from the parent's become [per-name settings](https://developers.openwaf.dev/fundamentals/zones-names-and-sites/#per-name-settings)
  of the child's names in the parent.
- **Rules** of the child zone become rules of the parent limited to the child's names. Rules of the parent that applied
  to “every name” are limited to the parent's own names when needed, so they do not start applying to the moved names.
- The parent takes the child's client if it had none.

## Merge

Always simulate first. The answer is the same whether the merge is simulated, applied or refused: an **equivalence
report** that compares, for every name of both zones, the site the edge serves before and after (`equal`, and the
`differences` with the path of each field).

**CLI**

```sh
openwaf-cloud ctl zones merge api.example.com --into example.com --reason "One zone per domain"
```
The CLI simulates, shows the equivalence per name and asks for confirmation. It only applies when every name is
equivalent.
**API**

```sh
curl -X POST "https://dash.openwaf.dev/v1/orgs/$ORG/zones/$CHILD_ZONE/merge" \
  -H "Authorization: Bearer $OPENWAF_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"into": "example.com", "reason": "One zone per domain", "dry_run": true}'
```
Send it again with `"dry_run": false` to apply. Add `"expected_versions": {"example.com": 12, "api.example.com": 7}`
to refuse the merge if either zone changed since you reviewed it.


If any name would not be served the same, or the merge cannot be expressed (different clients, different DNS modes, a
zone that is not active…), nothing is applied: the answer is `409 merge_not_equivalent` with the plan and the
`problems`.

## After the merge

- The parent gets a new version (action `zone.merge`), and the child a final one (`zone.merged`).
- The child zone becomes **disabled**, read-only and hidden from the zone list (the API shows it with
  `?include=merged`). It is kept for 14 days so the merge can be undone, then deleted.
- **Delegated zones**: there is no gap in DNS. The child's names are published in the parent; the child zone keeps
  answering the same until every DNS server serves the parent's new version, and only then disappears.
- **External zones**: nothing changes in DNS. The CNAMEs at your provider keep pointing to the edge.

## Undo a merge

While the parent has not changed since the merge, you can restore both zones as they were before it (records and
certificates go back to the child, which becomes active again):

```sh
openwaf-cloud ctl zones unmerge api.example.com --reason "Undo the merge"
```

In the API: `POST /v1/orgs/{org}/zones/{child}/unmerge` with `{"reason": "…", "expected_version": <parent version after
the merge>}`. If the parent changed after the merge, the answer is `409 merge_not_reversible`: revert those changes
first.

## Move a single site

To move one site (one name with its proxied records) from one zone to another of your organization without merging
whole zones, contact [support@openwaf.dev](mailto:support@openwaf.dev).
