Configuration versions

Browse the version history of a zone, compare two versions, revert to an earlier one and follow its propagation to the edge.

On this page

Every change to a zone's configuration (records, edge settings, rules) creates a new numbered version with its author and reason. Versions can be compared and restored, and the propagation endpoint shows which version each edge node has applied. See Configuration changes.

OperationEndpoint
List versionsGET /v1/orgs/{org}/zones/{zone}/versions
Get versionGET /v1/orgs/{org}/zones/{zone}/versions/{version}
Compare versionsGET /v1/orgs/{org}/zones/{zone}/diff
Revert to a versionPOST /v1/orgs/{org}/zones/{zone}/revert
Get propagationGET /v1/orgs/{org}/zones/{zone}/propagation

List versions

GET /v1/orgs/{org}/zones/{zone}/versions

Lists the configuration versions of a zone, newest first, without their snapshots. It also works for a deleted zone, whose last version is zone.delete; the ETag is then its final version.

Required role: readonly or higher.

Parameters

NameInTypeRequiredDescription
orgpathstring (uuid)YesOrganization id. Every route checks that it is the token's organization (otherwise 404).
zonepathstring (uuid)YesZone id (see List zones).
limitqueryintegerNoMaximum number of items. Default 50. From 1 to 500.
beforequeryintegerNoOnly versions before this one (pagination). Minimum 0.

Response

FieldTypeDescription
items[].versionintegerVersion number.
items[].created_atstring (date-time)Creation time.
items[].actorstringWho made the change: a token, a user or OpenWAF.
items[].actionstring
items[].reasonstringReason of the change.
items[].restored_frominteger or nullVersion restored by a revert (null otherwise).
items[].channelstringChannel of the change when it is neither the API nor the CLI (mcp); absent otherwise.
items[].snapshot_sha256stringSHA-256 of the canonical form of the snapshot.
items[].snapshotZoneSnapshot

Response headers: ETag.

Errors

StatusDescription
400Malformed request (bad_request).
404Not found, or not visible to the token (not_found).

Example

curl "https://dash.openwaf.dev/v1/orgs/$OPENWAF_ORG/zones/6f1d2c3b-8a4e-4b7d-9c21-5e3f7a8b9c0d/versions?limit=20" \
  -H "Authorization: Bearer $OPENWAF_TOKEN"
200
{
  "items": [
    {
      "version": 12,
      "created_at": "2026-10-27T09:30:00Z",
      "actor": "token:11111111-2222-4333-8444-555555555555",
      "action": "block",
      "reason": "Point www at the new origin",
      "restored_from": 0,
      "channel": "mcp",
      "snapshot_sha256": "example",
      "snapshot": {
        "schema": "openwaf-cloud/zone-config/v1",
        "zone": {},
        "settings": {},
        "rules": [],
        "records": [],
        "certificates": []
      }
    }
  ]
}

Get version

GET /v1/orgs/{org}/zones/{zone}/versions/{version}

Returns one version of the zone with its full configuration snapshot (snapshot).

Required role: readonly or higher.

Parameters

NameInTypeRequiredDescription
orgpathstring (uuid)YesOrganization id. Every route checks that it is the token's organization (otherwise 404).
zonepathstring (uuid)YesZone id (see List zones).
versionpathintegerYesVersion number. Minimum 1.

Response

FieldTypeDescription
versionintegerVersion number.
created_atstring (date-time)Creation time.
actorstringWho made the change: a token, a user or OpenWAF.
actionstring
reasonstringReason of the change.
restored_frominteger or nullVersion restored by a revert (null otherwise).
channelstringChannel of the change when it is neither the API nor the CLI (mcp); absent otherwise.
snapshot_sha256stringSHA-256 of the canonical form of the snapshot.
snapshotZoneSnapshot

Errors

StatusDescription
404Not found, or not visible to the token (not_found).

Example

curl "https://dash.openwaf.dev/v1/orgs/$OPENWAF_ORG/zones/6f1d2c3b-8a4e-4b7d-9c21-5e3f7a8b9c0d/versions/11" \
  -H "Authorization: Bearer $OPENWAF_TOKEN"
