# Policy Engine v2: transaction status changes

Ripple is rolling out Policy Engine v2, which runs policy checks and transaction approvals in a single policy phase. Until now, a transaction that required approvals passed its policy checks first and then waited in a separate approval phase. With Policy Engine v2, the transaction stays in the policy phase until policy rules and any required approvals all complete.

This changes the sequence of `status` values that transactions emit. If you poll the transactions API or consume `TRANSACTION` webhooks, review the changes below and update any automation that depends on the approval statuses.

Rollout is per environment
Nothing changes in an environment until Ripple enables Policy Engine v2 there. It's active in Development today. Ripple will announce the Sandbox and Production dates separately and will enable Sandbox first so that you can validate your integration before Production changes. See [Availability](#availability).

## What's changing

### Wallet-as-a-Service no longer emits the approval statuses

New transactions no longer transition through `APPROVAL_CHECK_PENDING` or `APPROVAL_CHECK_PASSED`. Instead, the transaction remains in `POLICY_CHECK_PENDING` while approvers act on it.

| Status | Before | After |
|  --- | --- | --- |
| `APPROVAL_CHECK_PENDING` | Wallet-as-a-Service emits this status when a transaction-level approval round starts. | Wallet-as-a-Service doesn't emit this status. The transaction stays in `POLICY_CHECK_PENDING` while it collects approvals. |
| `APPROVAL_CHECK_PASSED` | Wallet-as-a-Service emits this status when the transaction meets its approval requirement. | Wallet-as-a-Service doesn't emit this status. The policy phase completes with `POLICY_CHECK_PASSED` and the transaction proceeds to `COMPILATION_PENDING`. |


Both values remain valid members of the `TransactionStatus` enum. Clients that deserialize the enum keep working, and historical transactions keep the status history they already have. Transactions already in flight when Ripple enables Policy Engine v2 complete on the path they started, so they might still emit these statuses for a short time after the switch.

### `POLICY_CHECK_PASSED` means policy and approvals passed

Wallet-as-a-Service still emits `POLICY_CHECK_PASSED` for every allowed transaction, but later in the lifecycle. It now means that the transaction passed policy evaluation **and** all required approvals, and compilation is about to start. Previously, Wallet-as-a-Service emitted it before any approval round started.

The status sequence for an allowed outbound transaction becomes:

```
REQUESTED → POLICY_CHECK_PENDING → POLICY_CHECK_PASSED → COMPILATION_PENDING → COMPILED → SIGNATURE_PENDING → SIGNED → PUBLISH_PENDING → PUBLISHED → CONFIRMATION_PENDING → CONFIRMED
```

When a policy rule, an approver, or an expired approval rejects a transaction during the policy phase, the transaction moves from `POLICY_CHECK_PENDING` to `REJECTED`. This is the same transition a policy rejection makes today.

### `POLICY_CHECK_PENDING` can last much longer

Because approvals now happen inside the policy phase, a transaction can stay in `POLICY_CHECK_PENDING` for the full approval window, which can be hours or until the approval expires. Previously, this status typically lasted milliseconds. Review any timeout or alerting logic that depends on time spent in `POLICY_CHECK_PENDING`.

### Structured rejection details

When the policy phase rejects a transaction, Wallet-as-a-Service adds a structured entry to the transaction's `problems` array that explains why. Each entry includes:

| Field | Description |
|  --- | --- |
| `reason` | A `PAL006.xxx` code. Policy rule rejections carry the rule's code, for example `PAL006.007` for an over-limit transfer. `PAL006.044` means the transaction didn't meet its approval requirement. `PAL006.045` means the approval expired. |
| `message` | A human-readable explanation. Wallet-as-a-Service mirrors the same text into the deprecated `reasons` array for compatibility. |
| `retryability` | `NOT_RETRYABLE` for policy-phase rejections. Fix the cause and submit a new transaction. |


Read the `problems` entry rather than parsing the free-text `reasons` array. Transactions created before the rollout don't carry a policy-stamped `problems` entry, so treat its absence as no information rather than as an error.

## What's not changing

- **Approver experience.** Wallet-as-a-Service still creates approval requests for transactions that require them. Approvers receive and action them in the web console and passkey flows exactly as before.
- **Approvals API and approval webhooks.** In-progress approval visibility, such as who has approved so far, stays in the approvals API and `APPROVAL` domain webhooks. An open approval request for a transaction means it's waiting on approvers while the transaction itself sits in `POLICY_CHECK_PENDING`.
- **Webhook event types.** There are no new `TRANSACTION` webhook events. Notifications for the two approval statuses stop arriving for new transactions because those transitions no longer happen.
- **API schema.** Ripple isn't removing any fields or enum values.
- **Approval groups, quorums, and policy configuration.** Your existing policies and approval groups continue to apply without changes.
- **Terminal statuses.** `CONFIRMED`, `REJECTED`, and `FAILED` behave exactly as today.


## What you need to do

Before Ripple enables Policy Engine v2 in your environment:

1. Remove any state-machine logic that requires `APPROVAL_CHECK_PENDING` or `APPROVAL_CHECK_PASSED` to occur. Don't remove the values from your client-side enum definitions.
2. If your integration waits for `APPROVAL_CHECK_PASSED` before it treats a transaction as progressing, wait for `POLICY_CHECK_PASSED` or any later status instead.
3. If you interpret `POLICY_CHECK_PASSED` as "policy passed, approvals may still be pending," update that interpretation. After the change, it means the whole policy phase, including approvals, is complete.
4. If you treat `APPROVAL_CHECK_PENDING` as "awaiting approval," use `POLICY_CHECK_PENDING` together with the approvals API or `APPROVAL` webhooks to detect that state.
5. Adjust any timeout or alerting logic that depends on time spent in `POLICY_CHECK_PENDING`.
6. Optionally, read the structured `problems` entry on `REJECTED` transactions instead of the deprecated `reasons` array.


These changes apply equally to API polling and to `TRANSACTION` webhook consumers, because webhook notifications carry the same status values.

## Availability

Ripple enables Policy Engine v2 per environment and per organization.

| Environment | Status |
|  --- | --- |
| Development | Active for all organizations. |
| Sandbox | Ripple enables Policy Engine v2 in Sandbox on September 21, 2026. Ripple enables Sandbox before Production so that you can validate against Sandbox first. |
| Production | Ripple will announce the date and coordinate enablement with each organization. |


Until Ripple enables Policy Engine v2 in an environment, transactions there continue to emit the legacy status sequence, including `APPROVAL_CHECK_PENDING` and `APPROVAL_CHECK_PASSED`.

## Related documentation

- [Transactions overview](/products/wallet/user-interface/transactions/overview) for the complete status reference
- [Webhooks overview](/products/wallet/user-interface/integrations/overview) for `TRANSACTION` webhook payloads
- [Approvals](/products/wallet/user-interface/security-controls/approvals) for how approval requests work
- [Wallet-as-a-Service API](/products/wallet/api-docs/palisade-api/palisade-api) for the transaction and approvals endpoints