# Policy examples

Use this page for reusable policy patterns and complete `v0_CreatePolicy` examples. For the concepts, see [Policies](/products/custody/v1.36/governance/policies). For launch design, see [Design your policies](/products/custody/v1.36/governance/genesis/design-your-policies). For field rules and JavaScript guidance, see [Policy reference](/products/custody/v1.36/governance/policies/reference).

The examples use representative roles, domains, ledgers, thresholds, and UUIDs. Before publication or deployment, validate the payloads against your live environment, especially account, endpoint, ledger, and custom property paths.

## Catalog

| Pattern | Type | Goal | Intent types | Condition | Workflow | When to use |
|  --- | --- | --- | --- | --- | --- | --- |
| Maker-checker | Approval pattern | Require independent review. | Any sensitive intent type. | Usually author role or target operation. | Maker role first, checker role second. | Routine operations that need a second human review. |
| Quorum | Approval pattern | Require multiple approvals from one role. | Lock, unlock, policy, domain, recovery. | Usually broad or high-risk. | `RoleQuorum` with quorum greater than 1. | Sensitive actions controlled by one team. |
| Multi-step approval | Approval pattern | Escalate approval in sequence. | Transfers, policy changes, high-risk administration. | Amount, risk, domain, operation type. | Ordered workflow steps. | Later approvers should only act after earlier review. |
| And approval | Approval pattern | Require multiple groups in one step. | Transfers, exceptions, compliance, policy changes. | Any business condition. | `And` with `left` and `right`. | Two teams must both approve. |
| Or approval | Approval pattern | Allow alternative approver groups. | Transfers, operational routing, backup operations. | Any business condition. | `Or` with `left` and `right`. | Human or bot, regional alternatives, backup approvers. |
| Amount threshold | Condition pattern | Change approval by value. | `v0_CreateTransactionOrder`. | `BigInt(...)` amount comparison. | Tiered approval. | High-value outgoing transfers. |
| Trusted endpoint | Condition pattern | Treat known destinations differently. | `v0_CreateTransactionOrder`. | Destination is endpoint and trust score is high enough. | Lower or automated maker workflow. | Trusted address workflows. |
| System-signed service proposal | Automation pattern | Allow a service caller to submit a narrow set of API proposals without a client-side payload signature. | Usually `v0_CreateTransactionOrder`, `v0_CreateTransferOrder`, or another explicitly selected type. | Service submitter role or subject. | Null workflow for deliberate auto-approval, or user approval workflow. | API-only automation where the deployment supports system-signed intents. |
| Smart contract endpoint | Condition pattern | Escalate smart contract endpoint creation. | `v0_CreateEndpoint`. | Endpoint parameters exist. | System operator plus compliance. | Contract addresses require extra review. |
| User management | Operation policy | Govern user lifecycle changes. | `v0_CreateUser`, `v0_UpdateUser`, `v0_LockUser`, `v0_UnlockUser`. | Requester role or target role assignment. | User admin, security, compliance. | Creating users or changing user role assignments. |
| Policy management | Operation policy | Govern policy lifecycle changes. | `v0_CreatePolicy`, `v0_UpdatePolicy`, `v0_LockPolicy`, `v0_UnlockPolicy`. | Policy operator author role. | Policy operator plus compliance. | Any change to governance rules. |
| Account management | Operation policy | Govern account lifecycle changes. | `v0_CreateAccount`, `v0_UpdateAccount`, `v0_LockAccount`, `v0_UnlockAccount`. | System operator author role. | System operator plus compliance. | Account setup and maintenance. |
| Quarantine release | Operation policy | Govern release of quarantined funds. | `v0_ReleaseQuarantinedTransfers`. | Compliance or system operator role. | Compliance quorum. | AML and screening workflows. |
| Fallback | Operation policy | Catch unmatched legitimate workflows. | Omit `intentTypes` intentionally. | Maker role or true fallback condition. | Low-rank, high-control workflow. | Exceptions not handled by specific policies. |


## User management

Use this policy for user creation, user role-assignment changes, locking, and unlocking.


```json
{
  "id": "8925d558-d8d7-47d6-b789-92c49d6d66f6",
  "alias": "user-management",
  "rank": 300,
  "scope": "SelfAndDescendants",
  "intentTypes": [
    "v0_CreateUser",
    "v0_UpdateUser",
    "v0_LockUser",
    "v0_UnlockUser"
  ],
  "scriptingEngine": "Javascript_v0",
  "condition": {
    "expression": "context.references.users[context.request.author.id].roles.includes('system-operator')",
    "type": "Expression"
  },
  "workflow": [
    {
      "role": "system-operator",
      "quorum": 2,
      "type": "RoleQuorum"
    }
  ],
  "lock": "Unlocked",
  "description": "Controls user lifecycle operations.",
  "customProperties": {},
  "type": "v0_CreatePolicy"
}
```