200
{
  "version": 12,
  "created_at": "2026-10-27T09:30:00Z",
  "actor": "token:11111111-2222-4333-8444-555555555555",
  "action": "block",
  "reason": "Point www at the new origin",
  "restored_from": 0,
  "channel": "mcp",
  "snapshot_sha256": "example",
  "snapshot": {
    "schema": "openwaf-cloud/zone-config/v1",
    "zone": {
      "id": "a5614527-0ce6-43be-ad1d-d012b7394867",
      "name": "example.com",
      "dns_mode": "delegated"
    },
    "settings": {
      "zone_id": "6f1d2c3b-8a4e-4b7d-9c21-5e3f7a8b9c0d",
      "mode": "active",
      "waf_level": "medium",
      "rate_limit_rpm": 0,
      "timeout_ms": 0,
      "enable_feed": true,
      "stack": "generic",
      "block_page_mode": "branded",
      "fake_server_header": "",
      "block_page_html": "",
      "access_gate": {
        "enabled": false,
        "path": "/checkout",
        "ttl_hours": 0,
        "emails": []
      },
      "max_body_mb": 0,
      "redirect_allow_hosts": [
        "www.example.com"
      ],
      "cors_allow_origins": [
        "https://app.example.com"
      ],
      "hsts": {
        "max_age": 0,
        "include_subdomains": false,
        "preload": false
      },
      "compression": false,
      "origin": {
        "scheme": "https",
        "port": 0,
        "tls_verify": "full",
        "server_name": "",
        "client_cert": false
      },
      "hosts": {},
      "redirects": [
        {}
      ],
      "cache": {
        "enabled": false,
        "dev_mode_until": "2026-10-27T09:30:00Z",
        "query": {},
        "browser_ttl": 0,
        "deception_armor": true,
        "serve_stale": {},
        "max_object_mb": 100,
        "rules": []
      },
      "early_hints": {
        "enabled": false,
        "mode": "both",
        "extra_origins": []
      },
      "ai_agents": {
        "enabled": false,
        "mode": "log",
        "spoofed_challenge": "log",
        "template": "search_ok_block_training",
        "policy": {},
        "bot_overrides": [],
        "trap": {},
        "tarpit": {},
        "robots": {},
        "markdown": {},
        "block_response": {},
        "endpoints": []
      },
      "rum": {
        "enabled": false,
        "sample_rate": 1,
        "exclude_paths": []
      },
      "rate_rules": [
        {}
      ],
      "updated_at": "2026-10-27T09:30:00Z"
    },
    "rules": [
      {
        "id": 3,
        "zone_id": "6f1d2c3b-8a4e-4b7d-9c21-5e3f7a8b9c0d",
        "kind": "ip",
        "ip": "203.0.113.0/24",
        "action": "block",
        "note": "Abusive scanner",
        "hosts": [],
        "created_at": "2026-10-27T09:30:00Z"
      }
    ],
    "records": [
      {
        "id": "a5614527-0ce6-43be-ad1d-d012b7394867",
        "seq": 0,
        "name": "example.com",
        "type": "A",
        "content": "203.0.113.10",
        "ttl": 0,
        "proxied": false,
        "priority": 0
      }
    ],
    "certificates": [
      {
        "id": "a5614527-0ce6-43be-ad1d-d012b7394867",
        "hostname": "www.example.com",
        "source": "example",
        "fingerprint_sha256": "example",
        "not_after": "2026-10-27T09:30:00Z"
      }
    ]
  }
}

Compare versions

GET /v1/orgs/{org}/zones/{zone}/diff

Returns what changed between two versions of the zone. By default, the current version against the one before it.

Required role: readonly or higher.

Parameters

NameInTypeRequiredDescription
orgpathstring (uuid)YesOrganization id. Every route checks that it is the token's organization (otherwise 404).
zonepathstring (uuid)YesZone id (see List zones).
fromqueryintegerNoSource version (to - 1 by default). Minimum 0.
toqueryintegerNoTarget version (the current one by default). Minimum 0.

Response

FieldTypeDescription
frominteger
tointeger
changesarray of DiffChange

Errors

StatusDescription
400Malformed request (bad_request).
404Not found, or not visible to the token (not_found).

Example

curl "https://dash.openwaf.dev/v1/orgs/$OPENWAF_ORG/zones/6f1d2c3b-8a4e-4b7d-9c21-5e3f7a8b9c0d/diff?from=10&to=12" \
  -H "Authorization: Bearer $OPENWAF_TOKEN"
200
{
  "from": 0,
  "to": 0,
  "changes": [
    {
      "path": "rules[id=12]",
      "op": "add",
      "from": "example",
      "to": "example"
    }
  ]
}

