# Policies

Transaction policies are the security rules that control what funds can leave your wallets. Each policy is a **policy rule** with a kind: a limit rule caps what a wallet can send, an approval rule holds large transactions for named approvers, and a Travel Rule rule requires a Travel Rule data exchange before a transfer settles. Every wallet in Ripple Custody (Wallet) is **deposit-only by default**. You must create at least one limit rule for an asset before you can send that asset from the wallet.

In this section
- [Manage policies via the console](/products/wallet/governance-and-controls/policies/manage-policies): Create, change, and delete limit, approval, and Travel Rule rules in the console
- [Manage policy rules via the API](/products/wallet/governance-and-controls/policies/manage-policies-api): Create, list, get, and delete policy rules, and use the wallet limits endpoints
- [Policy reference](/products/wallet/governance-and-controls/policies/policy-reference): Limit types, matchers, rule statuses, permissions, and error codes
- [Policy best practices](/products/wallet/governance-and-controls/policies/best-practices): Recommended patterns and troubleshooting
- [Step-up approvals](/products/wallet/governance-and-controls/approvals/step-up-approvals): Require named approvers for transactions of more than an amount
- [Travel Rule](/products/wallet/compliance/travel-rule): Exchange originator and beneficiary information before a transfer settles


## What policies do

Think of policies as programmable spending limits. When you submit a transaction, the policy engine checks it against the applicable active policy rules for that wallet and asset. If the transaction exceeds any applicable limit, the system rejects it before signing. This protects your assets even if someone gains unauthorized access to your API credentials or user accounts.

**Policies answer these questions:**

- How much can leave in a single transaction?
- How much can leave over a period of time?
- What is the maximum that can ever leave?
- Who can initiate transactions, and to where?
- Which transactions need extra approvers, or a Travel Rule exchange?


Policies protect against:

- **Unauthorized large transfers** – Per-transaction limits cap individual transaction amounts
- **Rapid fund drainage** – Rolling-duration limits detect abnormal withdrawal patterns
- **Total asset loss** – Max-total-value limits set lifetime caps on withdrawals


## Quick start

1. **Create a policy** – Open your wallet's **Policy** tab and select **Add a new rule**. Select **Limit**, and then select the asset, limit type, and amount.
2. **Approve the policy** – If your organization has approval groups configured, designated approvers must authorize the policy before it takes effect.
3. **Send transactions** – Once the policy is active, transactions within the limit proceed normally. Transactions exceeding the limit are rejected.


See [Manage policies via the console](/products/wallet/governance-and-controls/policies/manage-policies) for the full walkthrough.

## Rule kinds

Each policy rule has a **kind** that decides what the rule does when a transaction matches it:

| Kind | What it does | Direction |
|  --- | --- | --- |
| `LIMIT` | Lets outgoing transactions proceed up to an amount, and blocks transactions that exceed it | Outbound |
| `APPROVAL` | Holds outgoing transactions of more than an amount until named approvers approve them. See [Step-up approvals](/products/wallet/governance-and-controls/approvals/step-up-approvals). | Outbound |
| `TRAVEL_RULE` | Requires a Travel Rule data exchange with the counterparty before a transfer settles. See [Travel Rule](/products/wallet/compliance/travel-rule). | Outbound and inbound |


