> ## Documentation Index
> Fetch the complete documentation index at: https://docs.dynamic.xyz/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Policy and screening webhooks

> Events emitted by the Policy Engine: policy violations, transaction review decisions, and address screening verdicts.

Policy and screening events fire under the `waas.*` and `wallet.*` namespaces. They cover blocked transactions, transaction review decisions, and screening verdicts on wallet addresses.

For the shared event envelope, endpoint setup, retries, and signature verification, see [Setting up webhooks](https://docs.dynamic.xyz/docs/platform/console/webhooks/setup.md) and [Event delivery & best practices](https://docs.dynamic.xyz/docs/platform/console/webhooks/delivery-best-practices.md). The current list of event types is always available from the [event types endpoint](https://docs.dynamic.xyz/docs/api-reference/events/get-event-types.md).

Browse [all webhook events](https://docs.dynamic.xyz/docs/platform/console/webhooks/event-types.md) for the full listing across Dynamic products.

## Policy violations

**waas.policy.violation** `object`

Occurs whenever a transaction is blocked by a configured policy rule. This event provides detailed information about the violation including the denied addresses, all counterparties involved in the transaction, and the reason for blocking. Useful for building allow-only rules, security monitoring, and debugging policy configurations. See [Policy Violation Webhooks](https://docs.dynamic.xyz/docs/embedded-wallets/mpc/policies/violation-webhooks.md) for more details.

## Screening verdicts

**wallet.sanctions.blocked** `object`

Occurs whenever one of a user's wallet addresses is blocked by the sanctions
baseline. A block produced by your own [screening
policy](https://docs.dynamic.xyz/docs/policies/screening-policies.md) sends
`wallet.addressScreening.blocked` instead. A block in an environment with no
screening policy in play also sends this event, so an environment that has
authored nothing sees what it saw before. Dynamic also sends the deprecated
`sanctions.wallet.blocked` alias; that behavior is unchanged.

Fires once per blocked decision in a user flow (the winning result), not per
provider response, including decisions served from the screening cache. Only
blocks emit this event. An alert sends `wallet.addressScreening.alerted`.

`backgroundPrefetch` is the one exception to per-decision emission: the
background cache-warming check emits only on a fresh discovery, so a blocked
returning user does not emit once per visit. Later user-facing flows that hit
that cache do emit, with their own `origin`.

The payload contains `walletAddress` (lowercase, normalized), `chain`,
`sanctionsProvider`, `sanctionCheckRequestId`, `categories` (the
provider-returned categories that triggered the block), `origin` (the surface that triggered the
screening: `signIn`, `walletConnect`,
`flowDestination`, `flowSource`, `api`, `backgroundPrefetch`,
`transactionSigning`, or `transactionScreenApi`; this enum will grow as new
screening surfaces are added, so handle unrecognized values gracefully), `keyOwner`
(`dynamic` or `customerProvided`), and `screenedAt`.

**wallet.addressScreening.blocked** `object`

Occurs whenever a wallet address is blocked by your own [screening
policy](https://docs.dynamic.xyz/docs/policies/screening-policies.md), either by one of your rules or
by an address you listed as blocked. A block by the sanctions baseline sends
`wallet.sanctions.blocked` instead.

Emission follows the same rules as `wallet.sanctions.blocked`: once per
user-facing decision including cache-served ones, with `backgroundPrefetch`
emitting only on fresh discovery.

The payload carries the same fields as `wallet.sanctions.blocked`, plus
`action` (always `blocked`), `reason`, and an optional `txContext`.

`reason` explains which layer decided and what it matched, in the provider's own
vocabulary. It is always present and always contains `provider` and `matched`.
`matched` is `customer` for one of your rules and `address` for a blocked
address entry. The other fields depend on the provider and on which signal
fired: `revision` (the policy generation that produced the verdict), `rule`
(the matched rule exactly as evaluated, present only when `matched` is
`customer`), `category`, `riskType` and `score` for TRM Labs, `risk` for
Chainalysis, and `summary`.

`txContext` carries `amountUsd` and `asset` for the transaction the screen was
performed for. It is omitted when neither is known, which is the case at
sign-in, on connect, on background prefetch, and on the signing path.

> [!WARNING]
>
> `summary` is for display and logs only. Its wording can change in any
> release, so do not parse it. Route on `category`, `provider`, and `matched`.

> [!NOTE]
>
> Neither screening API response returns `reason`. Both endpoints accept an
> end-user JWT, so the response body is readable by the person being screened,
> and the reason names your rule and the provider's assessment of that person.
> The reason reaches you server-side, on this event.

**wallet.addressScreening.alerted** `object`

Occurs whenever your screening policy alerts on a wallet address. An alert does
not block: the request proceeds and the user is not stopped.

The payload is the same as `wallet.addressScreening.blocked`, with `action`
always `alerted`. The sanctions baseline never alerts, so `matched` is
`customer` or `address` on this event too.

Subscribe to this event to run a rule in monitoring mode before you switch it
to a block.

### Example Wallet Sanctions Blocked Event Payload

```json theme={"system"}
{
  "eventId": "2a92c161-3167-44ad-8fce-4c6cdaed8129",
  "messageId": "5a2a5360-bb7e-4ea6-9bd3-0146bf2f734f",
  "webhookId": "a86acea4-e050-4846-8e4f-0ae039f6e37c",
  "userId": "a5914498-7a8b-4c58-b04c-9624fef2897c",
  "eventName": "wallet.sanctions.blocked",
  "environmentId": "123e4567-e89b-12d3-a456-426614174000",
  "environmentName": "sandbox",
  "timestamp": "2023-10-26T14:30:59.210Z",
  "data": {
    "walletAddress": "0x7f367cc41522ce07553e823bf3be79a889debe1b",
    "chain": "ethereum",
    "sanctionsProvider": "dynamic-sanctions-screening",
    "sanctionCheckRequestId": "484e49ba-3026-4e2c-9bf0-ed98ae224833",
    "categories": ["Sanctions", "Blocklisted"],
    "origin": "signIn",
    "keyOwner": "dynamic",
    "screenedAt": "2023-10-26T14:30:59.210Z"
  }
}
```

### Example Wallet Address Screening Blocked Event Payload

```json theme={"system"}
{
  "eventId": "6f1c0f2a-9d3b-4f0e-8a21-5b7c4e91d0aa",
  "messageId": "1c8e2d44-7b90-4f5a-9c31-2a6b8e47f012",
  "webhookId": "a86acea4-e050-4846-8e4f-0ae039f6e37c",
  "userId": "a5914498-7a8b-4c58-b04c-9624fef2897c",
  "eventName": "wallet.addressScreening.blocked",
  "environmentId": "123e4567-e89b-12d3-a456-426614174000",
  "environmentName": "sandbox",
  "timestamp": "2026-09-15T10:12:04.880Z",
  "data": {
    "walletAddress": "0x2f389ce8bd8ff92de3402ffce4691d17fc4f6535",
    "chain": "ethereum",
    "sanctionsProvider": "trm-wallet-screening",
    "sanctionCheckRequestId": "9d6b1f7c-2a44-4e51-9f0c-58c2b1e7a3d4",
    "categories": ["Mixer"],
    "origin": "transactionSigning",
    "keyOwner": "customerProvided",
    "screenedAt": "2026-09-15T10:12:04.880Z",
    "action": "blocked",
    "reason": {
      "provider": "trm-wallet-screening",
      "matched": "customer",
      "revision": 7,
      "rule": {
        "when": {
          "exists": {
            "in": "trm.addressRiskIndicators",
            "where": {
              "all": [
                { "field": "category", "op": "eq", "value": "Mixer" },
                { "field": "riskType", "op": "eq", "value": "OWNERSHIP" }
              ]
            }
          }
        },
        "then": "BLOCK"
      },
      "category": "Mixer",
      "riskType": "OWNERSHIP",
      "score": 10,
      "summary": "Mixer owned by the screened address"
    },
    "txContext": {
      "amountUsd": 25000,
      "asset": "USDC"
    }
  }
}
```

An alert has the same shape, with `eventName` of `wallet.addressScreening.alerted` and `action` of `alerted`.

> [!NOTE]
>
> `sanctions.wallet.blocked` is the deprecated alias of
> `wallet.sanctions.blocked`. Existing subscriptions on the old name keep
> receiving the event; it is not advertised in the event types catalog, so new
> subscriptions should use `wallet.sanctions.blocked`.

## Transaction review

> [!NOTE]
>
> `waas.transaction.review.approved` and `waas.transaction.review.denied` are
> emitted when a transaction review resolves, but are not selectable in the
> event types catalog today.

## Policy configuration events

Changes to policies, screening policies, and BYOK screening keys by console admins emit `admin.*` events: `admin.waas.policy.*`, `admin.addressScreening.policy.*`, and `admin.addressScreening.byok.*`. These are documented with the other admin events under [Admin and environment events](https://docs.dynamic.xyz/docs/platform/console/webhooks/events.md).


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.