# Cache

> Purge what the edge cached for a zone, everything or by URL, prefix, host or cache tag, and follow recent purges.

Purge the edge cache of a zone and follow how far each purge has propagated. A purge reaches the edge nodes in about a second; it is recorded in the audit log, not as a configuration version.

| Operation | Endpoint |
|---|---|
| [Purge cache](https://developers.openwaf.dev/api/cache/#purge-cache) | `POST /v1/orgs/{org}/zones/{zone}/cache/purge` |
| [List purges](https://developers.openwaf.dev/api/cache/#list-cache-purges) | `GET /v1/orgs/{org}/zones/{zone}/cache/purges` |

## Purge cache

```http
POST /v1/orgs/{org}/zones/{zone}/cache/purge
```

Purges what the edge cached for the zone. The body has exactly one of `purge_everything` (`true`), `files` (URLs, or `{"url": …}` objects; every variant of each URL is purged), `prefixes` (`host/path`), `hosts` or `tags` (`Cache-Tag` values), with at most 100 values. Values are normalized (lowercase scheme and host, default port and fragment removed, canonical path) and their names must belong to the zone.

The edge nodes apply the purge within about a second. A purge is not a configuration version: it is recorded in the audit log with its reason. Per organization, 10 purges per minute with bursts of 30 for everything, hosts, prefixes and tags, and 500 URLs per minute. With `dry_run=1` the request is only validated and normalized and does not count towards the limit.

**Required role:** `tech` or higher. Cache-purge-only tokens of the zone can call it too.

**Change controls:** [`dry_run`](https://developers.openwaf.dev/api/#configuration-changes) · [`X-Change-Reason`](https://developers.openwaf.dev/api/#configuration-changes) (optional)

#### Parameters

| Name | In | Type | Required | Description |
|---|---|---|---|---|
| `org` | path | string (uuid) | Yes | Organization id. Every route checks that it is the token's organization (otherwise `404`). |
| `zone` | path | string (uuid) | Yes | Zone id (see [List zones](https://developers.openwaf.dev/api/zones/#list-zones)). |
| `X-Change-Reason` | header | string | No | Reason of the change (1-500 UTF-8 characters, no control characters); defaults to the creation of the zone. 1 to 500 characters. |
| `dry_run` | query | string | No | `1`/`true` simulates the change: answers 200 with the plan (`Applied`) and saves nothing. `0`/`false` accepted; any other value: 400. One of `1`, `true`, `0`, `false`. |

#### Request body

Content type `application/json`. Schema: [PurgeRequest](https://developers.openwaf.dev/api/schemas/#purge-request).

Exactly one of the fields

| Field | Type | Required | Description |
|---|---|---|---|
| `purge_everything` | boolean | No |  |
| `files` | array of string or object | No | http(s) URLs of the zone; every variant is purged. At most 100 items. |
| `files[].url` | string | Yes |  |
| `prefixes` | array of string | No | host/path (without query string or fragment). At most 100 items. |
| `hosts` | array of string | No | At most 100 items. |
| `tags` | array of string | No | Cache-Tag values (stored lowercase). At most 100 items. |

#### Response

- `200`: Purge accepted (or simulated). Returns [PurgeResult](https://developers.openwaf.dev/api/schemas/#purge-result).

| Field | Type | Description |
|---|---|---|
| `dry_run` | boolean | `true` in a simulation. |
| `seq` | integer | Position of the purge (0 in a simulation). |
| `kind` | string | One of `everything`, `host`, `url`, `prefix`, `tag`. |
| `values` | array of string | Normalized values. |
| `epoch` | integer | New cache epoch (everything and hosts). |
| `created_at` | string (date-time) | Creation time. |
| `warnings` | array of string | Warnings (the change is still valid). |

#### Errors

| Status | Description |
|---|---|
| `400` | Malformed request (`bad_request`). |
| `403` | The token's role or limits do not allow it (`forbidden`). |
| `404` | Not found, or not visible to the token (`not_found`). |
| `409` | `zone_merged`: the zone is merged into another one (read-only until it is unmerged or purged). |
| `422` | Validation error (`invalid`) or missing or invalid reason (`reason_required`). |
| `429` | `rate_limited`: too many purges; `Retry-After` in seconds. |

#### Example

**curl**


```sh
curl -X POST "https://dash.openwaf.dev/v1/orgs/$OPENWAF_ORG/zones/6f1d2c3b-8a4e-4b7d-9c21-5e3f7a8b9c0d/cache/purge" \
  -H "Authorization: Bearer $OPENWAF_TOKEN" \
  -H "X-Change-Reason: Deploy of the new home page" \
  -H "Content-Type: application/json" \
  --data '{
    "files": [
      "https://www.example.com/index.html"
    ]
  }'
```

**TypeScript**


```ts
import { OpenWAF } from "./openwaf";

const owf = new OpenWAF({ baseUrl: "https://dash.openwaf.dev" }); // token from OPENWAF_TOKEN
const result = await owf.purgeCache({
  zone: "6f1d2c3b-8a4e-4b7d-9c21-5e3f7a8b9c0d",
  body: {
    files: [
      "https://www.example.com/index.html"
    ]
  }
}, {
  reason: "Deploy of the new home page"
});
```

**Python**


```py
from openwaf import OpenWAF

owf = OpenWAF(base_url="https://dash.openwaf.dev")  # token from OPENWAF_TOKEN
result = owf.purge_cache(
    zone="6f1d2c3b-8a4e-4b7d-9c21-5e3f7a8b9c0d",
    body={
        "files": [
            "https://www.example.com/index.html"
        ]
    },
    reason="Deploy of the new home page",
)
```



```json
{
  "dry_run": false,
  "seq": 0,
  "kind": "everything",
  "values": [
    "https://www.example.com/index.html"
  ],
  "epoch": 0,
  "created_at": "2026-10-27T09:30:00Z",
  "warnings": []
}
```

## List purges

```http
GET /v1/orgs/{org}/zones/{zone}/cache/purges
```

Lists the purges of the last 7 days, newest first, with how many of the active caching edge nodes serving the zone (`nodes`) have already applied each one (`applied`).

**Required role:** `readonly` or higher.

#### Parameters

| Name | In | Type | Required | Description |
|---|---|---|---|---|
| `org` | path | string (uuid) | Yes | Organization id. Every route checks that it is the token's organization (otherwise `404`). |
| `zone` | path | string (uuid) | Yes | Zone id (see [List zones](https://developers.openwaf.dev/api/zones/#list-zones)). |
| `limit` | query | integer | No | Maximum number of items. Default `20`. From 1 to 100. |

#### Response

- `200`: Returns `items`, an array of [PurgeStatus](https://developers.openwaf.dev/api/schemas/#purge-status).

| Field | Type | Description |
|---|---|---|
| `items[].seq` | integer |  |
| `items[].zone_id` | string (uuid) | Zone id. |
| `items[].kind` | string | One of `everything`, `host`, `url`, `prefix`, `tag`. |
| `items[].values` | array of string |  |
| `items[].actor` | string | Who made the change: a token, a user or OpenWAF. |
| `items[].created_at` | string (date-time) | Creation time. |
| `items[].nodes` | integer | Active caching edge nodes serving the zone. |
| `items[].applied` | integer | How many of them have already received it. |

#### Errors

| Status | Description |
|---|---|
| `404` | Not found, or not visible to the token (`not_found`). |

#### Example

**curl**


```sh
curl "https://dash.openwaf.dev/v1/orgs/$OPENWAF_ORG/zones/6f1d2c3b-8a4e-4b7d-9c21-5e3f7a8b9c0d/cache/purges" \
  -H "Authorization: Bearer $OPENWAF_TOKEN"
```

**TypeScript**


```ts
import { OpenWAF } from "./openwaf";

const owf = new OpenWAF({ baseUrl: "https://dash.openwaf.dev" }); // token from OPENWAF_TOKEN
const result = await owf.listCachePurges({
  zone: "6f1d2c3b-8a4e-4b7d-9c21-5e3f7a8b9c0d"
});
```

**Python**


```py
from openwaf import OpenWAF

owf = OpenWAF(base_url="https://dash.openwaf.dev")  # token from OPENWAF_TOKEN
result = owf.list_cache_purges(zone="6f1d2c3b-8a4e-4b7d-9c21-5e3f7a8b9c0d")
```



```json
{
  "items": [
    {
      "seq": 0,
      "zone_id": "6f1d2c3b-8a4e-4b7d-9c21-5e3f7a8b9c0d",
      "kind": "everything",
      "values": [
        "https://www.example.com/index.html"
      ],
      "actor": "token:11111111-2222-4333-8444-555555555555",
      "created_at": "2026-10-27T09:30:00Z",
      "nodes": 0,
      "applied": 0
    }
  ]
}
```