## Account management

Use this policy for account creation, account updates, locking, and unlocking.


```json
{
  "id": "a13678a6-5f8c-4f85-8657-27f58933bffc",
  "alias": "account-management",
  "rank": 320,
  "scope": "SelfAndDescendants",
  "intentTypes": [
    "v0_CreateAccount",
    "v0_UpdateAccount",
    "v0_LockAccount",
    "v0_UnlockAccount"
  ],
  "scriptingEngine": "Javascript_v0",
  "condition": {
    "expression": "context.references.users[context.request.author.id].roles.includes('system-operator')",
    "type": "Expression"
  },
  "workflow": [
    {
      "left": {
        "role": "system-operator",
        "quorum": 2,
        "type": "RoleQuorum"
      },
      "right": {
        "role": "compliance",
        "quorum": 1,
        "type": "RoleQuorum"
      },
      "type": "And"
    }
  ],
  "lock": "Unlocked",
  "description": "Controls account lifecycle operations.",
  "customProperties": {},
  "type": "v0_CreatePolicy"
}
```

## Endpoint management


```json
{
  "id": "18b187ad-9d2e-4e84-9ce8-0063bfe8d8da",
  "alias": "endpoint-management",
  "rank": 300,
  "scope": "SelfAndDescendants",
  "intentTypes": [
    "v0_CreateEndpoint",
    "v0_UpdateEndpoint",
    "v0_LockEndpoint",
    "v0_UnlockEndpoint"
  ],
  "scriptingEngine": "Javascript_v0",
  "condition": {
    "expression": "context.references.users[context.request.author.id].roles.includes('system-operator')",
    "type": "Expression"
  },
  "workflow": [
    {
      "role": "system-operator",
      "quorum": 2,
      "type": "RoleQuorum"
    }
  ],
  "lock": "Unlocked",
  "description": "Controls endpoint lifecycle operations.",
  "customProperties": {},
  "type": "v0_CreatePolicy"
}
```

## Smart contract endpoint escalation

Use this higher-rank policy to catch smart contract endpoint creation before the generic endpoint-management policy.


```json
{
  "id": "ba4d7753-2756-4080-8d7b-9f6699f70ada",
  "alias": "smart-contract-endpoint",
  "rank": 450,
  "scope": "SelfAndDescendants",
  "intentTypes": ["v0_CreateEndpoint"],
  "scriptingEngine": "Javascript_v0",
  "condition": {
    "expression": "context.references.users[context.request.author.id].roles.includes('system-operator') && context.request.payload.hasOwnProperty('parameters') && context.request.payload.parameters != null",
    "type": "Expression"
  },
  "workflow": [
    {
      "role": "system-operator",
      "quorum": 2,
      "type": "RoleQuorum"
    },
    {
      "role": "compliance",
      "quorum": 1,
      "type": "RoleQuorum"
    }
  ],
  "lock": "Unlocked",
  "description": "Escalates smart contract endpoint creation.",
  "customProperties": {},
  "type": "v0_CreatePolicy"
}
```

## Policy management

Use this policy to govern creation, update, lock, and unlock operations for other policies.


```json
{
  "id": "5b440ba5-d013-11eb-8cd0-dcfb48cfb3cb",
  "alias": "policy-governance",
  "rank": 700,
  "scope": "Self",
  "intentTypes": [
    "v0_CreatePolicy",
    "v0_UpdatePolicy",
    "v0_LockPolicy",
    "v0_UnlockPolicy"
  ],
  "scriptingEngine": "Javascript_v0",
  "condition": {
    "expression": "context.references.users[context.request.author.id].roles.includes('policy-operator')",
    "type": "Expression"
  },
  "workflow": [
    {
      "left": {
        "role": "policy-operator",
        "quorum": 2,
        "type": "RoleQuorum"
      },
      "right": {
        "role": "compliance",
        "quorum": 2,
        "type": "RoleQuorum"
      },
      "type": "And"
    }
  ],
  "lock": "Unlocked",
  "description": "Controls policy lifecycle operations.",
  "customProperties": {},
  "type": "v0_CreatePolicy"
}
```

## Unknown address transfer

Use this policy to escalate outgoing transaction orders to an unknown address. The condition checks that the destination field exists before reading it.