Revert to a version

POST /v1/orgs/{org}/zones/{zone}/revert

Restores the configuration (records, edge settings and rules) of to_version as a new version; changes made after it are undone. If-Match is required. If some site of the restored version would be left without a valid certificate, the answer is 409 missing_certs with the hostnames, unless allow_missing_certs is true.

Required role: tech or higher.

Change controls: dry_run · If-Match (required) · X-Change-Reason (required)

Parameters

NameInTypeRequiredDescription
orgpathstring (uuid)YesOrganization id. Every route checks that it is the token's organization (otherwise 404).
zonepathstring (uuid)YesZone id (see List zones).
X-Change-ReasonheaderstringYesReason of the change: 1-500 UTF-8 characters after trimming spaces, no control characters. If it is missing or invalid: 422 reason_required. 1 to 500 characters.
If-MatchheaderstringYesExpected configuration version, e.g. "12". Required (428 if_match_required); if it is not the current one: 412 version_conflict.
dry_runquerystringNo1/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.

FieldTypeRequiredDescription
to_versionintegerYesVersion the change creates (the same if nothing changes). Minimum 1.
allow_missing_certsbooleanNoDefault false.

Response

  • 200: Reverted (RevertResult, with X-Config-Version and ETag) or, with dry_run, the plan (Applied). Returns RevertResult or Applied.
FieldTypeDescription
versionintegerNew version created by the revert.
restored_fromintegerVersion restored by a revert (null otherwise).
diffDiffChanges.
warningsarray of stringWarnings (the change is still valid).

Response headers: ETag, X-Config-Version.

Errors

StatusDescription
400Malformed request (bad_request).
403The token's role or limits do not allow it (forbidden).
404Not found, or not visible to the token (not_found).
409missing_certs: sites that would be left without a valid certificate · conflict: the zone is disabled (merged zones too).
412version_conflict: If-Match does not match the current version.
422Validation error (invalid) or missing or invalid reason (reason_required).
428if_match_required: the operation requires If-Match.

Example

curl -X POST "https://dash.openwaf.dev/v1/orgs/$OPENWAF_ORG/zones/6f1d2c3b-8a4e-4b7d-9c21-5e3f7a8b9c0d/revert" \
  -H "Authorization: Bearer $OPENWAF_TOKEN" \
  -H "X-Change-Reason: Undo the last change" \
  -H 'If-Match: "12"' \
  -H "Content-Type: application/json" \
  --data '{
    "to_version": 11
  }'
200
{
  "version": 12,
  "restored_from": 0,
  "diff": {
    "from": 0,
    "to": 0,
    "changes": [
      {
        "path": "rules[id=12]",
        "op": "add",
        "from": "example",
        "to": "example"
      }
    ]
  },
  "warnings": []
}

Get propagation

GET /v1/orgs/{org}/zones/{zone}/propagation

Shows which configuration version each edge node serving the zone has applied, against the desired (current) version in the ETag. Nodes that are leaving the zone appear with status retiring until they apply a configuration without it.

Required role: readonly or higher.

Parameters

NameInTypeRequiredDescription
orgpathstring (uuid)YesOrganization id. Every route checks that it is the token's organization (otherwise 404).
zonepathstring (uuid)YesZone id (see List zones).

Response

FieldTypeDescription
zone_idstring (uuid)Zone id.
desired_versioninteger
nodesarray of NodePropagation

Response headers: ETag.

Errors

StatusDescription
404Not found, or not visible to the token (not_found).

Example

curl "https://dash.openwaf.dev/v1/orgs/$OPENWAF_ORG/zones/6f1d2c3b-8a4e-4b7d-9c21-5e3f7a8b9c0d/propagation" \
  -H "Authorization: Bearer $OPENWAF_TOKEN"
200
{
  "zone_id": "6f1d2c3b-8a4e-4b7d-9c21-5e3f7a8b9c0d",
  "desired_version": 12,
  "nodes": [
    {
      "node_id": "edge-node-1",
      "status": "converged",
      "applied_version": 12,
      "applied_serial": 0,
      "current_serial": 0,
      "pending_since": "2026-10-27T09:30:00Z",
      "lag_seconds": 0,
      "last_seen_at": "2026-10-27T09:30:00Z"
    }
  ]
}

Last updated:

↑↓ to navigate↵ to openesc to close