Wallet limits that you create with the older wallet limits endpoints are `LIMIT` rules, with the same IDs. See [Use the wallet limits endpoints](/products/wallet/governance-and-controls/policies/manage-policies-api#use-the-wallet-limits-endpoints-via-the-api).

### How the rule kinds work together

- **Only `LIMIT` rules let a wallet send.** A wallet can only receive an asset until it has an applicable `LIMIT` rule for that asset. `APPROVAL` and `TRAVEL_RULE` rules never let a transaction through on their own. If no `LIMIT` rule applies, Ripple Custody (Wallet) rejects the transaction with `PAL006.005`.
- **Rule kinds don't override each other.** A transaction must pass its applicable `LIMIT` rules, and then meet any `APPROVAL` and `TRAVEL_RULE` requirements that apply to it.
- **A blocked transaction never reaches approvers.** If a `LIMIT` rule blocks the transaction, Ripple Custody (Wallet) rejects it before it creates any approval request.


## Policy scope

Policies operate at the **wallet level only**. Each policy rule applies to a single wallet and controls transactions for a specific asset within that wallet. The exception is a `TRAVEL_RULE` rule with no amount condition, which can apply to every asset in the wallet.

No vault-level or organization-level policies
You can't create a policy that applies to multiple wallets simultaneously. If you need the same limit across ten wallets, you must create ten separate policies—one for each wallet.

Multi-chain EVM wallets
If your organization uses separate wallets for different EVM chains (for example, one Ethereum wallet and one Arbitrum wallet), policies on one wallet do **not** apply to the other—even if both wallets hold the same asset (ETH). You must create policies independently on each wallet.

## Limit types

`LIMIT` rules support three limit types. In the policy rules API, the limit type is the rule's `aggregation`. The older wallet limits endpoints call it `limitType`.

- **Per transaction (`SINGLE_TX`, or `PER_TX` in the wallet limits endpoints)** – Maximum amount for any single transaction
- **Rolling (`ROLLING`, or `ROLLING_DURATION`)** – Maximum cumulative amount within a sliding time window
- **Max total value (`TOTAL`, or `CONSTANT`)** – Lifetime cap on total withdrawals


You can combine multiple limit types on the same wallet for layered protection.

How rolling windows work
When you attempt a transaction, the system calculates how much has already left the wallet within the current window. If your new transaction would push the total over the limit, the system rejects it immediately. As older transactions "roll off" the window, capacity becomes available again.

See [Policy reference](/products/wallet/governance-and-controls/policies/policy-reference#limit-types) for complete limit type documentation, duration values, and examples.

## Policy uniqueness

Each policy rule must be unique within its wallet. Ripple Custody (Wallet) identifies a rule by these attributes:

| Attribute | Description |
|  --- | --- |
| Wallet ID | The wallet the rule belongs to |
| Kind | `LIMIT`, `APPROVAL`, or `TRAVEL_RULE` |
| Trigger | `OUTBOUND_INITIATED` or `INBOUND_DETECTED` |
| Asset | The asset's registry ID (for example, `3::XRP`) |
| Limit type | The `aggregation`: `SINGLE_TX`, `ROLLING`, or `TOTAL` |
| Matchers | Optional filters that narrow when the rule applies |


The amount and the rolling window don't count, so two `LIMIT` rules that differ only in amount or window are duplicates. For `APPROVAL` rules, the amount does count, so you can create approval tiers with different thresholds.

You can create multiple rules with the same kind, limit type, and asset **if they have different matchers**. For example:

- Per transaction + `XRP` + no matchers → Applies to all XRP transactions
- Per transaction + `XRP` + `TRANSACTION_TYPE: OfferCreate` → Applies only to XRP Ledger DEX offers


Both rules can coexist because their matcher configurations differ.

Duplicate policy error
If you try to create a rule that matches a rule on the wallet that isn't deleted, the policy rules API returns HTTP 409 with `PAL006.039: an equivalent policy rule already exists`. The wallet limits endpoints return `PAL006.023: limit policy already exists`. A rejected rule still counts until you delete it.

## Policy immutability

Policies are immutable. You can't edit an existing policy's limit amount, duration, or matchers.

**To modify a policy:**

1. Create a new policy with the updated values.
2. After the new policy is active, delete the existing policy (see [Manage policies via the console](/products/wallet/governance-and-controls/policies/manage-policies#delete-a-policy-via-the-console)).


Creating the new policy first keeps the wallet protected throughout the change. See [Modify a policy](/products/wallet/governance-and-controls/policies/manage-policies#modify-a-policy-via-the-console).

Why policies are immutable
Immutability provides a clear audit trail. Every policy change creates a new record with its own approval history, making it easy to track who authorized what and when.

## Policy lifecycle

Every policy rule moves through a series of statuses from creation to deletion.

```mermaid
stateDiagram-v2
    direction TB

    [*] --> RULE_CREATION_APPROVAL_PENDING: Create rule

    RULE_CREATION_APPROVAL_PENDING --> RULE_ENABLED: Approved
    RULE_CREATION_APPROVAL_PENDING --> RULE_REJECTED: Rejected

    RULE_ENABLED --> RULE_DELETION_APPROVAL_PENDING: Request deletion

    RULE_DELETION_APPROVAL_PENDING --> RULE_DELETED: Approved
    RULE_DELETION_APPROVAL_PENDING --> RULE_ENABLED: Rejected

    RULE_REJECTED --> RULE_DELETED: Delete (no approval)
    RULE_DELETED --> [*]

    note right of RULE_ENABLED
        Active and enforcing
    end note
    note right of RULE_DELETION_APPROVAL_PENDING
        Still enforcing
    end note
    note right of RULE_REJECTED
        Can't be enabled again
    end note
    note right of RULE_DELETED
        Terminal state
    end note
```

Policy rules move through five main statuses: pending approval, enabled, rejected, pending deletion, and deleted. A rule in `RULE_DELETION_APPROVAL_PENDING` status continues to enforce transactions until approvers approve the deletion—this prevents gaps in protection. If approvers reject the deletion, the rule returns to `RULE_ENABLED`. A rule that Ripple Custody (Wallet) can't process moves to `RULE_ERROR`.

See [Policy reference](/products/wallet/governance-and-controls/policies/policy-reference#rule-statuses) for the complete status reference.

## Approval requirements

Whether a policy requires approval depends on your organization's approval group configuration.

### With approval groups configured

If your organization has an approval group for **Policy rules**, new policy rules enter `RULE_CREATION_APPROVAL_PENDING` status. Designated approvers must authorize the policy before it takes effect.

The policy activates after the required number of approvers authorize it (for example, 2 of 3 approvers). If the approval threshold becomes mathematically impossible to reach (for example, too many approvers skip), the policy moves to `RULE_REJECTED`.

### Without approval groups configured

If no approval group exists for Policy rules, the policy **automatically activates** immediately after creation. It transitions directly to `RULE_ENABLED` with `active: true`.

Security consideration
Without approval groups, anyone with API credentials that include the `policy:create` permission, or `keylimit:create` for the wallet limits endpoints, can instantly enable policies. Consider configuring approval groups to add human oversight.

See [Configure approval flows](/products/wallet/governance-and-controls/approvals/configure-approval-flows) to configure approval groups for your organization.

## Policy evaluation

When you submit a transaction, the policy engine evaluates it against all active policies for that wallet and asset. Policy checks are one stage in the full transaction pipeline.

### Where policies fit in the transaction pipeline

Policy evaluation is the first check after a user or API credential creates a transaction. The full pipeline is:

```mermaid
flowchart TD
    TX[Transaction created] --> PC[Policy check]
    PC -->|Pass| AP{Approvals required?}
    PC -->|Fail| REJ[Transaction rejected]
    AP -->|Yes| AG[Approval group review]
    AP -->|No| SIG[MPC signing]
    AG -->|Approved| SIG
    AG -->|Rejected| REJ
    SIG --> BC[Blockchain submission]
    BC --> CONF[Confirmed]

    style REJ fill:#ffcccc
    style CONF fill:#ccffcc
```

1. **Policy check** – The engine evaluates the transaction against every applicable `LIMIT` rule (see [Evaluation order](#evaluation-order)). If any applicable rule rejects it, Ripple Custody (Wallet) rejects the transaction immediately and never sends it to approvers.
2. **Approval check** – If a [step-up approval](/products/wallet/governance-and-controls/approvals/step-up-approvals) rule fires, the rule's approvers must authorize the transaction. Otherwise, if your organization configures approval groups for transactions, designated approvers must authorize it. The transaction stays in `POLICY_CHECK_PENDING` while approvers respond. Any `TRAVEL_RULE` rule that applies also requires a Travel Rule exchange before the transfer settles.
3. **MPC signing** – The wallet's MPC quorum signs the transaction.
4. **Blockchain submission** – Ripple Custody (Wallet) publishes the signed transaction to the network.


See [Governance and controls overview](/products/wallet/governance-and-controls) for how policies, approvals, and MPC quorums work together.

### Evaluation order

```mermaid
flowchart TD
    A[Transaction submitted] --> B{Find matching policies}
    B --> C[Policy 1: Check limit]
    B --> D[Policy 2: Check limit]
    B --> E[Policy N: Check limit]

    C --> F{All policies pass?}
    D --> F
    E --> F

    F -->|Yes| G[Proceed to approvals/signing]
    F -->|No| H[Transaction rejected]

    style H fill:#ffcccc
    style G fill:#ccffcc
```

For each wallet and asset, Ripple Custody (Wallet) sorts the enforcing `LIMIT` rules (status `RULE_ENABLED` or `RULE_DELETION_APPROVAL_PENDING`) into two groups:

- **Base rules** have no matchers. They apply to every outgoing transaction for the asset.
- **Scoped rules** have one or more matchers, such as `USER` or `COUNTERPARTY_ID`. A scoped rule applies only when the transaction matches every one of its matchers.


The engine then evaluates the transaction:

1. The engine selects which rules apply:
  - If at least one scoped rule matches the transaction, the scoped rules **replace** the base rules for that transaction, including base rolling and max-total-value rules.
  - If no scoped rule matches, the base rules apply.
  - If no rule applies, the engine rejects the transaction with `PAL006.005`.
2. For each applicable rule, the engine checks whether the transaction would exceed the limit.
3. If **any** applicable rule rejects the transaction, the entire transaction fails.
4. If **all** applicable rules pass, the transaction proceeds to the next stage (approvals or signing).


**Example:** A wallet has a base per-transaction limit of 10 ETH, and a scoped per-transaction limit of 50 ETH for one API credential.

- A 30 ETH transfer from that API credential passes. The scoped rule applies, so the base rule doesn't.
- A 30 ETH transfer from any other initiator fails, because the base rule applies.


### Network fees and policy limits

Ripple Custody (Wallet) checks policy limits against the **transaction amount only** and excludes network fees (gas on EVM chains, transaction fees on XRP Ledger) from the limit calculation. For example, if you have a PER_TX limit of 10 ETH and send exactly 10 ETH, the policy check passes — the gas cost doesn't push the transaction over the limit.

### Operations that bypass policies

Policy checks don't cover all outgoing fund movements. **Asset sweeping bypasses policies entirely.** A wallet doesn't need any policies in place before Ripple Custody (Wallet) can sweep it, and Ripple Custody (Wallet) doesn't evaluate sweep transactions against existing policies.

This means policies alone don't prevent all fund movement from a wallet. If you need to restrict sweeping, manage sweep configurations separately through **Settings > Workflows**. Only owners and administrators can configure sweeping operations.

See [Asset sweeping](/products/wallet/vaults-and-wallets/asset-sweeping) for details on sweep configuration.

Transaction freeze is separate from policies
[Transaction freeze controls](/products/wallet/compliance/transaction-freeze) apply to **inbound** transactions only (holding incoming funds for compliance review). Limit policies apply to **outbound** transactions only. The exception is inbound [Travel Rule](/products/wallet/compliance/travel-rule) policy rules, which can freeze deposits that arrive without an accepted Travel Rule message.

### Matcher evaluation

Matchers filter which transactions a policy applies to. A transaction must match **all** matchers on a policy for that policy to apply. If a policy has no matchers, it applies to **all** transactions for that asset.

Active matcher types include: `TRANSACTION_TYPE`, `USER`, `API_CREDENTIAL`, `SIGN_FOR`, `COUNTERPARTY_ID`, `ALL_COUNTERPARTIES`, `ADDRESS_ID`, `WALLET_ID`, and `CHAIN_ID`. `APPROVAL` rules don't support matchers. Use `COUNTERPARTY_ID` for counterparty destinations. The API rejects the older, deprecated `COUNTERPARTY` matcher.

See [Policy reference](/products/wallet/governance-and-controls/policies/policy-reference#matchers) for detailed matcher documentation and examples.

## Monitoring policy checks with webhooks

If you have webhooks configured for the **TRANSACTION** domain, you receive notifications as transactions move through the policy check stage. The relevant statuses are:

| Status | Description |
|  --- | --- |
| `POLICY_CHECK_PENDING` | Ripple Custody (Wallet) is evaluating the transaction against policies. The transaction also waits here while it collects any required approvals. |
| `POLICY_CHECK_PASSED` | Transaction passed all policy checks and all required approvals. |
| `REJECTED` | A policy or approval rejected the transaction. The transaction's `problems` array carries a `PAL006.xxx` reason code. |


These webhooks allow you to build automated monitoring for policy enforcement — for example, alerting on rejected transactions or tracking policy check latency. Because approvals happen in this stage, `POLICY_CHECK_PENDING` can last for the full approval window rather than milliseconds, so set any latency alerts accordingly. See [Transaction status changes](/products/wallet/changelogs/policy-engine-v2-transaction-status-changes).

No policy lifecycle webhooks
Webhook notifications cover **transaction** status changes only. There are no webhook events for policy creation, approval, or deletion. To track policy lifecycle changes, use the [Approval domain](/products/wallet/integrations-and-monitoring/webhooks/webhook-event-reference#approval-domain) webhooks, which notify you when Ripple Custody (Wallet) creates or resolves approval requests for policy rules.

See [Webhooks overview](/products/wallet/integrations-and-monitoring/webhooks) for setup instructions and payload format.

## Next steps

- **Ready to create a policy?** Follow [Manage policies via the console](/products/wallet/governance-and-controls/policies/manage-policies) or [Manage policy rules via the API](/products/wallet/governance-and-controls/policies/manage-policies-api).
- **Looking up a limit type, matcher, status, permission, or error code?** See [Policy reference](/products/wallet/governance-and-controls/policies/policy-reference).
- **Planning your policies or having issues?** See [Policy best practices](/products/wallet/governance-and-controls/policies/best-practices), including its troubleshooting section.