```json
{
  "id": "074fb6c8-f433-4f76-95f0-e01934486b73",
  "alias": "unknown-address-transfer",
  "rank": 420,
  "scope": "Self",
  "intentTypes": ["v0_CreateTransactionOrder"],
  "scriptingEngine": "Javascript_v0",
  "condition": {
    "expression": "context.references.users[context.request.author.id].roles.includes('transaction-operator') && context.request.payload.hasOwnProperty('parameters') && context.request.payload.parameters != null && context.request.payload.parameters.hasOwnProperty('destination') && context.request.payload.parameters.destination.type == 'Address'",
    "type": "Expression"
  },
  "workflow": [
    {
      "left": {
        "role": "transaction-operator",
        "quorum": 2,
        "type": "RoleQuorum"
      },
      "right": {
        "role": "compliance",
        "quorum": 2,
        "type": "RoleQuorum"
      },
      "type": "And"
    }
  ],
  "lock": "Unlocked",
  "description": "Escalates outgoing transfers to unknown addresses.",
  "customProperties": {},
  "type": "v0_CreatePolicy"
}
```

## Trusted endpoint transfer

Use this policy for trusted endpoint destinations. Keep the rank lower than high-risk transfer policies so thresholds and compliance overrides can still win.


```json
{
  "id": "db8c31d5-26e6-4c46-8643-1cbe03019a1a",
  "alias": "trusted-endpoint-transfer",
  "rank": 250,
  "scope": "Self",
  "intentTypes": ["v0_CreateTransactionOrder"],
  "scriptingEngine": "Javascript_v0",
  "condition": {
    "expression": "(context.references.users[context.request.author.id].roles.includes('transaction-operator') || context.references.users[context.request.author.id].roles.includes('transaction-operator-bot')) && context.request.payload.hasOwnProperty('parameters') && context.request.payload.parameters != null && context.request.payload.parameters.hasOwnProperty('destination') && context.request.payload.parameters.destination.type == 'Endpoint' && context.references.endpoints[context.request.payload.parameters.destination.endpointId].trustScore >= 75",
    "type": "Expression"
  },
  "workflow": [
    {
      "left": {
        "role": "transaction-operator",
        "quorum": 1,
        "type": "RoleQuorum"
      },
      "right": {
        "role": "transaction-operator-bot",
        "quorum": 1,
        "type": "RoleQuorum"
      },
      "type": "Or"
    },
    {
      "left": {
        "role": "transaction-operator",
        "quorum": 1,
        "type": "RoleQuorum"
      },
      "right": {
        "role": "transaction-operator-bot",
        "quorum": 1,
        "type": "RoleQuorum"
      },
      "type": "Or"
    }
  ],
  "lock": "Unlocked",
  "description": "Allows trusted endpoint transfer workflow.",
  "customProperties": {},
  "type": "v0_CreatePolicy"
}
```

## System-signed Gas Station proposal

Use this pattern when a service caller should submit a narrow set of API proposals without managing a user private key. This example allows service callers whose token includes the `gas-station` custody role to submit transaction order proposals. The policy does not match user-signed proposals.


```json
{
  "id": "af1d2e33-9a94-4456-bcb3-895bba820d38",
  "alias": "gas-station-system-signed",
  "rank": 420,
  "scope": "SelfAndDescendants",
  "intentTypes": ["v0_CreateTransactionOrder"],
  "intentOrigin": "SystemSigned",
  "scriptingEngine": "Javascript_v0",
  "condition": {
    "expression": "submitter.type === 'Service' && submitter.custodyRoles.includes('gas-station')",
    "type": "Expression"
  },
  "lock": "Unlocked",
  "description": "Allows Gas Station service-submitted transaction orders.",
  "customProperties": {},
  "type": "v0_CreatePolicy"
}
```

Omit `workflow` only when automatic execution is intentional. If the policy includes a workflow, user-signed approvers complete the approval steps.

## Large Ethereum transfer

Use this policy to require compliance approval for Ethereum transaction orders above 5 ETH.


