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

# Account layer

> Read, add, update, remove, and replace rules on a business account's account layer, as legacy rules or declarative rules.

> [!NOTE]
>
> Wallet and signer policy layers are in **early access**. [Talk to us](https://www.dynamic.xyz/talk-to-us) if you'd like to participate.

Calls on this page go to `/sdk/<environment_id>/...` and authenticate with the signed-in end user's JWT (`<user_jwt>`), not an environment API token. The caller must be a business-account owner or admin. For which kind of rules a layer holds and how declarative rules are enabled, see [Managing layers](https://www.dynamic.xyz/docs/embedded-wallets/mpc/policies/managing-layers.md).

The account layer applies to every wallet in a business account. It is created when you first write to it.

## Read the account-Layer

```bash theme={"system"}
curl "https://app.dynamicauth.com/api/v0/sdk/<environment_id>/businessAccounts/<business_account_id>/policy-layer" \
  -H "Authorization: Bearer <user_jwt>"
```

## Add or update a rule

For a declarative rule, the rule goes in `declarativeRule` instead of `rule`, and `ruleId` is optional: leave it out to create a rule, and the response returns the generated id.

**Legacy rules (cURL)**

```bash theme={"system"}
curl -X PATCH \
"https://app.dynamicauth.com/api/v0/sdk/<environment_id>/businessAccounts/<business_account_id>/policy-layer" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer <user_jwt>" \
-d '{
  "op": "upsert",
  "rule": {
    "name": "Allow USDC on Ethereum mainnet",
    "ruleType": "allow",
    "chain": "EVM",
    "chainIds": [1],
    "addresses": ["0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48"],
    "valueLimit": { "maxPerCall": "100000000000" }
  }
}'
```

**Legacy rules (JavaScript SDK)**

```javascript theme={"system"}
import { createPolicy } from '@dynamic-labs-sdk/client/waas';
import { WaasChainEnum } from '@dynamic-labs/sdk-api-core';

const businessAccountId = '<business_account_id>';

const layer = await createPolicy({
  scope: { businessAccountId },
  chain: WaasChainEnum.Evm,
  chainIds: [1],
  rules: {
    allowAddresses: ['0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48'],
    maxAmountPerTransaction: { amount: '100000000000' },
  },
});
```

**Declarative rules (cURL)**

```bash theme={"system"}
curl -X PATCH \
"https://app.dynamicauth.com/api/v0/sdk/<environment_id>/businessAccounts/<business_account_id>/policy-layer" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer <user_jwt>" \
-d '{
  "op": "upsert",
  "declarativeRule": {
    "ruleId": "00000000-0000-4000-8000-000000000004",
    "name": "Blocked address",
    "phase": "transaction",
    "then": "DENY",
    "when": {
      "exists": {
        "in": "counterparties",
        "where": { "field": "address", "op": "in", "value": ["0x0000000000000000000000000000000000000bad"] }
      }
    }
  }
}'
```

**Declarative rules (JavaScript SDK)**

```javascript theme={"system"}
import { upsertAccountPolicyRule } from '@dynamic-labs-sdk/client/waas';
import {
  WaasPolicyAction,
  WaasPolicyDeclarativeRuleInputPhaseEnum,
} from '@dynamic-labs/sdk-api-core';

const businessAccountId = '<business_account_id>';

const layer = await upsertAccountPolicyRule({
  businessAccountId,
  rule: {
    ruleId: '00000000-0000-4000-8000-000000000004',
    name: 'Blocked address',
    phase: WaasPolicyDeclarativeRuleInputPhaseEnum.Transaction,
    then: WaasPolicyAction.Deny,
    when: {
      exists: {
        in: 'counterparties',
        where: { field: 'address', op: 'in', value: ['0x0000000000000000000000000000000000000bad'] },
      },
    },
  },
});
```

## Remove a rule

```bash theme={"system"}
curl -X PATCH \
"https://app.dynamicauth.com/api/v0/sdk/<environment_id>/businessAccounts/<business_account_id>/policy-layer" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer <user_jwt>" \
-d '{
  "op": "remove",
  "ruleId": "<existing_rule_id>"
}'
```

The same request removes a legacy rule or a declarative rule. In the JavaScript SDK, use `removeAccountPolicyRule({ businessAccountId, ruleId })`.

## Replace the layer's rules

`op: "replace"` sets the layer's full rule list in one write, so any rule you leave out is removed. Keep the `ruleId` of every rule you are keeping. The examples use declarative rules. Only environment admins and business-account admins can replace a layer.

**cURL**

```bash theme={"system"}
curl -X PATCH \
"https://app.dynamicauth.com/api/v0/sdk/<environment_id>/businessAccounts/<business_account_id>/policy-layer" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer <user_jwt>" \
-d '{
  "op": "replace",
  "rules": [
    {
      "ruleId": "00000000-0000-4000-8000-000000000004",
      "name": "Blocked address",
      "phase": "transaction",
      "then": "DENY",
      "when": {
        "exists": {
          "in": "counterparties",
          "where": { "field": "address", "op": "in", "value": ["0x0000000000000000000000000000000000000bad"] }
        }
      }
    },
    {
      "ruleId": "00000000-0000-4000-8000-000000000010",
      "name": "No client signing",
      "phase": "operation",
      "then": "DENY",
      "when": { "field": "operation.type", "op": "eq", "value": "clientSigning" }
    }
  ]
}'
```

**JavaScript SDK**

```javascript theme={"system"}
import { replacePolicyLayerRules } from '@dynamic-labs-sdk/client/waas';
import {
  WaasPolicyAction,
  WaasPolicyDeclarativeRuleInputPhaseEnum,
} from '@dynamic-labs/sdk-api-core';

const businessAccountId = '<business_account_id>';

const layer = await replacePolicyLayerRules({
  scope: { businessAccountId },
  rules: [
    {
      ruleId: '00000000-0000-4000-8000-000000000004',
      name: 'Blocked address',
      phase: WaasPolicyDeclarativeRuleInputPhaseEnum.Transaction,
      then: WaasPolicyAction.Deny,
      when: {
        exists: {
          in: 'counterparties',
          where: { field: 'address', op: 'in', value: ['0x0000000000000000000000000000000000000bad'] },
        },
      },
    },
    {
      ruleId: '00000000-0000-4000-8000-000000000010',
      name: 'No client signing',
      phase: WaasPolicyDeclarativeRuleInputPhaseEnum.Operation,
      then: WaasPolicyAction.Deny,
      when: { field: 'operation.type', op: 'eq', value: 'clientSigning' },
    },
  ],
});
```

## Next steps

> **[Wallet layer](https://www.dynamic.xyz/docs/embedded-wallets/mpc/policies/wallet-layer.md)**
>
> Rules that apply to a single wallet.

> **[Signer layer](https://www.dynamic.xyz/docs/embedded-wallets/mpc/policies/signer-layer.md)**
>
> Rules that apply to a single signer share set.

> **[Managing layers](https://www.dynamic.xyz/docs/embedded-wallets/mpc/policies/managing-layers.md)**
>
> Auth, which kind of rules a layer holds, and signer-modifiable rules.

> **[Rule examples](https://www.dynamic.xyz/docs/embedded-wallets/mpc/policies/rule-examples.md)**
>
> Ready-made declarative rules.


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