# OpenWAF Verify

> Challenges issued, solved and failed by the browser challenge and the Verify widgets of a zone, siteverify answers and risk scoring.

Analytics of [OpenWAF Verify](https://developers.openwaf.dev/waf/verify-widget/) on a zone, the browser challenge page (gate, rate limits, AI Crawl Control, [under attack mode](https://developers.openwaf.dev/waf/under-attack/)) and the widgets. The settings are the `challenge` block of the zone's [edge settings](https://developers.openwaf.dev/api/edge-settings/#update-zone-edge).

| Operation | Endpoint |
|---|---|
| [Get Verify analytics](https://developers.openwaf.dev/api/verify/#get-challenge-analytics) | `GET /v1/orgs/{org}/zones/{zone}/challenge/analytics` |

## Get Verify analytics

```http
GET /v1/orgs/{org}/zones/{zone}/challenge/analytics
```

Returns, for the last `days` (1–30, default 7), the challenges issued, solved, failed, abandoned and solved with a click (`interactive`), the solve rate and solve time, failures by cause, siteverify answers, one row per trigger (`gate`, `rate_rule`, `ai_agents`, `pipeline`, `crawler`, `under_attack`) and per widget, and one per day. `risk` is the zone's [risk scoring](https://developers.openwaf.dev/waf/verify-risk/#analytics) mode and thresholds and what it decided in the window, always present (zeros without data); in `log` mode its levels, escalations and blocks are what would have been applied. See [Browser challenge analytics](https://developers.openwaf.dev/waf/browser-challenge/#analytics).

**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)). |
| `days` | query | integer | No | UTC days ending today. Default `7`. From 1 to 30. |

#### Response

- `200`: Returns [ChallengeAnalytics](https://developers.openwaf.dev/api/schemas/#challenge-analytics).

| Field | Type | Description |
|---|---|---|
| `zone` | string |  |
| `days` | integer |  |
| `from` | string (date-time) |  |
| `to` | string (date-time) |  |
| `totals` | object |  |
| `totals.issued` | integer |  |
| `totals.solved` | integer |  |
| `totals.failed` | integer |  |
| `totals.abandoned` | integer |  |
| `totals.interactive` | integer |  |
| `totals.solve_rate` | number |  |
| `totals.latency_p50_ms` | integer |  |
| `totals.latency_p95_ms` | integer |  |
| `totals.latency_mean_ms` | integer |  |
| `failures` | object |  |
| `failures.invalid` | integer |  |
| `failures.expired` | integer |  |
| `failures.replayed` | integer |  |
| `failures.solution` | integer |  |
| `failures.elsewhere` | integer |  |
| `siteverify` | object |  |
| `siteverify.ok` | integer |  |
| `siteverify.invalid` | integer |  |
| `siteverify.duplicate` | integer |  |
| `siteverify.expired` | integer |  |
| `siteverify.bad_secret` | integer |  |
| `siteverify.remoteip_mismatch` | integer |  |
| `siteverify.error` | integer |  |
| `by_label` | array of object |  |
| `by_label[].source` | string | One of `interstitial`, `widget`. |
| `by_label[].widget_id` | string |  |
| `by_label[].widget_name` | string |  |
| `by_label[].label` | string |  |
| `by_label[].issued` | integer |  |
| `by_label[].solved` | integer |  |
| `by_label[].failed` | integer |  |
| `by_label[].solve_rate` | number |  |
| `by_label[].latency_p50_ms` | integer |  |
| `by_label[].latency_p95_ms` | integer |  |
| `by_label[].risk_levels` | [ChallengeRiskLevels](https://developers.openwaf.dev/api/schemas/#challenge-risk-levels) |  |
| `daily` | array of object |  |
| `daily[].date` | string (date) |  |
| `daily[].issued` | integer |  |
| `daily[].solved` | integer |  |
| `daily[].failed` | integer |  |
| `risk` | [ChallengeRiskReport](https://developers.openwaf.dev/api/schemas/#challenge-risk-report) |  |
| `settings` | [ZoneEdgeChallenge](https://developers.openwaf.dev/api/schemas/#zone-edge-challenge) |  |

#### Errors

| Status | Description |
|---|---|
| `400` | Malformed request (`bad_request`). |
| `404` | Not found, or not visible to the token (`not_found`). |
| `503` | Not available right now (`unavailable`); retry later. |

#### Example

No SDK method yet: use the HTTP request.

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

```json
{
  "zone": "example.com",
  "days": 0,
  "from": "2026-10-27T09:30:00Z",
  "to": "2026-10-27T09:30:00Z",
  "totals": {
    "issued": 0,
    "solved": 0,
    "failed": 0,
    "abandoned": 0,
    "interactive": 0,
    "solve_rate": 0.5,
    "latency_p50_ms": 0,
    "latency_p95_ms": 0,
    "latency_mean_ms": 0
  },
  "failures": {
    "invalid": 0,
    "expired": 0,
    "replayed": 0,
    "solution": 0,
    "elsewhere": 0
  },
  "siteverify": {
    "ok": 0,
    "invalid": 0,
    "duplicate": 0,
    "expired": 0,
    "bad_secret": 0,
    "remoteip_mismatch": 0,
    "error": 0
  },
  "by_label": [
    {
      "source": "interstitial",
      "widget_id": "b37fe5d7-b6b8-4af4-ad93-0e98076dac07",
      "widget_name": "example",
      "label": "AI training",
      "issued": 0,
      "solved": 0,
      "failed": 0,
      "solve_rate": 0.5,
      "latency_p50_ms": 0,
      "latency_p95_ms": 0,
      "risk_levels": {
        "pass": 0,
        "harder": 0,
        "interactive": 0,
        "block": 0
      }
    }
  ],
  "daily": [
    {
      "date": "2026-10-27",
      "issued": 0,
      "solved": 0,
      "failed": 0
    }
  ],
  "risk": {
    "mode": "off",
    "thresholds": {
      "harder": 0,
      "interactive": 0,
      "block": 0
    },
    "evaluated": 0,
    "levels": {
      "pass": 0,
      "harder": 0,
      "interactive": 0,
      "block": 0
    },
    "scores": [
      0
    ],
    "top_signals": [
      {
        "signal": "example",
        "count": 128
      }
    ],
    "escalated": 0,
    "blocked": 0
  },
  "settings": {
    "pass_ttl_minutes": 720,
    "difficulty": 16,
    "pass_scope": "host",
    "color": "",
    "gate": {
      "enabled": false,
      "paths": [
        "/checkout"
      ],
      "pages": [
        "example"
      ]
    },
    "under_attack": {
      "enabled": false,
      "until": "2026-10-27T09:30:00Z",
      "hosts": [
        "www.example.com"
      ],
      "exempt_paths": [
        "example"
      ],
      "difficulty": 0,
      "pass_ttl_minutes": 0,
      "interactive": true
    },
    "risk": {
      "mode": "log",
      "thresholds": {
        "harder": 30,
        "interactive": 60,
        "block": 90
      }
    }
  }
}
```
