# Wallets

Source: https://docs.settlemint.com/docs/console/participants/restrict-a-wallet
Freeze a wallet on every token it holds here where you are Custodian, record why, and lift the restriction when the review or order ends.

A wallet restriction freezes one wallet, in one request, on every token it holds in this organisation where you hold the **Custodian** role, and stores the reason. A freeze stops the wallet from sending and receiving that token, and the balance stays where it is, except that a holder of the "Custodian" role can still move it with a forced transfer. Use a restriction when a review or an order requires a wallet to stop on the organisation's tokens, for example an anti-money-laundering (AML) review, a sanctions match or a court order.

Without a restriction you freeze the address on each token separately, from that token's **Blocklist** tab. That takes one submission per token, and a token you miss stays open to the wallet. A restriction sends all the freezes in one request with one reason, and keeps one record of the outcome on each token. One lift then releases every freeze it applied. A restriction is reversible, and neither the restriction nor the lift moves or removes tokens. [Controls that stop movement](#controls-that-stop-movement) compares it with the other controls.

![Restrict wallet sheet over a participant's Wallets tab, with the Reason picker, the Note field and the Review button](https://docs.settlemint.com/docs/screenshots/console-participant-wallet-restrict.light.en.webp)

[Screenshot] The "Restrict wallet" sheet names the wallet and warns that it "will be frozen on every token it holds in this organisation".

Its "Details" step holds a required "Reason" picker and a "Note" field with a 500-character counter. "Review" stays off until you choose a reason and, for "Other", add a note.

## Before you start [#before-you-start]

- **The Custodian role on each token.** The "Custodian" role is granted per token, from the token's own page, and the Owner role does not include it. The platform checks the role token by token: it freezes the wallet on every token where you hold the "Custodian" role and reports each other token as failed, with a code, a message and a fix. If you hold the role on none of the wallet's tokens, the Console refuses the request. [Roles and duties](https://docs.settlemint.com/docs/concepts/compliance-and-identity/roles-and-segregation-of-duties#asset-roles) lists what the role permits.
- **Who restricts in the Console.** The Console offers the restriction actions to the organisation's owner, and only the owner and platform administrators can list or read restrictions. The "Wallets" tab sits on the user's page, which also needs the "System manager", "Identity manager" or "Verification issuer" role. Any other member who holds the "Custodian" role, a compliance officer included, restricts and lifts through the Platform API or the CLI and keeps the restriction id from the first response. [API routes](#api-routes) shows the calls. Ask the owner for the list of active restrictions.
- **Your wallet verification.** The Console asks for your transaction PIN or transaction code before it sends the change. A request made with an [API key](https://docs.settlemint.com/docs/console/my-account/api-keys) skips that check.
- **The reason and the note.** A wallet has one active restriction at a time and its reason cannot change, so decide both before you start. To record a different reason later and keep the wallet stopped meanwhile, add its address to the address block list first, then lift and restrict again.
- **The network.** A restriction covers the tokens of one network, so select the network first if your organisation uses more than one.
- **The tokens it covers.** A restriction freezes the tokens the wallet holds when you run it. To also stop tokens it receives later, add its address to the address block list in [Global controls](https://docs.settlemint.com/docs/console/compliance/global-controls) as well. [Controls that stop movement](#controls-that-stop-movement) compares the four controls.

## Steps [#steps]

The Console restricts the wallet on every token it holds in the organisation. To restrict a listed set of tokens, use the Platform API or the CLI.

### Open the wallet [#open-the-wallet]

Open the user's page and select the **Wallets** tab. If you do not see it, open "More": a user's page with more than seven tabs moves one of them there. Each wallet the participant owns offers "Restrict wallet". Pick the wallet that holds the tokens: a participant can own more than one wallet, and a restriction covers only the one you pick.

### Choose the reason [#choose-the-reason]

Select "Restrict wallet" and choose the **Reason** that fits the review or order. [Reason codes](#reason-codes) lists the seven reasons. Add a "Note" of up to 500 characters when a colleague needs context to lift the restriction later, such as a case reference. "Review" stays unavailable until you choose a reason and, for "Other", add a note. The platform stores the reason and the note with the restriction and with every freeze it sends.

### Confirm with wallet verification [#confirm-with-wallet-verification]

Review the summary and enter your transaction PIN or transaction code. The platform sends one freeze for each token where you hold the "Custodian" role, and it waits for each freeze to settle on the chain before it shows the result.

### Read the result for each token [#read-the-result-for-each-token]

The Console shows **Restriction result** with the counts "Frozen", "Already frozen", "Queued", "Failed" and "Lifted", and lists every token under "Tokens" with its outcome. [Token statuses](#token-statuses) explains each outcome and what to do next. A failed token shows the code, message and fix the platform recorded.

The wallet card shows a badge that reads "Restricted: " and the reason, such as "Restricted: AML review". The badge shows whenever the wallet has an active restriction, whatever each token's outcome, so the wallet is stopped only on the tokens that read "Frozen" or "Already frozen".

## Apply a restriction again [#apply-a-restriction-again]

Select **Apply again** on the wallet card of a restricted wallet and confirm with your wallet verification. The Console sends the same reason and note for every token the wallet holds. The platform freezes the tokens the restriction does not cover yet, retries each freeze that failed, and resumes each freeze that was accepted but has not settled. Use it for a token the wallet acquired after the restriction, a "Freeze failed" token or a token that stays "Queued". For a restriction created with a list of tokens, call the Platform API or the CLI, as [API routes](#api-routes) shows.

A paused token is frozen like any other. The result flags it as `paused`, and the freeze holds when transfers resume.

## Lift a restriction [#lift-a-restriction]

Open the participant's **Wallets** tab again. A restricted wallet shows the "Restricted: " badge with its reason, and the card offers "Apply again" beside "Lift restriction". Select "Lift restriction" and confirm with your wallet verification, or select "Keep wallet restricted" to stop. The Console then lists every token with its outcome, as it did when you restricted the wallet.

The lift needs the **Custodian** role on at least one token of the restriction. Without it, the lift is refused as if the restriction did not exist, even when no token has an unfreeze left to send. The lift first sends any freeze still pending and waits for every queued freeze to settle, so a freeze that lands late cannot outlast the lift. It then unfreezes each token that shows "Frozen", which needs the "Custodian" role on that token. Two outcomes stay in place:

- A token that showed `already-frozen` stays frozen, because the wallet was frozen there before the restriction. Once the "Restricted: " badge is gone from the wallet card, you can release it with **Unblock** on that token's "Blocklist" tab.
- A token that showed `failed` has nothing to undo and does not hold the lift back.

The restriction's status turns to lifted once every freeze it applied is removed. If an unfreeze fails, the restriction stays active and the token shows "Lift failed" with the cause. If a freeze on a token where you hold the "Custodian" role is still settling after the lift waits for it, the lift sends no unfreeze, the restriction stays active and the token keeps "Queued". Apply the fix, or wait for the transaction to settle, and lift again: the platform sends only the unfreezes that are still missing.

While the restriction is active, the wallet cannot be released one token at a time. **Unblock** on the "Blocklist" tab of any token the restriction lists is refused before the PIN, and the Platform API answers an address unfreeze for that token with 409 `TOKEN_ADDRESS_RESTRICTION_ACTIVE`, naming the restriction. Lift the restriction to release the wallet. "Block" still works.

## Reason codes [#reason-codes]

The reason is a code and a note. The code is a label for your records and for filtering restrictions, and it does not change what the freeze does. The note is free text of 1 to 500 characters. It is optional for every code except `other`, which needs one.

| In the Console | Code | Use it when |
| --- | --- | --- |
| **AML review** | `aml-review` | An anti-money-laundering review of the wallet is open. |
| **Sanctions screening** | `sanctions-screening` | The wallet matched a sanctions list, or screening of it is not finished. |
| **Fraud investigation** | `fraud-investigation` | The wallet is part of a fraud investigation. |
| **Court order** | `court-order` | A court order requires the freeze. |
| **Regulatory request** | `regulatory-request` | A regulator asked for the freeze. |
| **Client request** | `client-request` | The owner of the wallet asked for the freeze. |
| **Other** | `other` | No other code fits. Describe the reason in the note. |

The single-token freeze calls accept the same optional `reason`, with the same codes and note limit. [Pause and freeze](https://docs.settlemint.com/docs/console/asset-management/manage/pause-freeze) names them.

## Token statuses [#token-statuses]

The platform decides each token's outcome on its own, so one failed token never stops the others. For each token in scope it first checks your "Custodian" role on the token. With the role, it checks whether the wallet is already frozen there. If the wallet is not, it sends the freeze and records how the transaction ends.

[Figure] The first check that applies decides each token's status. Restrict wallet applies to each token in turn. First the platform checks the custodian role on the token: without it the token is failed. With the role it checks whether the wallet is already frozen on the token: if so the token is already-frozen and nothing is sent. Otherwise it sends the freeze. A freeze the chain rejects leaves the token failed, a freeze that has not settled leaves it queued, and a freeze that settles leaves it frozen. A later lift unfreezes frozen and queued tokens, leaves already-frozen tokens frozen, and has nothing to undo on failed tokens. Labels: Restrict wallet; one reason, every token; for each token; Custodian role?; held on this token; no; yes; Already frozen?; before the restriction; yes; already-frozen; Lift: leaves it frozen; no; Send the freeze; one transaction per token; rejected; settles; not settled yet; failed; Lift: nothing to undo; frozen; Lift: unfreezes it; queued; Lift: unfreezes it.

The first check that applies decides each token's status, and a lift reverses only the freezes the restriction
applied.

| Console badge | API status | What it means | What to do |
| --- | --- | --- | --- |
| **Frozen** | `frozen` | This restriction froze the wallet on the token. | Nothing. A lift unfreezes it. |
| **Already frozen** | `already-frozen` | The wallet was frozen on the token before the restriction. The platform sends nothing for it. | Nothing. A lift leaves it frozen. |
| **Queued** | `queued` | The platform accepted the freeze, and the transaction has not settled. | Select **Apply again**. The platform resumes the accepted transaction. |
| **Freeze failed** | `failed` | The freeze did not happen. The `failure` field holds a `code`, a `message`, and a `fix`. | Apply the fix, then select **Apply again**. |
| **Queued** | `pending` | The platform recorded the token and has not sent its freeze. | Select **Apply again**. |
| **Lift queued** | `lift-queued` | The platform accepted the unfreeze, and the transaction has not settled. | Lift the restriction again. |
| **Lifted** | `lifted` | The platform unfroze the wallet on the token. | Nothing. |
| **Lift failed** | `lift-failed` | The unfreeze did not happen. The restriction stays active, and `failure` holds the cause and the fix. | Apply the fix, then lift the restriction again. |

The `code` in a `failure` names the cause. For a cause the DALP error catalogue lists, it is the DALP error code: `DALP-0712` when you lack the "Custodian" role, and `DALP-0706` when the token is not available in the active system, the organisation's deployment on the selected network. When the transaction queue refuses or fails the transaction, it is the queue code, for example `UNPROCESSABLE_CONTENT` for a transaction that reverted.

The restriction also reports a `summary` that counts the tokens by outcome: `total`, `frozen`, `queued`, `failed`, `alreadyFrozen`, and `lifted`. The `queued` count includes `pending` and `lift-queued` tokens, and the `failed` count includes `lift-failed` tokens.

## What the restriction does not cover [#what-the-restriction-does-not-cover]

### Tokens the wallet acquires later [#tokens-the-wallet-acquires-later]

A restriction freezes the tokens the wallet holds when the request runs. A token the wallet receives afterwards, or a token minted to it, is not frozen. Two options cover it:

- To freeze a token the wallet has acquired since, select **Apply again**, or repeat the restrict request as [Repeat a request safely](#repeat-a-request-safely) describes. The platform adds the missing freezes to the same restriction.
- To stop the wallet from receiving tokens at all, add its address to the address block list.

The address block list is the **Block addresses** control in [Global controls](https://docs.settlemint.com/docs/console/compliance/global-controls). On every token bound to the platform's compliance engine, including tokens issued later, it rejects a transfer or a mint that names a listed address as sender or recipient. It differs from a token's "Blocklist" tab, which lists the addresses frozen on that one token.

The list belongs to the organisation's system, not to one token. A block list rule blocks a listed address on every bound token in that rule's scope while the rule is on, so check the rule's "Applies to" scope before you rely on it. A custodian forced transfer and a token recovery skip the block list, as they skip every compliance rule. You need the "Compliance manager" role to change it, and lifting a restriction does not remove the address from it. The [Block addresses](https://docs.settlemint.com/docs/concepts/compliance-and-identity/compliance-modules#block-addresses) reference describes the module.

In the Console, open "Compliance", then "Global controls", select the **Block addresses** control, and add the wallet address to its list. [Add a wallet to the address block list](#add-a-wallet-to-the-address-block-list) shows the Platform API call.

### Partial freezes and forced transfers [#partial-freezes-and-forced-transfers]

A restriction uses the address freeze only. It never creates, changes or removes a partial freeze, so a partial freeze the wallet already had stays as it was before and after the lift. A custodian forced transfer ignores the freeze on the sending wallet, so a restriction does not stop a holder of the "Custodian" role from moving the wallet's tokens out. The chain does refuse a forced transfer into the restricted wallet and a Supply management burn from it. [Transfers](https://docs.settlemint.com/docs/console/asset-management/manage/transfers) describes forced transfers.

### Unfreezes outside the restriction [#unfreezes-outside-the-restriction]

While a restriction is active, DALP refuses an unblock of the wallet on any token the restriction lists and releases those freezes only through the lift, as [Lift a restriction](#lift-a-restriction) describes. An AI app that runs an unblock as one of the organisation's agents through the [hosted MCP server](https://docs.settlemint.com/docs/api-reference/cli/hosted-mcp) is refused the same way. The token contract holds only the freeze and knows nothing of the restriction, so a holder of the **Custodian** role on the token can still unfreeze the wallet with a direct call to the contract, outside DALP. The restriction then still reads active while the token no longer holds the freeze. To confirm a freeze still holds, check the token's "Blocklist" tab, not the restriction. To restore one, use "Block" on that tab: a restriction never stops a "Block".

## Controls that stop movement [#controls-that-stop-movement]

Four controls stop movement, and each acts at a different scope. Choose by what must stop.

| You need to stop | Use | What to weigh |
| --- | --- | --- |
| One wallet, on the tokens it holds now | A wallet restriction | It freezes only what the wallet holds when you run it. |
| One wallet, on every token including ones it receives later | The address block list in [Global controls](https://docs.settlemint.com/docs/console/compliance/global-controls) | One rule serves every bound token in its scope, and changing it needs the "Compliance manager" role. |
| Part of one balance on one token | A partial freeze on [Pause and freeze](https://docs.settlemint.com/docs/console/asset-management/manage/pause-freeze) | Each submission covers one address and one token. |
| One asset, for every holder | A pause on [Pause and freeze](https://docs.settlemint.com/docs/console/asset-management/manage/pause-freeze) | It stops every holder of the asset. |

None of the four stops a custodian forced transfer.

## You should see [#you-should-see]

- Open the user's "Wallets" tab and confirm the "Restricted: " badge shows the reason you chose.
- In **Restriction result**, confirm "Failed" and "Queued" are 0.
- Open each frozen token, open its "Blocklist" tab, and confirm the wallet is listed. The address details show the reason of the active restriction. Check the "Blocklist" tab again before you report on or lift the restriction, because an unfreeze sent on chain outside DALP removes the freeze while the restriction still reads active.
- The organisation owner or an integration can also read the restriction through the API and check that `data.summary.failed` is 0 and that every token you expect is `frozen` or `already-frozen`. To match a freeze to the chain, compare the token's `transactionHash` in the restriction with the entry on that token's "Events" tab.
- After a lift, confirm the badge is gone and the wallet no longer appears on the "Blocklist" of the tokens the restriction froze. A token that showed `already-frozen` still lists the wallet.

## Troubleshooting [#troubleshooting]

**A token shows Freeze failed**

Read the `failure` of that token: it holds a `code`, a `message` and a `fix`. A token where you lack the "Custodian"
role fails with `DALP-0712`. Ask a holder of the token's admin role to grant you "Custodian" from the token's page,
then select **Apply again**, or repeat the restrict request as [Repeat a request safely](#repeat-a-request-safely)
describes. The platform already froze the wallet on the other tokens, and it sends only the freezes that are still
missing.

**A token stays Queued**

The platform accepted the freeze and the transaction has not settled. Select **Apply again**, or repeat the restrict
request as [Repeat a request safely](#repeat-a-request-safely) describes. The platform resumes the accepted
transaction instead of sending a second one, and it records the outcome.

**A token the wallet received later is not frozen**

A restriction freezes the tokens the wallet holds when you run it. Select **Apply again**, or repeat the restrict
request as [Repeat a request safely](#repeat-a-request-safely) describes, to freeze the new token. Or add the wallet
to the address block list to stop it from receiving tokens at all. [What the restriction does not
cover](#what-the-restriction-does-not-cover) describes both.

**The lift leaves the restriction active**

At least one unfreeze failed or has not settled, or a freeze is still settling. The token shows "Lift failed", "Lift
queued", or "Queued", and a failed token states its cause. Apply the fix, usually the "Custodian" role on that token,
or wait for the transaction to settle, and lift again. The platform sends only the unfreezes that are still missing.

**The lift returns 409 with DALP-17460**

A freeze on one of the restriction's tokens had not settled when you lifted, so the platform sent no unfreeze and the
restriction stays active. Wait for the freeze to settle, then lift again. The freeze has settled when no token of the
restriction shows **Queued**.

**The wallet is still frozen on a token after the lift**

The token showed "Already frozen", so the wallet was frozen there before the restriction and the lift leaves it. If
that freeze should end too, check that the "Restricted: " badge is gone from the wallet card, then open the token's
"Blocklist" tab and use **Unblock** for the address. If the badge still shows, follow "The lift leaves the restriction
active" first.

## Frequently asked questions [#frequently-asked-questions]

### What happens to a transfer the wallet already submitted?

The chain checks a freeze when a transfer executes, not when it is submitted. A transfer from or to the wallet that executes after the freeze lands reverts. A transfer that executed before the freeze keeps its result.

### Can I change the reason of an active restriction?

No. The reason, the note and the scope are fixed when you create the restriction, and a restrict request with a different reason, note or scope returns 409. To record a different reason, add the wallet's address to the address block list in [Global controls](https://docs.settlemint.com/docs/console/compliance/global-controls) first, lift the restriction and restrict the wallet again, then remove the address from the list. Without the block list, the wallet is unfrozen between the lift and the new restriction.

### Can I restrict more than one wallet in one request?

No. A request names one wallet, and the Console restricts one wallet at a time. To restrict more than one wallet, send one request for each.

## API routes [#api-routes]

The Platform API and the CLI offer four operations: restrict, list, read and lift. Authenticate with an [API key](https://docs.settlemint.com/docs/api-reference/guides/authentication-api-keys), which acts with the permissions of the user who created it and skips the wallet verification. While that user is in a cooling-off period after a wallet security change, a request that sends a transaction returns 403 `DALP-17440`. A request made with a Console session sends the verification as `walletVerification` in the body. The calls use your organisation's default network, and the `X-Chain-Id` header selects another one. The [Platform API reference](https://docs.settlemint.com/docs/api-reference/v2) lists every field and response.

### Send a restrict request [#send-a-restrict-request]

Send the wallet address, the scope, and the reason. Scope `all` freezes every token the wallet holds when the request runs. Scope `tokens` freezes the 1 to 50 token addresses you list, including tokens the wallet does not hold yet.

```bash
curl -X POST "https://your-instance.example.com/api/v2/restrictions" \
  -H "X-Api-Key: sm_dalp_..." \
  -H "Content-Type: application/json" \
  -d '{
    "walletAddress": "0x8ba1f109551bD432803012645Ac136ddd64DBA72",
    "scope": { "kind": "all" },
    "reason": { "code": "aml-review", "text": "Transaction monitoring alert, case 2026-0417" }
  }'
```

The CLI sends the same body. The generated command follows the HTTP verb and the path, so `POST /api/v2/restrictions` becomes `dalp create restrictions`:

```bash
dalp create restrictions --body '{
  "walletAddress": "0x8ba1f109551bD432803012645Ac136ddd64DBA72",
  "scope": { "kind": "all" },
  "reason": { "code": "aml-review", "text": "Transaction monitoring alert, case 2026-0417" }
}'
```

The call waits for the freezes to settle and returns 200 with the restriction. A token whose transaction has not settled by then shows `queued`, and the call then returns 202 with the same body and a `Location` header, the restriction's own URL. The organisation owner or a platform administrator reads that URL until no token shows `queued`, because each read settles the queued tokens from the queue. Any other caller gets 404 `DALP-17457` on that URL, so it sends the same restrict request again instead, which resumes the accepted transactions. A partial result is a normal response: read `data.summary` and the `status` of each entry in `data.tokens`. Here the caller is the organisation owner, who holds the **Custodian** role on two of the wallet's three tokens. The platform froze those two, one of them paused, and could not freeze the third.

```json
{
  "data": {
    "id": "0198f1a2-3c4d-7e8f-9a0b-1c2d3e4f5a6b",
    "walletAddress": "0x8ba1f109551bD432803012645Ac136ddd64DBA72",
    "participantId": "participant_3b1f",
    "scope": "all",
    "reason": {
      "code": "aml-review",
      "text": "Transaction monitoring alert, case 2026-0417"
    },
    "status": "active",
    "createdBy": "user_8f3a2c",
    "createdAt": "2026-10-25T12:00:00.000Z",
    "liftedBy": null,
    "liftedAt": null,
    "liftNote": null,
    "summary": {
      "total": 3,
      "frozen": 2,
      "queued": 0,
      "failed": 1,
      "alreadyFrozen": 0,
      "lifted": 0
    },
    "tokens": [
      {
        "token": "0x71C7656EC7ab88b098defB751B7401B5f6d8976F",
        "tokenName": "Northwind Coffee Series A Bond",
        "tokenSymbol": "NWCAB",
        "status": "frozen",
        "paused": false,
        "transactionId": "0198f1a2-4a5b-7c6d-8e9f-0a1b2c3d4e5f",
        "transactionHash": "0x2a8f0d4c1b6e39a7c05d8f21b4e7a63c9d0f5b18e24a7c36d91b0f8e5a3c7d24",
        "failure": null,
        "updatedAt": "2026-10-25T12:00:07.000Z"
      },
      {
        "token": "0xDc64a140Aa3E981100a9becA4E685f962f0cF6C9",
        "tokenName": "Northwind Real Estate Fund",
        "tokenSymbol": "NWREF",
        "status": "frozen",
        "paused": true,
        "transactionId": "0198f1a2-4a5c-7c6d-8e9f-0a1b2c3d4e60",
        "transactionHash": "0x5c1d9e7a3b0f2486d1c7e5a9b3f08d24c6e1a7b95d3f20c84e6a1b7d9c3f5e02",
        "failure": null,
        "updatedAt": "2026-10-25T12:00:07.000Z"
      },
      {
        "token": "0x5FbDB2315678afecb367f032d93F642f64180aa3",
        "tokenName": "Northwind Treasury Note",
        "tokenSymbol": "NWTN",
        "status": "failed",
        "paused": false,
        "transactionId": null,
        "transactionHash": null,
        "failure": {
          "code": "DALP-0712",
          "message": "This operation is not available to the caller",
          "fix": "Ask an administrator to grant one of the listed roles on this token."
        },
        "updatedAt": "2026-10-25T12:00:07.000Z"
      }
    ]
  },
  "links": {
    "self": "/api/v2/restrictions/0198f1a2-3c4d-7e8f-9a0b-1c2d3e4f5a6b"
  }
}
```

The record also states who created the restriction and when, and who lifted it, when, and with which note.

### List and read restrictions [#list-and-read-restrictions]

Find the active restriction for a wallet by listing the restrictions, newest first. The list filters by `walletAddress`, `participantId`, `status` (`active` or `lifted`), `reasonCode`, and `createdAt`, and [Pagination](https://docs.settlemint.com/docs/api-reference/guides/pagination) describes the query model. Each row states the reason, the actors, the times, and the `summary`. Read one restriction by its identifier to see its tokens.

```bash
curl -g "https://your-instance.example.com/api/v2/restrictions?filter[walletAddress]=0x8ba1f109551bD432803012645Ac136ddd64DBA72&filter[status]=active" \
  -H "X-Api-Key: sm_dalp_..."

curl "https://your-instance.example.com/api/v2/restrictions/0198f1a2-3c4d-7e8f-9a0b-1c2d3e4f5a6b" \
  -H "X-Api-Key: sm_dalp_..."
```

In the CLI, `dalp get restrictions` lists the restrictions and `dalp get restrictions <restrictionId>` reads one. Run `dalp get restrictions --help` for the filter options.

### Send a lift request [#send-a-lift-request]

Send `status` as `lifted`, with an optional `note` of up to 500 characters. The platform stores the note with the lift and with each unfreeze.

```bash
curl -X PATCH "https://your-instance.example.com/api/v2/restrictions/0198f1a2-3c4d-7e8f-9a0b-1c2d3e4f5a6b" \
  -H "X-Api-Key: sm_dalp_..." \
  -H "Content-Type: application/json" \
  -d '{ "status": "lifted", "note": "Cleared after review" }'
```

```bash
dalp patch restrictions 0198f1a2-3c4d-7e8f-9a0b-1c2d3e4f5a6b \
  --body '{ "status": "lifted", "note": "Cleared after review" }'
```

The response shows the restriction after the lift. As with the restrict request, a token whose lift has not settled shows `lift-queued`, and the call returns 202 with a `Location` header that the owner or a platform administrator reads until none does. Any other caller sends the same lift request again. The platform unfroze the two frozen tokens and recorded the new transactions. The third token stays `failed`, because there was nothing to undo, and it does not keep the restriction active.

```json
{
  "data": {
    "id": "0198f1a2-3c4d-7e8f-9a0b-1c2d3e4f5a6b",
    "walletAddress": "0x8ba1f109551bD432803012645Ac136ddd64DBA72",
    "participantId": "participant_3b1f",
    "scope": "all",
    "reason": {
      "code": "aml-review",
      "text": "Transaction monitoring alert, case 2026-0417"
    },
    "status": "lifted",
    "createdBy": "user_8f3a2c",
    "createdAt": "2026-10-25T12:00:00.000Z",
    "liftedBy": "user_8f3a2c",
    "liftedAt": "2026-10-26T09:30:08.000Z",
    "liftNote": "Cleared after review",
    "summary": {
      "total": 3,
      "frozen": 0,
      "queued": 0,
      "failed": 1,
      "alreadyFrozen": 0,
      "lifted": 2
    },
    "tokens": [
      {
        "token": "0x71C7656EC7ab88b098defB751B7401B5f6d8976F",
        "tokenName": "Northwind Coffee Series A Bond",
        "tokenSymbol": "NWCAB",
        "status": "lifted",
        "paused": false,
        "transactionId": "0198f6d3-6b7c-7d8e-9f0a-1b2c3d4e5f60",
        "transactionHash": "0x9b4e1f7c2a6d8035e1b9c4a7f2d60e3b8a5c1d9f4e7b2a60c3d8f5e1a9b7c402",
        "failure": null,
        "updatedAt": "2026-10-26T09:30:07.000Z"
      },
      {
        "token": "0xDc64a140Aa3E981100a9becA4E685f962f0cF6C9",
        "tokenName": "Northwind Real Estate Fund",
        "tokenSymbol": "NWREF",
        "status": "lifted",
        "paused": true,
        "transactionId": "0198f6d3-6b7d-7d8e-9f0a-1b2c3d4e5f61",
        "transactionHash": "0x3d7a9c1e5b2f48067a1c9e3d5b7f2a4c6e8091b3d5f7a2c4e6a8b0d2f4c6e8a1",
        "failure": null,
        "updatedAt": "2026-10-26T09:30:08.000Z"
      },
      {
        "token": "0x5FbDB2315678afecb367f032d93F642f64180aa3",
        "tokenName": "Northwind Treasury Note",
        "tokenSymbol": "NWTN",
        "status": "failed",
        "paused": false,
        "transactionId": null,
        "transactionHash": null,
        "failure": {
          "code": "DALP-0712",
          "message": "This operation is not available to the caller",
          "fix": "Ask an administrator to grant one of the listed roles on this token."
        },
        "updatedAt": "2026-10-25T12:00:07.000Z"
      }
    ]
  },
  "links": {
    "self": "/api/v2/restrictions/0198f1a2-3c4d-7e8f-9a0b-1c2d3e4f5a6b"
  }
}
```

Send the same lift request again to retry the unfreezes that failed and to finish a freeze that was still settling. A restriction that is already lifted comes back unchanged, and the platform sends nothing. Every lift request, a repeat included, needs the **Custodian** role on at least one token of the restriction.

### Repeat a request safely [#repeat-a-request-safely]

Send a restrict request again with the same reason code, the same note, and the same scope kind, and the platform continues the active restriction instead of creating another. The repeat does three things:

- It adds a freeze for each token in scope that the restriction does not cover yet.
- It retries each token that failed.
- It resumes each freeze that was accepted but has not settled, without sending a second transaction.

Send a different reason, note or scope kind and the platform returns 409. When the wallet holds no token any more, only the organisation owner and platform administrators can continue the active restriction. Any other caller gets 422. A caller who may not read restrictions still gets the restriction back from a restrict or a lift, with less in it. The response leaves out the free-text reason and the lift note. It lists only the tokens where that caller holds the **Custodian** role, and `summary` counts only those.

Both write calls also accept the optional `Idempotency-Key` header. The repeat rules hold without it, because the platform keys the transaction of each token by the restriction.

### Add a wallet to the address block list [#add-a-wallet-to-the-address-block-list]

Read the registered compliance modules and find the entry whose `typeId` is `address-block-list-v2`. [Global controls](https://docs.settlemint.com/docs/console/compliance/global-controls) owns this control. The steps below assume the organisation has one block list binding. Note its `moduleAddress`. If `globalConfigs` is empty, the platform has no block list yet, and a configure call without `instanceAddress` creates it. If `globalConfigs` holds a binding, its `moduleAddress` is the `instanceAddress` to send, and `parameters.addresses` is the current list.

```bash
curl "https://your-instance.example.com/api/v2/system/compliance-modules" \
  -H "X-Api-Key: sm_dalp_..."
```

A configure call on an installed control replaces the whole list with the `values` you send. An address you leave out is removed from the block list and can send and receive again. Copy every address from `parameters.addresses` into `values`, then add the new one. The binding must be enabled, and the call needs the **Compliance manager** role. In this example the first address was already on the list and the second is the wallet.

```bash
curl -X POST "https://your-instance.example.com/api/v2/system/compliance-modules/configure" \
  -H "X-Api-Key: sm_dalp_..." \
  -H "Content-Type: application/json" \
  -d '{
    "instanceAddress": "0xa513E6E4b8f2a923D98304ec87F64353C4D5C853",
    "params": {
      "typeId": "address-block-list-v2",
      "module": "0x0165878A594ca255338adfa4d48449f69242Eb8F",
      "values": [
        "0x2546BcD3c84621e976D8185a91A922aE77ECEc30",
        "0x8ba1f109551bD432803012645Ac136ddd64DBA72"
      ]
    }
  }'
```

Read the module again at `/api/v2/system/compliance-modules/<moduleAddress>`. The `parameters.addresses` of its binding lists the new addresses once the change is indexed.

### Errors [#errors]

| Status | Error | Cause | What to do |
| --- | --- | --- | --- |
| 403 | [DALP-9485](https://docs.settlemint.com/docs/api-reference/errors) | You hold the Custodian role on none of the tokens the request covers. | Ask an administrator to grant the role on at least one token, then send the request again. |
| 403 | [DALP-17440](https://docs.settlemint.com/docs/api-reference/errors) | The API key's user is in the cooling-off period after a wallet security change, and the request sends a transaction. Nothing was stored. | Wait until `data.heldUntil`, then send the request again. |
| 404 | [DALP-17457](https://docs.settlemint.com/docs/api-reference/errors) | No restriction in this organisation has that identifier, you may not see restrictions, or you hold the Custodian role on none of its tokens. | Use the identifier from the request that created the restriction, or ask the owner to list restrictions. |
| 409 | [DALP-17458](https://docs.settlemint.com/docs/api-reference/errors) | The wallet already has an active restriction with a different reason, note, or scope kind. | Send the reason, note, and scope kind of the active restriction again to continue it, or lift it first. The organisation owner can read them. |
| 409 | [DALP-17460](https://docs.settlemint.com/docs/api-reference/errors) | A lift found a freeze still settling on a token where you hold the Custodian role, so it sent no unfreeze. | Wait for the freeze to settle, then send the lift again. The error is safe to retry. |
| 422 | [DALP-17459](https://docs.settlemint.com/docs/api-reference/errors) | The wallet holds no token in this organisation, or none of the listed tokens exists in the active system. | List tokens that exist in the active system, or add the wallet to the address block list. |
