> ## 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.

> [tab] 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" }
>   }
> }'
> ```

> [tab] 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' },
>   },
> });
> ```

> [tab] 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"] }
>       }
>     }
>   }
> }'
> ```

> [tab] 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.

> [tab] 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" }
>     }
>   ]
> }'
> ```

> [tab] 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

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

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

> [card] [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.

> [card] [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.