Policy Engine v2 adds typed policy rules. Each 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. | Outbound |
TRAVEL_RULE | Requires a Travel Rule data exchange with the counterparty before a transfer settles. See Travel Rule. | Outbound and inbound |
Your existing wallet limits are LIMIT rules. They keep working, and the policy rules API returns them as LIMIT rules.
Typed policy rules are available only in organizations where Ripple has turned on Policy Engine v2. APPROVAL and TRAVEL_RULE rules also need Ripple to turn them on for your organization. The policy rules API on this page is in preview, and the published API reference doesn't include it yet. To turn on these features, contact your Ripple representative.
- Only
LIMITrules let a wallet send. A wallet can only receive an asset until it has an applicableLIMITrule for that asset.APPROVALandTRAVEL_RULErules never let a transaction through on their own. If noLIMITrule applies, Wallet-as-a-Service rejects the transaction withPAL006.005. - Rule kinds don't override each other. A transaction must pass its applicable
LIMITrules, and then meet anyAPPROVALandTRAVEL_RULErequirements that apply to it. - A blocked transaction never reaches approvers. If a
LIMITrule blocks the transaction, Wallet-as-a-Service rejects it before it creates any approval request.
For each wallet and asset, Wallet-as-a-Service sorts LIMIT rules 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
USERorCOUNTERPARTY_ID. A scoped rule applies only when the transaction matches every one of its matchers.
If at least one scoped rule applies to a transaction, the scoped rules replace the base rules for that transaction, including base rolling and lifetime limits. If no scoped rule applies, the base rules apply. The transaction must pass every rule in the selected group.
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.
Open the wallet and go to the Policy tab.
Select Add a new rule.
On the Direction step, select Outbound for transfers from this wallet, or Inbound for deposits into this wallet. Only Travel Rule rules support Inbound. Select Next.

On the Conditions step, select the asset, and then select the rule under Rule:
- Limit: Select Max total value, Rolling, or Per transaction, and enter the Value limit. For Rolling, select a Duration: 1 hour, 1 day, 1 week, 2 weeks, or 1 month.
- Approval: See Step-up approvals.
- Travel rule: See Set up Travel Rule.

On the Scope step, select the destinations the rule applies to. You can also narrow the rule by Sign for address and Transaction types. To apply the rule to every destination, leave the selection empty.

On the Advanced step, leave All selected, or restrict the rule to one User or API credential.
On the Confirm step, review the rule, and then select Add policy rule.

If your organization has a Policy rules approval group, the rule shows Inactive | Approval pending until approvers approve it. Approvers find the request under Notifications > Approvals.

After approval, the rule shows Active | Enabled on the Policy tab.

