## Web tamper protection (`site-tamper-guards`)

Web tamper protection of one site: protected scopes (home page, pages, directories), what counts as tampering (structure only / any change), serving the baseline page or alerting only, and the observation period; baseline update and diff; part of WAF Enhanced.

Authentication: User (some parameters admin only) · Docs: https://www-demo.kuxitong.com/en/docs/api/site-tamper-guards

### GET `/api/v2/site-tamper-guards/{site_id}`

Get site web tamper protection settings · Authentication: User (some parameters admin only)

```sh
curl "https://panel.example.com/api/v2/site-tamper-guards/{site_id}" \
  -H "X-API-Key: $GOCDN_API_KEY"
```

### PUT `/api/v2/site-tamper-guards/{site_id}`

Set site web tamper protection · Authentication: User (some parameters admin only)

Request body:

| Field | Type | Required | Description |
|---|---|---|---|
| `action` | string |  | Action on tampering. Values: ["restore","log"] |
| `enabled` | boolean | Yes | Whether enabled. |
| `expected_updated_at` | string |  | Optimistic lock - the updated_at as the caller read it (when null, i.e. never set, use 1970-01-01T00:00:00Z). If it differs from the stored one, 409 stale_version is returned and nothing is saved; omit to skip the check. |
| `mode` | string |  | What counts as tampering. Values: ["structure","full"] |
| `observe_days` | integer |  | Days observed after turning on. |
| `scopes` | SiteTamperScope[] |  | Protected scopes. |

```sh
curl -X PUT "https://panel.example.com/api/v2/site-tamper-guards/{site_id}" \
  -H "X-API-Key: $GOCDN_API_KEY"
```

### DELETE `/api/v2/site-tamper-guards/{site_id}`

Restore site web tamper protection to the scheme · Authentication: User (some parameters admin only)

```sh
curl -X DELETE "https://panel.example.com/api/v2/site-tamper-guards/{site_id}" \
  -H "X-API-Key: $GOCDN_API_KEY"
```

### GET `/api/v2/site-tamper-guards/{site_id}/diff`

Get site web tamper protection diff · Authentication: User (some parameters admin only)

Query parameters:

| Field | Type | Required | Description |
|---|---|---|---|
| `path` | string | Yes | Baseline page path (e.g. /, /about.html). |

```sh
curl "https://panel.example.com/api/v2/site-tamper-guards/{site_id}/diff" \
  -H "X-API-Key: $GOCDN_API_KEY"
```

### POST `/api/v2/site-tamper-guards/{site_id}/rebase`

Update site web tamper protection baseline · Authentication: User (some parameters admin only)

```sh
curl -X POST "https://panel.example.com/api/v2/site-tamper-guards/{site_id}/rebase" \
  -H "X-API-Key: $GOCDN_API_KEY"
```

Web tamper protection object:

| Field | Type | Required | Description |
|---|---|---|---|
| `action` | string |  | Action on tampering. Values: ["restore","log"] |
| `assets` | SiteTamperAsset[] |  | JS/CSS whose fingerprint differs (recorded only, not replaced). |
| `base_at` | string |  | Baseline time (the last baseline update). (read-only) |
| `base_ver` | integer |  | Baseline version, +1 on every baseline update; 0 = no baseline yet. (read-only) |
| `changes` | SiteTamperChange[] |  | Structural changes (removed links and text changes are not listed). |
| `enabled` | boolean |  | Whether enabled. |
| `expected_updated_at` | string |  | Optimistic lock - the updated_at as the caller read it (when null, i.e. never set, use 1970-01-01T00:00:00Z). If it differs from the stored one, 409 stale_version is returned and nothing is saved; omit to skip the check. |
| `fetch_error` | string |  | Why the page could not be fetched now (changes is then empty): fetch_failed = the origin did not return 200 or could not be reached; not_html = not a web page; too_large = over 1 MB. Absent when fetched. Values: ["fetch_failed","not_html","too_large"] |
| `gate` | string |  | WAF Enhanced status of the site's tenant: full = editable; readonly = expired but within the read-only buffer (License.readonly_days, 7 days by default), still in effect but read-only; basic = not subscribed or past the buffer, nothing checked and settings kept. Values: ["full","readonly","basic"] (read-only) |
| `gate_expired_at` | string |  | Administrator responses with gate_reason=expired only - when the platform WAF Enhanced license expired; not present in tenant responses. (read-only) |
| `gate_owner` | WafGateOwner |  | The owner of the site, in administrator responses only; tenant responses carry no one else's information. (read-only) |
| `gate_packages` | string[] |  | Administrator responses only - names of the owner's unexpired packages (at most 20); not present in tenant responses. (read-only) |
| `gate_reason` | WafGateReason |  | Why WAF Enhanced (waf_enhanced) is not in effect; absent when gate is full or readonly. package = the platform is licensed but the owner has no unexpired package that includes WAF Enhanced; license = the platform has not enabled it (never licensed, revoked by the provider, or the license was disabled); expired = the platform license has expired and its read-only buffer period (License.readonly_days, default 7 days) has passed, so it fell back to basic. Values: ["package","license","expired"] (read-only) |
| `mode` | string |  | What counts as tampering. Values: ["structure","full"] |
| `observe_days` | integer |  | Days observed after turning on. |
| `observe_until` | string |  | End of the observation period; null = not observing (never on, or 0 days chosen). (read-only) |
| `pages` | SiteTamperPage[] |  | Baseline pages (sorted by path), including scopes that were not included and why. (read-only) |
| `path` | string |  | Page path. |
| `scopes` | SiteTamperScope[] |  | Protected scopes. |
| `site_id` | integer |  | Site ID (read-only) |
| `source` | ProtectSiteSource |  | Where the site's setting comes from: scheme = follows the scheme (changes when the scheme is saved); custom = set for this site alone (including turned off and rows migrated from before). Values: ["scheme","custom"] (read-only) |
| `tampered` | boolean |  | Whether this counts as tampering under the site's mode. |
| `updated_at` | string |  | Version (null if never set); use expected_updated_at on update. (read-only) |
