## CC matchers (`cc-matches`)

Conditions that identify requests in CC protection; reusable across rule groups.

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

### GET `/api/v2/cc-matches`

List CC matchers · Authentication: User (some parameters admin only)

Query parameters:

| Field | Type | Required | Description |
|---|---|---|---|
| `page` | integer |  | Page number, starting from 1 Default: 1 |
| `page_size` | integer |  | Items per page Default: 20 |
| `sort` | string |  | Sort fields, comma-separated; prefix `-` for descending, e.g. `-created_at,id` |
| `tenant_id` | integer |  | Admin only: filter by tenant. Ignored for tenant credentials, which only see their own tenant's data |
| `name` | string |  | Filter by name substring. |
| `owner` | string |  | platform = platform objects only; tenant = tenant objects only. Values: ["platform","tenant"] |

```sh
curl "https://panel.example.com/api/v2/cc-matches" \
  -H "X-API-Key: $GOCDN_API_KEY"
```

### POST `/api/v2/cc-matches`

Create CC matcher · Authentication: User (some parameters admin only)

Request body:

| Field | Type | Required | Description |
|---|---|---|---|
| `des` | string |  | Remark; empty if omitted (omitting it on update also clears it, since the update replaces the whole object). |
| `name` | string | Yes | Name |
| `when` | object |  | Rule DSL condition: a combination of all/any/not, or a leaf {f, op, v, set, neg}; validated by the server and errors are returned as 422 (field is a JSON Pointer, code is the lowercase DSL error code). null = match everything. |

```sh
curl -X POST "https://panel.example.com/api/v2/cc-matches" \
  -H "X-API-Key: $GOCDN_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"name":"static","when":{"f":"req_uri","op":"contains","v":[".js",".css"]}}'
```

### POST `/api/v2/cc-matches/replay`

Replay a CC matcher draft · Authentication: User (some parameters admin only)

Request body:

| Field | Type | Required | Description |
|---|---|---|---|
| `site_id` | integer |  | Count this site's traffic only; omitted = every site visible to the caller. |
| `when` | object |  | Rule DSL condition: a combination of all/any/not, or a leaf {f, op, v, set, neg}; validated by the server and errors are returned as 422 (field is a JSON Pointer, code is the lowercase DSL error code). null = match everything. |

```sh
curl -X POST "https://panel.example.com/api/v2/cc-matches/replay" \
  -H "X-API-Key: $GOCDN_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"when":{"f":"ja4","op":"eq","v":["t13d1516h2_8daaf6152771_e5627efa2ab1"]}}'
```

### GET `/api/v2/cc-matches/{id}`

Get CC matcher · Authentication: User (some parameters admin only)

```sh
curl "https://panel.example.com/api/v2/cc-matches/{id}" \
  -H "X-API-Key: $GOCDN_API_KEY"
```

### PUT `/api/v2/cc-matches/{id}`

Update CC matcher · Authentication: User (some parameters admin only)

Request body:

| Field | Type | Required | Description |
|---|---|---|---|
| `des` | string |  | Remark; empty if omitted (omitting it on update also clears it, since the update replaces the whole object). |
| `name` | string | Yes | Name |
| `when` | object |  | Rule DSL condition: a combination of all/any/not, or a leaf {f, op, v, set, neg}; validated by the server and errors are returned as 422 (field is a JSON Pointer, code is the lowercase DSL error code). null = match everything. |

```sh
curl -X PUT "https://panel.example.com/api/v2/cc-matches/{id}" \
  -H "X-API-Key: $GOCDN_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"name":"static","when":{"f":"req_uri","op":"contains","v":[".js",".css"]}}'
```

### DELETE `/api/v2/cc-matches/{id}`

Delete CC matcher · Authentication: User (some parameters admin only)

```sh
curl -X DELETE "https://panel.example.com/api/v2/cc-matches/{id}" \
  -H "X-API-Key: $GOCDN_API_KEY"
```

CC matchers object:

| Field | Type | Required | Description |
|---|---|---|---|
| `builtin` | boolean |  | Built-in object; cannot be deleted. (read-only) |
| `created_at` | string |  | Created at (read-only) |
| `des` | string |  | Remark; empty if omitted (omitting it on update also clears it, since the update replaces the whole object). |
| `hits` | integer |  | Requests matched in the window (restored by sample_weight). |
| `id` | integer |  | Record ID (read-only) |
| `ips` | integer |  | Distinct client IPs among the matched requests (a distinct count, not restored by sample weight). |
| `name` | string |  | Name |
| `reason` | string |  | Explanation when supported=false. |
| `sampled` | boolean |  | Some rows in the window were sampled (sample_weight > 1); hits and total are estimates. |
| `site_id` | integer |  | Count this site's traffic only; omitted = every site visible to the caller. |
| `sites` | integer |  | Distinct sites among the matched requests (a distinct count, not restored by sample weight). |
| `supported` | boolean |  | false = the condition uses something access_log does not hold (request headers, accept_language, named sets), so nothing was replayed; see reason. |
| `tenant_id` | integer |  | Owning tenant; null = platform object (built-in or created by an admin, read-only for tenants). (read-only) |
| `top_ips` | CcMatchReplayIp[] |  | Client IPs with the most matched requests, at most 20, sorted by requests descending; empty when supported=false or nothing matched. |
| `top_urls` | CcMatchReplayUrl[] |  | URLs (without the query string) with the most matched requests, at most 5, sorted by requests descending; empty when supported=false or nothing matched. |
| `total` | integer |  | Total requests in the window (also restored). |
| `updated_at` | string |  | Updated at (read-only) |
| `when` | object |  | Rule DSL condition: a combination of all/any/not, or a leaf {f, op, v, set, neg}; validated by the server and errors are returned as 422 (field is a JSON Pointer, code is the lowercase DSL error code). null = match everything. |
| `window_hours` | integer |  | Replay window in hours (fixed at 24). |