```json
{
  "id": "0efa137d-5f59-4d3e-b720-06185c48ebbe",
  "alias": "large-ethereum-transfer",
  "rank": 500,
  "scope": "Self",
  "intentTypes": ["v0_CreateTransactionOrder"],
  "scriptingEngine": "Javascript_v0",
  "condition": {
    "expression": "context.references.users[context.request.author.id].roles.includes('transaction-operator') && context.references.accounts[context.request.payload.accountId].ledgerId == 'ethereum-testnet' && context.request.payload.hasOwnProperty('parameters') && context.request.payload.parameters != null && context.request.payload.parameters.hasOwnProperty('amount') && BigInt(context.request.payload.parameters.amount) >= 5000000000000000000n",
    "type": "Expression"
  },
  "workflow": [
    {
      "left": {
        "role": "transaction-operator",
        "quorum": 1,
        "type": "RoleQuorum"
      },
      "right": {
        "role": "compliance",
        "quorum": 2,
        "type": "RoleQuorum"
      },
      "type": "And"
    }
  ],
  "lock": "Unlocked",
  "description": "Escalates Ethereum transfers above 5 ETH.",
  "customProperties": {},
  "type": "v0_CreatePolicy"
}
```

## Large Bitcoin transfer

Use this policy to sum Bitcoin outputs and require compliance approval above 5 BTC.


```json
{
  "id": "4e9cc80b-e4d7-4be8-9940-a1eb0b2e1484",
  "alias": "large-bitcoin-transfer",
  "rank": 500,
  "scope": "Self",
  "intentTypes": ["v0_CreateTransactionOrder"],
  "scriptingEngine": "Javascript_v0",
  "condition": {
    "expression": "context.references.users[context.request.author.id].roles.includes('transaction-operator') && context.references.accounts[context.request.payload.accountId].ledgerId == 'bitcoin-testnet' && context.request.payload.hasOwnProperty('parameters') && context.request.payload.parameters != null && context.request.payload.parameters.hasOwnProperty('outputs') && context.request.payload.parameters.outputs.reduce((sum, output) => sum + BigInt(output.amount), 0n) >= 500000000n",
    "type": "Expression"
  },
  "workflow": [
    {
      "left": {
        "role": "transaction-operator",
        "quorum": 1,
        "type": "RoleQuorum"
      },
      "right": {
        "role": "compliance",
        "quorum": 2,
        "type": "RoleQuorum"
      },
      "type": "And"
    }
  ],
  "lock": "Unlocked",
  "description": "Escalates Bitcoin transfers above 5 BTC.",
  "customProperties": {},
  "type": "v0_CreatePolicy"
}
```

## Quarantine release

Use this policy for incoming funds that must stay quarantined until compliance releases them.


```json
{
  "id": "2431fbf2-69c1-4d74-b99a-a7ebf7bf5097",
  "alias": "quarantine-release",
  "rank": 400,
  "scope": "SelfAndDescendants",
  "intentTypes": ["v0_ReleaseQuarantinedTransfers"],
  "scriptingEngine": "Javascript_v0",
  "condition": {
    "expression": "context.references.users[context.request.author.id].roles.includes('system-operator')",
    "type": "Expression"
  },
  "workflow": [
    {
      "left": {
        "role": "system-operator",
        "quorum": 1,
        "type": "RoleQuorum"
      },
      "right": {
        "role": "compliance",
        "quorum": 1,
        "type": "RoleQuorum"
      },
      "type": "And"
    }
  ],
  "lock": "Unlocked",
  "description": "Requires compliance approval for quarantine release.",
  "customProperties": {},
  "type": "v0_CreatePolicy"
}
```

## Catch-all fallback

Use fallback policies with low rank and strong approval. They should catch exceptions, not replace specific policies. This example intentionally omits `intentTypes` so it can match any intent type after more specific policies fail to match.


```json
{
  "id": "ed6a0b68-d18c-4d14-8ad6-0e9e595fa0d6",
  "alias": "fallback-governance",
  "rank": 10,
  "scope": "SelfAndDescendants",
  "scriptingEngine": "Javascript_v0",
  "condition": {
    "expression": "context.references.users[context.request.author.id].roles.includes('system-operator') || context.references.users[context.request.author.id].roles.includes('policy-operator') || context.references.users[context.request.author.id].roles.includes('transaction-operator')",
    "type": "Expression"
  },
  "workflow": [
    {
      "left": {
        "left": {
          "role": "system-operator",
          "quorum": 1,
          "type": "RoleQuorum"
        },
        "right": {
          "role": "policy-operator",
          "quorum": 1,
          "type": "RoleQuorum"
        },
        "type": "Or"
      },
      "right": {
        "role": "transaction-operator",
        "quorum": 1,
        "type": "RoleQuorum"
      },
      "type": "Or"
    },
    {
      "role": "compliance",
      "quorum": 2,
      "type": "RoleQuorum"
    }
  ],
  "lock": "Unlocked",
  "description": "Low-rank fallback for unexpected governed workflows.",
  "customProperties": {},
  "type": "v0_CreatePolicy"
}
```