# Purge the cache

> Remove cached content by URL, prefix, hostname, Cache-Tag or everything; edge nodes apply it in about a second. Includes CI with a purge-only token.

A purge removes cached objects from every edge node; the next request for them goes to your origin. Edge nodes apply a purge **within about a second**, and you can see how many nodes have applied it.

## Purge types

Each purge has exactly one type and up to **100 values**:

| Type | API field | Values | Removes |
|---|---|---|---|
| Everything | `purge_everything` | `true` | Everything cached for the zone, on every name. |
| URLs | `files` | Full URLs, e.g. `https://www.example.com/app.css?v=2` | Those URLs, every variant (encodings, image formats, origins). The query string counts. |
| Prefixes | `prefixes` | `host/path`, e.g. `www.example.com/blog/` | Everything whose URL starts with it, any query. |
| Hostnames | `hosts` | Names of the zone, e.g. `static.example.com` | Everything cached for those names. |
| Tags | `tags` | `Cache-Tag` values, e.g. `product-42` | Every object with one of those [tags](https://developers.openwaf.dev/cache/cache-tags/). |

Every value must belong to the zone, and the zone must be active. A purge isn't versioned configuration: it can't be reverted, and reverting a zone version never brings purged content back.

## Purge

You need the `tech` or `admin` role, or a [purge-only token](#ci).

**Dashboard**

1. Go to **Caching › Purge cache**.
2. Select **Purge everything**, or **Custom purge** and choose **Purge by** (URLs, Prefixes, Hostnames or Tags), then enter the values, one per line.
3. Select **Review**: the dialog shows the values as the API normalized them, plus any warning.
4. Select **Purge**. **Recent purges** shows its **Propagation** as applied nodes out of the caching nodes.

**CLI**

```sh
openwaf-cloud ctl cache purge example.com --everything --reason "deploy"
openwaf-cloud ctl cache purge example.com --url https://www.example.com/app.css --url https://www.example.com/ --reason "new css"
openwaf-cloud ctl cache purge example.com --prefix www.example.com/blog/ --reason "blog"
openwaf-cloud ctl cache purge example.com --host static.example.com --reason "static files"
openwaf-cloud ctl cache purge example.com --tag product-42 --reason "price change"

openwaf-cloud ctl cache purges example.com    # recent purges, applied on N of M nodes
```

The command simulates first, shows the normalized values and warnings (for example "the cache is disabled"), and asks for confirmation (`--yes` without a terminal, `--dry-run` only simulates).

**API**

```sh
curl -s -X POST https://dash.openwaf.dev/v1/orgs/$ORG/zones/$ZONE/cache/purge \
  -H "Authorization: Bearer $OPENWAF_TOKEN" \
  -H "Content-Type: application/json" \
  -H "X-Change-Reason: new css" \
  -d '{"files": ["https://www.example.com/app.css"]}'
```

The body has the same shape as other CDNs' purge APIs: exactly one of `purge_everything`, `files`, `prefixes`, `hosts` or `tags`. `files` accepts strings or `{"url": "…"}` objects. The answer has `seq` (the purge number), `kind`, the normalized `values`, `created_at` and `warnings`; add `?dry_run=1` to normalize and check without purging. `X-Change-Reason` is optional (default `cache purge`).

List recent purges with their propagation (`nodes` and `applied`):

```sh
curl -s "https://dash.openwaf.dev/v1/orgs/$ORG/zones/$ZONE/cache/purges?limit=10" \
  -H "Authorization: Bearer $OPENWAF_TOKEN"
```

**MCP**

`purge_cache` works in two steps: `confirm=false` (default) returns the normalized purge and warnings, then the same call with `confirm=true` purges.

```json
{"zone": "example.com", "prefixes": ["www.example.com/blog/"], "reason": "blog", "confirm": false}
```


## Limits

Purges are rate limited per organization:

| Purge | Limit |
|---|---|
| Everything, prefixes, hostnames, tags | 10 per minute, bursts of up to 30 |
| URLs | 500 URLs per minute (each URL counts once) |

Over the limit the API answers `429` with `code` `rate_limited` and a `Retry-After` header. A zone that isn't active answers `409` (`zone_not_active`).

## Purge from CI after a deploy

Create a token that can **only** purge one zone's cache, so your pipeline never holds a token that can change configuration:

1. In **API tokens**, create a token with **Cache purge only**. It needs a domain in **Scope** and the role Tech. The dashboard then shows ready-to-paste snippets for `curl`, GitHub Actions and Coolify.
2. Store the token as a secret named `OPENWAF_PURGE_TOKEN` in your CI, never in the repository.
3. Call the purge after the new version is live:

   ```sh
   curl -fsS -X POST "https://dash.openwaf.dev/v1/orgs/$ORG/zones/$ZONE/cache/purge" \
     -H "Authorization: Bearer $OPENWAF_PURGE_TOKEN" \
     -H "Content-Type: application/json" \
     -H "X-Change-Reason: deploy" \
     -d '{"purge_everything": true}'
   ```


A purge-only token can call only `POST …/cache/purge` and `GET …/cache/purges` of its zone; everything else, MCP included, is refused with `403` (`token_scope`). See [API tokens](https://developers.openwaf.dev/fundamentals/api-tokens/).

> **Tip**
>
> For sites with hashed build assets (Next.js and similar), purge only the HTML pages (`prefixes` or `files`) after a deploy. The previous build's assets stay cached for tabs that are still open.


## Audit

Every purge is recorded in the audit log as `zone.cache.purge`, with its type, values, number and reason.