POST /v2/vaults/{vaultId}/wallets/{walletId}/policy-rulesYour API credential needs the policy:create permission at organization, vault, or wallet scope. See Permissions.
| Field | Type | Required | Description |
|---|---|---|---|
trigger | string | Yes | OUTBOUND_INITIATED for transactions the wallet sends, or INBOUND_DETECTED for deposits into the wallet. Only TRAVEL_RULE rules support INBOUND_DETECTED. |
assetId | string | Conditional | The asset's registry ID. LIMIT and APPROVAL rules require it. To apply a TRAVEL_RULE rule with no amount condition to all assets, leave it out. The asset's blockchain must match the wallet's blockchain. |
matchers | array | No | Filters that narrow which transactions the rule applies to. See Matchers. |
definition | object | Yes | The rule kind and its settings. Set definition.kind to LIMIT, APPROVAL, or TRAVEL_RULE, and include only the matching object: limit, approval, or travelRule. |
Registry IDs look like 3::XRP. To find an asset's registry ID, list assets from the registry. For example, to find a native asset, filter by blockchain and standard:
GET /v2/registry/assets?filter.blockchain.eq=<blockchain>&filter.standard.eq=NATIVELIMIT, APPROVAL, and TRAVEL_RULE rules use the same amount object:
| Field | Type | Description |
|---|---|---|
threshold | string | Decimal amount in the asset's units, for example "10000" or "0.5". "0" is valid. |
operator | string | GT (greater than). The schema also lists GTE, but Wallet-as-a-Service doesn't support it yet and rejects it. |
aggregation | string | SINGLE_TX compares each transaction on its own. ROLLING compares the total the wallet sent during the duration window. TOTAL compares the total the wallet ever sent. |
duration | string | The window length in seconds, for example "86400s" for 24 hours. Must be less than one year. Use it only with ROLLING, which requires it. |
| Kind | Supported aggregation values |
|---|---|
LIMIT | SINGLE_TX, ROLLING, TOTAL |
APPROVAL | SINGLE_TX |
TRAVEL_RULE | SINGLE_TX |
This rule caps payments to any counterparty at 10,000 of the asset in a rolling 24-hour window:
{
"trigger": "OUTBOUND_INITIATED",
"assetId": "3::XRP",
"matchers": [
{ "type": "ALL_COUNTERPARTIES", "values": [] }
],
"definition": {
"kind": "LIMIT",
"limit": {
"amount": {
"threshold": "10000",
"operator": "GT",
"aggregation": "ROLLING",
"duration": "86400s"
}
}
}
}For APPROVAL and TRAVEL_RULE examples, see Step-up approvals and Set up Travel Rule.
The API returns the new rule. The rule goes through your organization's Policy rules approval flow, so it usually has status RULE_CREATION_APPROVAL_PENDING and active: false.
{
"id": "0199a1c2-5d3e-7a10-9b2f-4c8e1d6f0a21",
"vaultId": "019be892-2834-7435-be18-bc13ac4c73ce",
"walletId": "019bec51-ab18-7284-907a-dd7747277116",
"createdBy": "8617b5b5-dfcf-4ffc-9f46-f7cec35a88bd",
"trigger": "OUTBOUND_INITIATED",
"assetId": "3::XRP",
"matchers": [
{ "type": "ALL_COUNTERPARTIES", "value": "", "values": [] }
],
"status": "RULE_CREATION_APPROVAL_PENDING",
"active": false,
"createdAt": "2026-09-24T12:00:00Z",
"updatedAt": "2026-09-24T12:00:00Z",
"definition": {
"kind": "LIMIT",
"limit": {
"amount": {
"threshold": "10000",
"operator": "GT",
"aggregation": "ROLLING",
"duration": "86400s"
}
}
}
}| Operation | Method and path | Permission |
|---|---|---|
| List rules | GET /v2/vaults/{vaultId}/wallets/{walletId}/policy-rules or POST …/policy-rules:list | policy:read |
| Get a rule | GET /v2/vaults/{vaultId}/wallets/{walletId}/policy-rules/{id} | policy:read |
| Delete a rule | DELETE /v2/vaults/{vaultId}/wallets/{walletId}/policy-rules/{id} | policy:delete |
- List supports
pageSize(default 50, maximum 1,000) andpageToken. You can filter bykind,trigger,assetId,status,active,createdAt, andupdatedAt. - No update operation. To change a rule, create the new rule first, and then delete the old one. This order keeps the wallet protected throughout the change.
- Wallet scope. A rule belongs to one wallet. If you request a rule ID under a different wallet, the API returns not found.
The existing /v2/vaults/{vaultId}/wallets/{walletId}/policy-rules/limits endpoints keep working, and use the keylimit:* permissions. See Manage policies.
Matchers use the same types as wallet limits. See Policy reference. In the policy rules API:
- Send each matcher as
{ "type": "...", "values": ["..."] }. Don't use the older singlevaluestring, which Ripple has deprecated. - Include each matcher type at most once, with up to 100 values. A transaction must match every matcher, and any one value in each matcher.
- The API rejects the deprecated
COUNTERPARTYtype. UseCOUNTERPARTY_IDinstead. ALL_COUNTERPARTIEStakes no values. It matches only destinations that resolve to a counterparty. To apply a rule to any destination, leave out destination matchers.APPROVALrules don't support matchers.
| Status | Enforcing | Description |
|---|---|---|
RULE_CREATION_APPROVAL_PENDING | No | The rule is waiting for approvers to approve it. |
RULE_ENABLED | Yes | The rule is active. |
RULE_REJECTED | No | Approvers rejected the rule. This status is final. |
RULE_DELETION_APPROVAL_PENDING | Yes | The rule is waiting for approvers to approve its deletion, and keeps enforcing until they do. If approvers reject the deletion, the rule returns to RULE_ENABLED. |
RULE_DELETED | No | Approvers approved the deletion. This status is final. |
RULE_ERROR | No | Wallet-as-a-Service couldn't process the rule. Delete the rule and create it again, or contact Ripple Support. |
A rule also passes through the short-lived statuses RULE_CREATED, RULE_CREATION_APPROVAL_COMPLETE, and RULE_DELETION_APPROVAL_COMPLETE. The active field is true only for RULE_ENABLED and RULE_DELETION_APPROVAL_PENDING.
The policy rules API uses the policy permission family, which is separate from keylimit. A keylimit permission doesn't give access to the policy rules API, and a policy permission doesn't give access to the /policy-rules/limits endpoints.
| Permission | Lets the credential |
|---|---|
policy:create | Create rules |
policy:read | List and get rules |
policy:delete | Delete rules |
When you create an API credential, you can grant each permission at organization, vault, or wallet scope. In the console, owners and administrators can create and delete rules. Approvers, auditors, proposers, and support users can view rules.
| Code | Message | Cause |
|---|---|---|
PAL006.038 | this policy rule type cannot be created yet | Ripple hasn't turned on this rule kind for your organization. |
PAL006.039 | an equivalent policy rule already exists | The wallet already has a rule with the same kind, trigger, asset, matchers, and amount. |
PAL006.040 | (varies) | The rule is invalid. The message names the problem, for example amount operator GTE is not yet supported. |
PAL006.041 | (varies) | The rule doesn't exist on this wallet. |
PAL006.046 | travel-rule policy rules require a configured travel-rule connection | You tried to create a TRAVEL_RULE rule before you connected Notabene. |
PAL006.048 | (varies) | You tried to create an APPROVAL rule on a wallet that has compliance screening integrations turned on. |
For transaction rejection codes, see Policy Engine v2: transaction status changes.