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

# customer.restricted

> Event triggered when a customer is restricted from depositing or withdrawing.

<Warning>
  `customer.restricted` is off by default. It will not be delivered until you enable it in Dashboard → Developers. See [Receiving Webhooks](/api-reference/api-v1/webhooks/setup) for instructions.
</Warning>

Fired when a customer's deposit or withdrawal access is restricted inside Soap — by a dashboard user or by automated checks (for example KYC failure or multi-accounting). The matching lift is [`customer.unrestricted`](/api-reference/api-v1/webhooks/customer-unrestricted), which uses the same payload shape.

This is a customer event, not a checkout event. The payload has no `charge`, `line_items`, or `subscription` fields.

## Payload Structure

```typescript theme={null}
interface WebhookEvent {
  event_id: string;
  data: {
    customer: {
      id: string;
    };
    type: "deposit_restricted" | "withdrawal_restricted";
    reason_code: string | null;
    created_at: string;
    user: {
      email: string;
    } | null;
  };
  type: "customer.restricted";
}
```

* `type` is which restriction flag changed, not the webhook event name.
* `user` is `{ "email": "..." }` when a dashboard user applied the restriction, and `null` when Soap applied it automatically or when the sandbox `$1.13` simulation produced it.
* `created_at` is a Ruby-formatted timestamp string (`"2026-08-25 18:20:59 UTC"`), not ISO 8601.
* `reason_code` says why the restriction was applied. See [Reason codes](#reason-codes).

## Reason codes

`reason_code` is a string when Soap applied the restriction automatically and `null` when no automatic reason was recorded. Unless noted, a code restricts both deposits and withdrawals.

| Code | Meaning | Scope |
| - | - | - |
| `KYC_FAILED` | Identity verification failed. | Deposits and withdrawals |
| `KYC_PENDING_REVIEW` | The identity verification provider needs a manual review. | Deposits and withdrawals |
| `KYC_UNDERAGE` | Identity verified, but the customer is under the account's minimum age. | Deposits and withdrawals |
| `KYC_DOES_NOT_MATCH_PROFILE_NAME` | The verified identity's name is not consistent with the customer profile's `first_name` and `last_name`. | Deposits and withdrawals |
| `PAYMENT_METHOD_NAME_MISMATCH` | The name on the card or bank account is not consistent with the customer profile or verified identity. | Deposits and withdrawals |
| `AEROPAY_USER_NAME_MISMATCH` | The name on the customer's Aeropay (Pay By Bank) account is not consistent with the customer profile or verified identity. | Deposits and withdrawals |
| `DEVICE_MULTI_ACCOUNTING` | The customer's device was seen on another customer account. | Deposits and withdrawals |
| `PAYMENT_METHOD_MULTI_ACCOUNTING` | The card or bank account was seen on another customer account. | Deposits and withdrawals |
| `CHARGE_RETURNED` | A succeeded payment was returned (for example an ACH return). Applied automatically. | Deposits and withdrawals |
| `DISPUTE` | A chargeback or dispute was opened on a card payment. Applied automatically; this is the only webhook signal of a dispute — see [Disputes and chargebacks](/api-reference/lifecycles#disputes-and-chargebacks). | Deposits and withdrawals |
| `TOO_MANY_FAILED_CARD_AUTHS` | Too many failed card authorization attempts. | Deposits and withdrawals |
| `TOO_MANY_FAILED_BANK_VALIDATIONS` | Too many failed bank account validations. | Deposits and withdrawals |
| `WITHDRAWAL_REVIEW` | A withdrawal review is open. Lifted when the reviewer resolves the review with the "unrestrict" option, which is the default in the dashboard. | Withdrawals only |
| `null` | No automatic reason was recorded: a dashboard user applied the restriction manually (`data.user.email` identifies who), or, in sandbox, the `$1.13` test amount simulated it (`user` is `null`). | Whichever flag `type` reports |

New codes may be added over time, so treat any unrecognized value with a generic fallback rather than rejecting the event.

For `KYC_DOES_NOT_MATCH_PROFILE_NAME`, correct the profile with [Update Customer](/api-reference/api-v1/customers/update) — use the customer's legal first name and surname as shown on their ID, with no nicknames, middle names, initials or suffixes in those fields — and then lift the restriction in the dashboard.

## Example Response

```json theme={null}
{
  "event_id": "ev_tDaWu5aTVa2kbvDjGe55rxZpaMEmVFWB",
  "data": {
    "customer": {
      "id": "cus_5cDuRGp9AvscMgoyS5Y7wygiTgQrycvs"
    },
    "type": "deposit_restricted",
    "reason_code": "KYC_FAILED",
    "created_at": "2026-08-25 18:20:59 UTC",
    "user": null
  },
  "type": "customer.restricted"
}
```

Dashboard-initiated example, with an acting user:

```json theme={null}
{
  "event_id": "ev_tDaWu5aTVa2kbvDjGe55rxZpaMEmVFWB",
  "data": {
    "customer": {
      "id": "cus_5cDuRGp9AvscMgoyS5Y7wygiTgQrycvs"
    },
    "type": "withdrawal_restricted",
    "reason_code": null,
    "created_at": "2026-08-25 18:20:59 UTC",
    "user": {
      "email": "ops@example.com"
    }
  },
  "type": "customer.restricted"
}
```


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