# Risk tools

> MCP tools for Risk: risk_blocklist_create, risk_blocklist_delete, risk_blocklist_list, risk_evaluations_get, risk_evaluations_list, risk_reviews_approve, risk_reviews_get, risk_reviews_list, risk_reviews_reject, risk_settings_get, risk_settings_update.

- `risk_blocklist_create`: Block an email, card, IP range or country
- `risk_blocklist_delete`: Remove a blocklist entry
- `risk_blocklist_list`: List blocklist entries
- `risk_evaluations_get`: Get a risk evaluation
- `risk_evaluations_list`: List risk evaluations
- `risk_reviews_approve`: Approve a held payment
- `risk_reviews_get`: Get a risk review
- `risk_reviews_list`: List risk reviews
- `risk_reviews_reject`: Refund a held payment and block the customer
- `risk_settings_get`: Get the risk settings
- `risk_settings_update`: Update the risk settings

## `risk_blocklist_create`

**Block an email, card, IP range or country.** Operation [`risk.blocklist.create`](https://ownrecord.io/docs/reference/risk-blocklist-create.md) · Brand level · permission `customers:write` · risk tier `write` · since M9

Adds a value to the brand's blocklist in the mode of the request. From the next attempt on, checkout and
auto-reload refuse payments that match it (`risk_payment_declined` for the buyer, without saying why):

- `email`: the customer's address (any case);
- `card_fingerprint`: the processor's fingerprint of a card number (Stripe `card.fingerprint`; a risk
  evaluation shows it), so the same card is refused whatever its expiry or the customer;
- `ip_range`: CIDR such as `203.0.113.0/24` or `2001:db8::/32`, at most /24 (IPv4) or /48 (IPv6) narrow, since
  Ownrecord keeps only the truncated network of an address; a bare address blocks its /24;
- `country`: an ISO country code, matched against the IP country, the billing country and the card's country.

Values are stored normalised (the answer shows how). A value already listed is `risk_blocklist_entry_exists`.

Annotations: `readOnlyHint: false` · `destructiveHint: false` · `idempotentHint: false` · `openWorldHint: false`

### Arguments

| Argument          | Type                                                      | Required | Description                                                                                                                                                                                              |
| ----------------- | --------------------------------------------------------- | -------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `kind`            | one of `email`, `card_fingerprint`, `ip_range`, `country` | yes      | –                                                                                                                                                                                                        |
| `value`           | string                                                    | yes      | (1–320 characters)                                                                                                                                                                                       |
| `reason`          | string                                                    | no       | (1–500 characters)                                                                                                                                                                                       |
| `entity_id`       | ID (`ent_…`)                                              | no       | Optional: the brand's legal entity (ent\_…); `brand_id` alone is enough.                                                                                                                                 |
| `brand_id`        | ID (`brd_…`)                                              | no       | The brand to act on (brd\_…), inside your API key's reach. Needed with an organization or entity key; a brand key acts on its own brand.                                                                 |
| `idempotency_key` | string                                                    | no       | A unique string for this change. Retrying with the same key and arguments never acts twice. When left out, the server generates one and returns it in the result's `idempotency_key`. (1–255 characters) |
| `dry_run`         | boolean                                                   | no       | true: check permissions and rules and compute the result, then roll everything back. Nothing is saved. (default `false`)                                                                                 |

- **Brand:** pass `brand_id` with an organization or entity key; a brand key acts on its own brand.
- **Idempotency:** the result returns the `idempotency_key` used, yours or one the server generated. Retry with it: a call with the same key and arguments never acts twice (keys are kept for 24 hours).
- **Dry run:** supported. `dry_run: true` checks permissions and rules and computes the result, then rolls everything back.

### Errors

- [`validation_failed`](https://ownrecord.io/docs/reference/errors.md#validation_failed): The value isn't one of its kind, or the IP range is narrower than /24 (/48).
- [`risk_blocklist_entry_exists`](https://ownrecord.io/docs/reference/errors.md#risk_blocklist_entry_exists): The value is already on the blocklist (`details.entryId`).
- [`permission_denied`](https://ownrecord.io/docs/reference/errors.md#permission_denied): You can't change this brand's customers.

### Examples

**Block a card tester's email**

Arguments:

```json
{
  "kind": "email",
  "value": "Card.Tester@Example.com",
  "reason": "Tried six cards in ten minutes",
  "brand_id": "brd_01jbx4m3v8e9t0s6k2c5n7q1wz",
  "idempotency_key": "8d0c5f8e-4b7a-4e43-9b0f-2f6a0c1d9e21"
}
```

Result `output`:

```json
{
  "id": "rbl_01m4ttwd3veh9apbewxheq5xr2",
  "object": "risk_blocklist_entry",
  "livemode": true,
  "brandId": "brd_01m4ttwd3veh9apbewxheq5xh5",
  "kind": "email",
  "value": "card.tester@example.com",
  "reason": "Tried six cards in ten minutes",
  "source": "operator",
  "evaluationId": null,
  "createdBy": "usr_01m4ttwd3veh9apbewxheq5xh6",
  "createdAt": "2026-10-20T09:00:00.000Z"
}
```

**Block an IP network**

Arguments:

```json
{
  "kind": "ip_range",
  "value": "203.0.113.77",
  "brand_id": "brd_01jbx4m3v8e9t0s6k2c5n7q1wz",
  "idempotency_key": "8d0c5f8e-4b7a-4e43-9b0f-2f6a0c1d9e21"
}
```

Result `output`:

```json
{
  "id": "rbl_01m4ttwd3veh9apbewxheq5xr9",
  "object": "risk_blocklist_entry",
  "livemode": true,
  "brandId": "brd_01m4ttwd3veh9apbewxheq5xh5",
  "kind": "ip_range",
  "value": "203.0.113.0/24",
  "reason": null,
  "source": "operator",
  "evaluationId": null,
  "createdBy": "usr_01m4ttwd3veh9apbewxheq5xh6",
  "createdAt": "2026-10-20T09:00:00.000Z"
}
```

## `risk_blocklist_delete`

**Remove a blocklist entry.** Operation [`risk.blocklist.delete`](https://ownrecord.io/docs/reference/risk-blocklist-delete.md) · Brand level · permission `customers:write` · risk tier `write` · since M9

Removes a value from the brand's blocklist: payments that match it are no longer refused for it (other rules
still apply). Returns the removed entry. The audit log keeps what was removed and by whom. A customer whose risk
a rejected review set to `blocked` stays blocked: change that on the customer.

Annotations: `readOnlyHint: false` · `destructiveHint: true` · `idempotentHint: false` · `openWorldHint: false`

### Arguments

| Argument          | Type         | Required | Description                                                                                                                                                                                              |
| ----------------- | ------------ | -------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `id`              | ID (`rbl_…`) | yes      | –                                                                                                                                                                                                        |
| `entity_id`       | ID (`ent_…`) | no       | Optional: the brand's legal entity (ent\_…); `brand_id` alone is enough.                                                                                                                                 |
| `brand_id`        | ID (`brd_…`) | no       | The brand to act on (brd\_…), inside your API key's reach. Needed with an organization or entity key; a brand key acts on its own brand.                                                                 |
| `idempotency_key` | string       | no       | A unique string for this change. Retrying with the same key and arguments never acts twice. When left out, the server generates one and returns it in the result's `idempotency_key`. (1–255 characters) |
| `dry_run`         | boolean      | no       | true: check permissions and rules and compute the result, then roll everything back. Nothing is saved. (default `false`)                                                                                 |

- **Brand:** pass `brand_id` with an organization or entity key; a brand key acts on its own brand.
- **Idempotency:** the result returns the `idempotency_key` used, yours or one the server generated. Retry with it: a call with the same key and arguments never acts twice (keys are kept for 24 hours).
- **Dry run:** supported. `dry_run: true` checks permissions and rules and computes the result, then rolls everything back.

### Errors

- [`resource_not_found`](https://ownrecord.io/docs/reference/errors.md#resource_not_found): No blocklist entry with this ID in this brand and mode.
- [`version_conflict`](https://ownrecord.io/docs/reference/errors.md#version_conflict): The entry changed at the same moment; retry.
- [`permission_denied`](https://ownrecord.io/docs/reference/errors.md#permission_denied): You can't change this brand's customers.

### Example

**Unblock an email**

Arguments:

```json
{
  "id": "rbl_01m4ttwd3veh9apbewxheq5xr2",
  "brand_id": "brd_01jbx4m3v8e9t0s6k2c5n7q1wz",
  "idempotency_key": "8d0c5f8e-4b7a-4e43-9b0f-2f6a0c1d9e21"
}
```

Result `output`:

```json
{
  "id": "rbl_01m4ttwd3veh9apbewxheq5xr2",
  "object": "risk_blocklist_entry",
  "livemode": true,
  "brandId": "brd_01m4ttwd3veh9apbewxheq5xh5",
  "kind": "email",
  "value": "card.tester@example.com",
  "reason": "Tried six cards in ten minutes",
  "source": "operator",
  "evaluationId": null,
  "createdBy": "usr_01m4ttwd3veh9apbewxheq5xh6",
  "createdAt": "2026-10-20T09:00:00.000Z"
}
```

## `risk_blocklist_list`

**List blocklist entries.** Operation [`risk.blocklist.list`](https://ownrecord.io/docs/reference/risk-blocklist-list.md) · Brand level · permission `customers:read` · risk tier `read` · since M9

Lists the brand's blocklist in the mode of the request, newest first: emails, card fingerprints (the
processor's), IP ranges and countries whose payments the risk rules refuse. Filter by `kind`, and by `value`
with it (an email in any case, a bare IP address for its /24). Paginate with `limit` (1–100, default 10) and
`starting_after`. Entries a rejected risk review added say so (`source: review`, `evaluationId`).

Annotations: `readOnlyHint: true` · `destructiveHint: false` · `idempotentHint: true` · `openWorldHint: false`

### Arguments

| Argument         | Type                                                      | Required | Description                                                                                                                              |
| ---------------- | --------------------------------------------------------- | -------- | ---------------------------------------------------------------------------------------------------------------------------------------- |
| `kind`           | one of `email`, `card_fingerprint`, `ip_range`, `country` | no       | Entries of one kind.                                                                                                                     |
| `value`          | string                                                    | no       | The entry for one value (with `kind`; written as you like). (1–320 characters)                                                           |
| `limit`          | integer                                                   | no       | (1–100)                                                                                                                                  |
| `starting_after` | ID (`rbl_…`)                                              | no       | The `next_cursor` of the previous page.                                                                                                  |
| `entity_id`      | ID (`ent_…`)                                              | no       | Optional: the brand's legal entity (ent\_…); `brand_id` alone is enough.                                                                 |
| `brand_id`       | ID (`brd_…`)                                              | no       | The brand to act on (brd\_…), inside your API key's reach. Needed with an organization or entity key; a brand key acts on its own brand. |

- **Brand:** pass `brand_id` with an organization or entity key; a brand key acts on its own brand.
- **Read-only:** changes nothing; `idempotency_key` is ignored.

### Errors

- [`validation_failed`](https://ownrecord.io/docs/reference/errors.md#validation_failed): A filter or pagination value is invalid.
- [`permission_denied`](https://ownrecord.io/docs/reference/errors.md#permission_denied): You can't see this brand's customers.

### Examples

**The blocked emails**

Arguments:

```json
{
  "kind": "email",
  "brand_id": "brd_01jbx4m3v8e9t0s6k2c5n7q1wz"
}
```

Result `output`:

```json
{
  "object": "list",
  "data": [
    {
      "id": "rbl_01m4ttwd3veh9apbewxheq5xr2",
      "object": "risk_blocklist_entry",
      "livemode": true,
      "brandId": "brd_01m4ttwd3veh9apbewxheq5xh5",
      "kind": "email",
      "value": "card.tester@example.com",
      "reason": "Tried six cards in ten minutes",
      "source": "operator",
      "evaluationId": null,
      "createdBy": "usr_01m4ttwd3veh9apbewxheq5xh6",
      "createdAt": "2026-10-20T09:00:00.000Z"
    }
  ],
  "has_more": false,
  "next_cursor": null
}
```

**Is this card blocked?**

Arguments:

```json
{
  "kind": "card_fingerprint",
  "value": "Xo1abC9dEf2GhI3j",
  "brand_id": "brd_01jbx4m3v8e9t0s6k2c5n7q1wz"
}
```

Result `output`:

```json
{
  "object": "list",
  "data": [
    {
      "id": "rbl_01m4ttwd3veh9apbewxheq5xr3",
      "object": "risk_blocklist_entry",
      "livemode": true,
      "brandId": "brd_01m4ttwd3veh9apbewxheq5xh5",
      "kind": "card_fingerprint",
      "value": "Xo1abC9dEf2GhI3j",
      "reason": "Risk review rsk_01m4ttwd3veh9apbewxheq5xr1 rejected: The cardholder doesn't know the customer.",
      "source": "review",
      "evaluationId": "rsk_01m4ttwd3veh9apbewxheq5xr1",
      "createdBy": "usr_01m4ttwd3veh9apbewxheq5xh6",
      "createdAt": "2026-10-20T09:00:00.000Z"
    }
  ],
  "has_more": false,
  "next_cursor": null
}
```

## `risk_evaluations_get`

**Get a risk evaluation.** Operation [`risk.evaluations.get`](https://ownrecord.io/docs/reference/risk-evaluations-get.md) · Brand level · permission `payments:read` · risk tier `read` · since M9

One payment attempt's risk evaluation: the decision and score, every reason (which rule, what it asked for, its
points, in plain words), the signals the rules used (the email's domain, the truncated IP network, the IP,
billing and card countries, the card's fingerprint, the amount, whether the customer was new) and every run of
the rules. When the payment was held, `review` says how the review went.

Annotations: `readOnlyHint: true` · `destructiveHint: false` · `idempotentHint: true` · `openWorldHint: false`

### Arguments

| Argument    | Type         | Required | Description                                                                                                                              |
| ----------- | ------------ | -------- | ---------------------------------------------------------------------------------------------------------------------------------------- |
| `id`        | ID (`rsk_…`) | yes      | –                                                                                                                                        |
| `entity_id` | ID (`ent_…`) | no       | Optional: the brand's legal entity (ent\_…); `brand_id` alone is enough.                                                                 |
| `brand_id`  | ID (`brd_…`) | no       | The brand to act on (brd\_…), inside your API key's reach. Needed with an organization or entity key; a brand key acts on its own brand. |

- **Brand:** pass `brand_id` with an organization or entity key; a brand key acts on its own brand.
- **Read-only:** changes nothing; `idempotency_key` is ignored.

### Errors

- [`resource_not_found`](https://ownrecord.io/docs/reference/errors.md#resource_not_found): No risk evaluation with this ID in this brand and mode.
- [`permission_denied`](https://ownrecord.io/docs/reference/errors.md#permission_denied): You can't see this brand's payments.

### Example

**A held first top-up**

Arguments:

```json
{
  "id": "rsk_01m4ttwd3veh9apbewxheq5xr1",
  "brand_id": "brd_01jbx4m3v8e9t0s6k2c5n7q1wz"
}
```

Result `output`:

```json
{
  "id": "rsk_01m4ttwd3veh9apbewxheq5xr1",
  "object": "risk_evaluation",
  "livemode": true,
  "brandId": "brd_01m4ttwd3veh9apbewxheq5xh5",
  "subject": {
    "type": "checkout_session",
    "checkoutSessionId": "cs_01m4ttwd3veh9apbewxheq5xr4",
    "walletId": null
  },
  "customerId": "cus_01m4ttwd3veh9apbewxheq5xr5",
  "paymentId": "pay_01m4ttwd3veh9apbewxheq5xr6",
  "stage": "confirm",
  "decision": "review",
  "score": 70,
  "reasons": [
    {
      "code": "first_payment",
      "action": "require_3ds",
      "points": null,
      "detail": "The customer's first payment."
    },
    {
      "code": "new_customer",
      "action": "score",
      "points": 10,
      "detail": "A new customer."
    },
    {
      "code": "country_mismatch_ip_billing",
      "action": "score",
      "points": 20,
      "detail": "IP country DE isn't the billing country HR."
    },
    {
      "code": "country_mismatch_card_billing",
      "action": "score",
      "points": 25,
      "detail": "Card country US isn't the billing country HR."
    },
    {
      "code": "country_mismatch_ip_card",
      "action": "score",
      "points": 15,
      "detail": "IP country DE isn't the card country US."
    },
    {
      "code": "score_review",
      "action": "review",
      "points": null,
      "detail": "Score 70 ≥ 70."
    }
  ],
  "signals": {
    "emailDomain": "corp.example",
    "ipNetwork": "203.0.113.0",
    "ipCountry": "DE",
    "billingCountry": "HR",
    "cardCountry": "US",
    "cardFingerprint": "Xo1abC9dEf2GhI3j",
    "amount": {
      "amount": "90000000",
      "currency": "EUR"
    },
    "topup": true,
    "newCustomer": true,
    "firstPayment": true,
    "disposableEmail": false
  },
  "history": [
    {
      "at": "2026-10-20T09:00:00.000Z",
      "stage": "intent",
      "decision": "require_3ds",
      "score": 30
    },
    {
      "at": "2026-10-20T09:01:00.000Z",
      "stage": "payment_method",
      "decision": "review",
      "score": 70
    },
    {
      "at": "2026-10-20T09:01:30.000Z",
      "stage": "confirm",
      "decision": "review",
      "score": 70
    }
  ],
  "review": {
    "status": "pending",
    "openedAt": "2026-10-20T09:02:00.000Z",
    "decidedAt": null,
    "decidedBy": null,
    "note": null,
    "refundId": null,
    "blocklistEntryIds": [],
    "frozenWalletIds": ["wal_01m4ttwd3veh9apbewxheq5xr7"]
  },
  "createdAt": "2026-10-20T09:00:00.000Z",
  "updatedAt": "2026-10-20T09:02:00.000Z"
}
```

## `risk_evaluations_list`

**List risk evaluations.** Operation [`risk.evaluations.list`](https://ownrecord.io/docs/reference/risk-evaluations-list.md) · Brand level · permission `payments:read` · risk tier `read` · since M9

Lists what the brand's risk rules decided for payment attempts in the mode of the request, newest first: one
evaluation per checkout session or auto-reload, with every run (`history`: before the payment intent, once the
card was known, at confirmation), the decision (`allow`, `require_3ds`, `review`, `block`), the score and each
reason. Filter by `paymentId` (why a payment was held), `checkoutSessionId` (why a checkout was refused; the
buyer only saw `risk_payment_declined`), `customerId` or `decision`. Paginate with `limit` (1–100, default 10)
and `starting_after`.

Annotations: `readOnlyHint: true` · `destructiveHint: false` · `idempotentHint: true` · `openWorldHint: false`

### Arguments

| Argument            | Type                                             | Required | Description                                                                                                                              |
| ------------------- | ------------------------------------------------ | -------- | ---------------------------------------------------------------------------------------------------------------------------------------- |
| `paymentId`         | ID (`pay_…`)                                     | no       | The evaluation of one payment (`pay_…`).                                                                                                 |
| `checkoutSessionId` | ID (`cs_…`)                                      | no       | The evaluation of one checkout (`cs_…`).                                                                                                 |
| `customerId`        | ID (`cus_…`)                                     | no       | A customer's evaluations (`cus_…`).                                                                                                      |
| `decision`          | one of `allow`, `require_3ds`, `review`, `block` | no       | Only this decision (e.g. `block`).                                                                                                       |
| `limit`             | integer                                          | no       | (1–100)                                                                                                                                  |
| `starting_after`    | ID (`rsk_…`)                                     | no       | The `next_cursor` of the previous page.                                                                                                  |
| `entity_id`         | ID (`ent_…`)                                     | no       | Optional: the brand's legal entity (ent\_…); `brand_id` alone is enough.                                                                 |
| `brand_id`          | ID (`brd_…`)                                     | no       | The brand to act on (brd\_…), inside your API key's reach. Needed with an organization or entity key; a brand key acts on its own brand. |

- **Brand:** pass `brand_id` with an organization or entity key; a brand key acts on its own brand.
- **Read-only:** changes nothing; `idempotency_key` is ignored.

### Errors

- [`validation_failed`](https://ownrecord.io/docs/reference/errors.md#validation_failed): A filter or pagination value is invalid.
- [`permission_denied`](https://ownrecord.io/docs/reference/errors.md#permission_denied): You can't see this brand's payments.

### Example

**Why was this payment held?**

Arguments:

```json
{
  "paymentId": "pay_01m4ttwd3veh9apbewxheq5xr6",
  "brand_id": "brd_01jbx4m3v8e9t0s6k2c5n7q1wz"
}
```

Result `output`:

```json
{
  "object": "list",
  "data": [
    {
      "id": "rsk_01m4ttwd3veh9apbewxheq5xr1",
      "object": "risk_evaluation",
      "livemode": true,
      "brandId": "brd_01m4ttwd3veh9apbewxheq5xh5",
      "subject": {
        "type": "checkout_session",
        "checkoutSessionId": "cs_01m4ttwd3veh9apbewxheq5xr4",
        "walletId": null
      },
      "customerId": "cus_01m4ttwd3veh9apbewxheq5xr5",
      "paymentId": "pay_01m4ttwd3veh9apbewxheq5xr6",
      "stage": "confirm",
      "decision": "review",
      "score": 70,
      "reasons": [
        {
          "code": "first_payment",
          "action": "require_3ds",
          "points": null,
          "detail": "The customer's first payment."
        },
        {
          "code": "new_customer",
          "action": "score",
          "points": 10,
          "detail": "A new customer."
        },
        {
          "code": "country_mismatch_ip_billing",
          "action": "score",
          "points": 20,
          "detail": "IP country DE isn't the billing country HR."
        },
        {
          "code": "country_mismatch_card_billing",
          "action": "score",
          "points": 25,
          "detail": "Card country US isn't the billing country HR."
        },
        {
          "code": "country_mismatch_ip_card",
          "action": "score",
          "points": 15,
          "detail": "IP country DE isn't the card country US."
        },
        {
          "code": "score_review",
          "action": "review",
          "points": null,
          "detail": "Score 70 ≥ 70."
        }
      ],
      "signals": {
        "emailDomain": "corp.example",
        "ipNetwork": "203.0.113.0",
        "ipCountry": "DE",
        "billingCountry": "HR",
        "cardCountry": "US",
        "cardFingerprint": "Xo1abC9dEf2GhI3j",
        "amount": {
          "amount": "90000000",
          "currency": "EUR"
        },
        "topup": true,
        "newCustomer": true,
        "firstPayment": true,
        "disposableEmail": false
      },
      "history": [
        {
          "at": "2026-10-20T09:00:00.000Z",
          "stage": "intent",
          "decision": "require_3ds",
          "score": 30
        },
        {
          "at": "2026-10-20T09:01:00.000Z",
          "stage": "payment_method",
          "decision": "review",
          "score": 70
        },
        {
          "at": "2026-10-20T09:01:30.000Z",
          "stage": "confirm",
          "decision": "review",
          "score": 70
        }
      ],
      "review": {
        "status": "pending",
        "openedAt": "2026-10-20T09:02:00.000Z",
        "decidedAt": null,
        "decidedBy": null,
        "note": null,
        "refundId": null,
        "blocklistEntryIds": [],
        "frozenWalletIds": ["wal_01m4ttwd3veh9apbewxheq5xr7"]
      },
      "createdAt": "2026-10-20T09:00:00.000Z",
      "updatedAt": "2026-10-20T09:02:00.000Z"
    }
  ],
  "has_more": false,
  "next_cursor": null
}
```

## `risk_reviews_approve`

**Approve a held payment.** Operation [`risk.reviews.approve`](https://ownrecord.io/docs/reference/risk-reviews-approve.md) · Brand level · permission `customers:write` · risk tier `write` · since M9

Releases a payment the risk rules held: the customer's wallets the hold froze are unfrozen (unless another
review of the customer is still pending, or someone changed the wallet since), the hold's reason leaves the
customer's risk (back to `normal` when nothing else elevated it), and `risk.review.approved` goes to your
webhook endpoints, so your integration can deliver what it held back. A review is decided once.

Annotations: `readOnlyHint: false` · `destructiveHint: false` · `idempotentHint: false` · `openWorldHint: false`

### Arguments

| Argument          | Type         | Required | Description                                                                                                                                                                                              |
| ----------------- | ------------ | -------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `id`              | ID (`rsk_…`) | yes      | –                                                                                                                                                                                                        |
| `note`            | string       | no       | (1–1000 characters)                                                                                                                                                                                      |
| `expectedVersion` | integer      | no       | (1–9007199254740991)                                                                                                                                                                                     |
| `entity_id`       | ID (`ent_…`) | no       | Optional: the brand's legal entity (ent\_…); `brand_id` alone is enough.                                                                                                                                 |
| `brand_id`        | ID (`brd_…`) | no       | The brand to act on (brd\_…), inside your API key's reach. Needed with an organization or entity key; a brand key acts on its own brand.                                                                 |
| `idempotency_key` | string       | no       | A unique string for this change. Retrying with the same key and arguments never acts twice. When left out, the server generates one and returns it in the result's `idempotency_key`. (1–255 characters) |
| `dry_run`         | boolean      | no       | true: check permissions and rules and compute the result, then roll everything back. Nothing is saved. (default `false`)                                                                                 |

- **Brand:** pass `brand_id` with an organization or entity key; a brand key acts on its own brand.
- **Idempotency:** the result returns the `idempotency_key` used, yours or one the server generated. Retry with it: a call with the same key and arguments never acts twice (keys are kept for 24 hours).
- **Dry run:** supported. `dry_run: true` checks permissions and rules and computes the result, then rolls everything back.

### Errors

- [`resource_not_found`](https://ownrecord.io/docs/reference/errors.md#resource_not_found): No risk evaluation with this ID in this brand and mode.
- [`risk_evaluation_not_held`](https://ownrecord.io/docs/reference/errors.md#risk_evaluation_not_held): The evaluation held no payment for review.
- [`risk_review_not_pending`](https://ownrecord.io/docs/reference/errors.md#risk_review_not_pending): The review was already approved or rejected.
- [`version_conflict`](https://ownrecord.io/docs/reference/errors.md#version_conflict): The review changed since `expectedVersion`, or at the same moment.
- [`permission_denied`](https://ownrecord.io/docs/reference/errors.md#permission_denied): You can't change this brand's customers.

### Example

**Approve after calling the customer**

Arguments:

```json
{
  "id": "rsk_01m4ttwd3veh9apbewxheq5xr1",
  "note": "Called the customer; the card is a company card.",
  "brand_id": "brd_01jbx4m3v8e9t0s6k2c5n7q1wz",
  "idempotency_key": "8d0c5f8e-4b7a-4e43-9b0f-2f6a0c1d9e21"
}
```

Result `output`:

```json
{
  "id": "rsk_01m4ttwd3veh9apbewxheq5xr1",
  "object": "risk_evaluation",
  "livemode": true,
  "brandId": "brd_01m4ttwd3veh9apbewxheq5xh5",
  "subject": {
    "type": "checkout_session",
    "checkoutSessionId": "cs_01m4ttwd3veh9apbewxheq5xr4",
    "walletId": null
  },
  "customerId": "cus_01m4ttwd3veh9apbewxheq5xr5",
  "paymentId": "pay_01m4ttwd3veh9apbewxheq5xr6",
  "stage": "confirm",
  "decision": "review",
  "score": 70,
  "reasons": [
    {
      "code": "first_payment",
      "action": "require_3ds",
      "points": null,
      "detail": "The customer's first payment."
    },
    {
      "code": "new_customer",
      "action": "score",
      "points": 10,
      "detail": "A new customer."
    },
    {
      "code": "country_mismatch_ip_billing",
      "action": "score",
      "points": 20,
      "detail": "IP country DE isn't the billing country HR."
    },
    {
      "code": "country_mismatch_card_billing",
      "action": "score",
      "points": 25,
      "detail": "Card country US isn't the billing country HR."
    },
    {
      "code": "country_mismatch_ip_card",
      "action": "score",
      "points": 15,
      "detail": "IP country DE isn't the card country US."
    },
    {
      "code": "score_review",
      "action": "review",
      "points": null,
      "detail": "Score 70 ≥ 70."
    }
  ],
  "signals": {
    "emailDomain": "corp.example",
    "ipNetwork": "203.0.113.0",
    "ipCountry": "DE",
    "billingCountry": "HR",
    "cardCountry": "US",
    "cardFingerprint": "Xo1abC9dEf2GhI3j",
    "amount": {
      "amount": "90000000",
      "currency": "EUR"
    },
    "topup": true,
    "newCustomer": true,
    "firstPayment": true,
    "disposableEmail": false
  },
  "history": [
    {
      "at": "2026-10-20T09:00:00.000Z",
      "stage": "intent",
      "decision": "require_3ds",
      "score": 30
    },
    {
      "at": "2026-10-20T09:01:00.000Z",
      "stage": "payment_method",
      "decision": "review",
      "score": 70
    },
    {
      "at": "2026-10-20T09:01:30.000Z",
      "stage": "confirm",
      "decision": "review",
      "score": 70
    }
  ],
  "review": {
    "status": "approved",
    "openedAt": "2026-10-20T09:02:00.000Z",
    "decidedAt": "2026-10-20T11:30:00.000Z",
    "decidedBy": "usr_01m4ttwd3veh9apbewxheq5xh6",
    "note": "Called the customer; the card is a company card.",
    "refundId": null,
    "blocklistEntryIds": [],
    "frozenWalletIds": ["wal_01m4ttwd3veh9apbewxheq5xr7"]
  },
  "createdAt": "2026-10-20T09:00:00.000Z",
  "updatedAt": "2026-10-20T11:30:00.000Z"
}
```

## `risk_reviews_get`

**Get a risk review.** Operation [`risk.reviews.get`](https://ownrecord.io/docs/reference/risk-reviews-get.md) · Brand level · permission `customers:read` · risk tier `read` · since M9

One held payment of the review queue: its risk evaluation (the decision, the score, every reason and the
signals the rules used: the email's domain, the truncated IP network, the IP, billing and card countries, the
card's fingerprint), the payment and customer, and the review (pending, approved or rejected, by whom, the
refund and blocklist entries of a rejection, the wallets the hold froze). An evaluation that held nothing is
`risk_evaluation_not_held`: read it with `risk.evaluations.get`.

Annotations: `readOnlyHint: true` · `destructiveHint: false` · `idempotentHint: true` · `openWorldHint: false`

### Arguments

| Argument    | Type         | Required | Description                                                                                                                              |
| ----------- | ------------ | -------- | ---------------------------------------------------------------------------------------------------------------------------------------- |
| `id`        | ID (`rsk_…`) | yes      | –                                                                                                                                        |
| `entity_id` | ID (`ent_…`) | no       | Optional: the brand's legal entity (ent\_…); `brand_id` alone is enough.                                                                 |
| `brand_id`  | ID (`brd_…`) | no       | The brand to act on (brd\_…), inside your API key's reach. Needed with an organization or entity key; a brand key acts on its own brand. |

- **Brand:** pass `brand_id` with an organization or entity key; a brand key acts on its own brand.
- **Read-only:** changes nothing; `idempotency_key` is ignored.

### Errors

- [`resource_not_found`](https://ownrecord.io/docs/reference/errors.md#resource_not_found): No risk evaluation with this ID in this brand and mode.
- [`risk_evaluation_not_held`](https://ownrecord.io/docs/reference/errors.md#risk_evaluation_not_held): The evaluation held no payment for review.
- [`permission_denied`](https://ownrecord.io/docs/reference/errors.md#permission_denied): You can't see this brand's customers.

### Example

**A held first top-up**

Arguments:

```json
{
  "id": "rsk_01m4ttwd3veh9apbewxheq5xr1",
  "brand_id": "brd_01jbx4m3v8e9t0s6k2c5n7q1wz"
}
```

Result `output`:

```json
{
  "id": "rsk_01m4ttwd3veh9apbewxheq5xr1",
  "object": "risk_evaluation",
  "livemode": true,
  "brandId": "brd_01m4ttwd3veh9apbewxheq5xh5",
  "subject": {
    "type": "checkout_session",
    "checkoutSessionId": "cs_01m4ttwd3veh9apbewxheq5xr4",
    "walletId": null
  },
  "customerId": "cus_01m4ttwd3veh9apbewxheq5xr5",
  "paymentId": "pay_01m4ttwd3veh9apbewxheq5xr6",
  "stage": "confirm",
  "decision": "review",
  "score": 70,
  "reasons": [
    {
      "code": "first_payment",
      "action": "require_3ds",
      "points": null,
      "detail": "The customer's first payment."
    },
    {
      "code": "new_customer",
      "action": "score",
      "points": 10,
      "detail": "A new customer."
    },
    {
      "code": "country_mismatch_ip_billing",
      "action": "score",
      "points": 20,
      "detail": "IP country DE isn't the billing country HR."
    },
    {
      "code": "country_mismatch_card_billing",
      "action": "score",
      "points": 25,
      "detail": "Card country US isn't the billing country HR."
    },
    {
      "code": "country_mismatch_ip_card",
      "action": "score",
      "points": 15,
      "detail": "IP country DE isn't the card country US."
    },
    {
      "code": "score_review",
      "action": "review",
      "points": null,
      "detail": "Score 70 ≥ 70."
    }
  ],
  "signals": {
    "emailDomain": "corp.example",
    "ipNetwork": "203.0.113.0",
    "ipCountry": "DE",
    "billingCountry": "HR",
    "cardCountry": "US",
    "cardFingerprint": "Xo1abC9dEf2GhI3j",
    "amount": {
      "amount": "90000000",
      "currency": "EUR"
    },
    "topup": true,
    "newCustomer": true,
    "firstPayment": true,
    "disposableEmail": false
  },
  "history": [
    {
      "at": "2026-10-20T09:00:00.000Z",
      "stage": "intent",
      "decision": "require_3ds",
      "score": 30
    },
    {
      "at": "2026-10-20T09:01:00.000Z",
      "stage": "payment_method",
      "decision": "review",
      "score": 70
    },
    {
      "at": "2026-10-20T09:01:30.000Z",
      "stage": "confirm",
      "decision": "review",
      "score": 70
    }
  ],
  "review": {
    "status": "pending",
    "openedAt": "2026-10-20T09:02:00.000Z",
    "decidedAt": null,
    "decidedBy": null,
    "note": null,
    "refundId": null,
    "blocklistEntryIds": [],
    "frozenWalletIds": ["wal_01m4ttwd3veh9apbewxheq5xr7"]
  },
  "createdAt": "2026-10-20T09:00:00.000Z",
  "updatedAt": "2026-10-20T09:02:00.000Z"
}
```

## `risk_reviews_list`

**List risk reviews.** Operation [`risk.reviews.list`](https://ownrecord.io/docs/reference/risk-reviews-list.md) · Brand level · permission `customers:read` · risk tier `read` · since M9

The brand's risk review queue in the mode of the request, newest first: payments the risk rules held. A held
payment went through and is invoiced; the customer's wallet that took its credits is frozen until someone
approves it (`risk.reviews.approve`) or refunds it and blocks the customer (`risk.reviews.reject`). Each review
is the payment's risk evaluation: the decision, the score and every reason.

`status` is `pending` by default; `approved` and `rejected` list the decided ones. Paginate with `limit` (1–100,
default 10) and `starting_after`.

Annotations: `readOnlyHint: true` · `destructiveHint: false` · `idempotentHint: true` · `openWorldHint: false`

### Arguments

| Argument         | Type                                     | Required | Description                                                                                                                              |
| ---------------- | ---------------------------------------- | -------- | ---------------------------------------------------------------------------------------------------------------------------------------- |
| `status`         | one of `pending`, `approved`, `rejected` | no       | Default `pending`: the queue.                                                                                                            |
| `customerId`     | ID (`cus_…`)                             | no       | Reviews of one customer (`cus_…`).                                                                                                       |
| `limit`          | integer                                  | no       | (1–100)                                                                                                                                  |
| `starting_after` | ID (`rsk_…`)                             | no       | The `next_cursor` of the previous page.                                                                                                  |
| `entity_id`      | ID (`ent_…`)                             | no       | Optional: the brand's legal entity (ent\_…); `brand_id` alone is enough.                                                                 |
| `brand_id`       | ID (`brd_…`)                             | no       | The brand to act on (brd\_…), inside your API key's reach. Needed with an organization or entity key; a brand key acts on its own brand. |

- **Brand:** pass `brand_id` with an organization or entity key; a brand key acts on its own brand.
- **Read-only:** changes nothing; `idempotency_key` is ignored.

### Errors

- [`validation_failed`](https://ownrecord.io/docs/reference/errors.md#validation_failed): A filter or pagination value is invalid.
- [`permission_denied`](https://ownrecord.io/docs/reference/errors.md#permission_denied): You can't see this brand's customers.

### Example

**The queue**

Arguments:

```json
{
  "brand_id": "brd_01jbx4m3v8e9t0s6k2c5n7q1wz"
}
```

Result `output`:

```json
{
  "object": "list",
  "data": [
    {
      "id": "rsk_01m4ttwd3veh9apbewxheq5xr1",
      "object": "risk_evaluation",
      "livemode": true,
      "brandId": "brd_01m4ttwd3veh9apbewxheq5xh5",
      "subject": {
        "type": "checkout_session",
        "checkoutSessionId": "cs_01m4ttwd3veh9apbewxheq5xr4",
        "walletId": null
      },
      "customerId": "cus_01m4ttwd3veh9apbewxheq5xr5",
      "paymentId": "pay_01m4ttwd3veh9apbewxheq5xr6",
      "stage": "confirm",
      "decision": "review",
      "score": 70,
      "reasons": [
        {
          "code": "first_payment",
          "action": "require_3ds",
          "points": null,
          "detail": "The customer's first payment."
        },
        {
          "code": "new_customer",
          "action": "score",
          "points": 10,
          "detail": "A new customer."
        },
        {
          "code": "country_mismatch_ip_billing",
          "action": "score",
          "points": 20,
          "detail": "IP country DE isn't the billing country HR."
        },
        {
          "code": "country_mismatch_card_billing",
          "action": "score",
          "points": 25,
          "detail": "Card country US isn't the billing country HR."
        },
        {
          "code": "country_mismatch_ip_card",
          "action": "score",
          "points": 15,
          "detail": "IP country DE isn't the card country US."
        },
        {
          "code": "score_review",
          "action": "review",
          "points": null,
          "detail": "Score 70 ≥ 70."
        }
      ],
      "signals": {
        "emailDomain": "corp.example",
        "ipNetwork": "203.0.113.0",
        "ipCountry": "DE",
        "billingCountry": "HR",
        "cardCountry": "US",
        "cardFingerprint": "Xo1abC9dEf2GhI3j",
        "amount": {
          "amount": "90000000",
          "currency": "EUR"
        },
        "topup": true,
        "newCustomer": true,
        "firstPayment": true,
        "disposableEmail": false
      },
      "history": [
        {
          "at": "2026-10-20T09:00:00.000Z",
          "stage": "intent",
          "decision": "require_3ds",
          "score": 30
        },
        {
          "at": "2026-10-20T09:01:00.000Z",
          "stage": "payment_method",
          "decision": "review",
          "score": 70
        },
        {
          "at": "2026-10-20T09:01:30.000Z",
          "stage": "confirm",
          "decision": "review",
          "score": 70
        }
      ],
      "review": {
        "status": "pending",
        "openedAt": "2026-10-20T09:02:00.000Z",
        "decidedAt": null,
        "decidedBy": null,
        "note": null,
        "refundId": null,
        "blocklistEntryIds": [],
        "frozenWalletIds": ["wal_01m4ttwd3veh9apbewxheq5xr7"]
      },
      "createdAt": "2026-10-20T09:00:00.000Z",
      "updatedAt": "2026-10-20T09:02:00.000Z"
    }
  ],
  "has_more": false,
  "next_cursor": null
}
```

## `risk_reviews_reject`

**Refund a held payment and block the customer.** Operation [`risk.reviews.reject`](https://ownrecord.io/docs/reference/risk-reviews-reject.md) · Brand level · permission `refunds:write` · risk tier `financial` · since M9

Rejects a payment the risk rules held, in one transaction:

- **Refund**, exactly as `refunds.create` with type `full` makes it: a credit note at the original rates, the
  ledger reversal and the processor refund (a credit pack only for its unused credits; the hold kept the wallet
  frozen, so normally all of them). Support refunds up to the brand's limit, finance without one.
  `refund: false` skips it (for a payment already refunded).
- **Block**: the customer's email and the card's fingerprint go on the brand's blocklist (`block` chooses;
  `ipNetwork: true` adds the IP network, which can block neighbours). An entry already listed is reused.
- The customer's risk becomes `blocked`; their frozen wallets stay frozen.

`risk.review.rejected` goes to your webhook endpoints. Financial tier: approval policies apply to agents and
apps; dry-run it first to see the refund.

Annotations: `readOnlyHint: false` · `destructiveHint: true` · `idempotentHint: false` · `openWorldHint: true`

### Arguments

| Argument          | Type         | Required | Description                                                                                                                                                                                              |
| ----------------- | ------------ | -------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `id`              | ID (`rsk_…`) | yes      | –                                                                                                                                                                                                        |
| `reason`          | string       | yes      | (1–1000 characters)                                                                                                                                                                                      |
| `refund`          | boolean      | no       | –                                                                                                                                                                                                        |
| `block`           | object       | no       | –                                                                                                                                                                                                        |
| `expectedVersion` | integer      | no       | (1–9007199254740991)                                                                                                                                                                                     |
| `entity_id`       | ID (`ent_…`) | no       | Optional: the brand's legal entity (ent\_…); `brand_id` alone is enough.                                                                                                                                 |
| `brand_id`        | ID (`brd_…`) | no       | The brand to act on (brd\_…), inside your API key's reach. Needed with an organization or entity key; a brand key acts on its own brand.                                                                 |
| `idempotency_key` | string       | no       | A unique string for this change. Retrying with the same key and arguments never acts twice. When left out, the server generates one and returns it in the result's `idempotency_key`. (1–255 characters) |
| `dry_run`         | boolean      | no       | true: check permissions and rules and compute the result, then roll everything back. Nothing is saved. (default `false`)                                                                                 |

- **Brand:** pass `brand_id` with an organization or entity key; a brand key acts on its own brand.
- **Idempotency:** the result returns the `idempotency_key` used, yours or one the server generated. Retry with it: a call with the same key and arguments never acts twice (keys are kept for 24 hours).
- **Dry run:** supported. `dry_run: true` checks permissions and rules and computes the result, then rolls everything back.

### Errors

- [`resource_not_found`](https://ownrecord.io/docs/reference/errors.md#resource_not_found): No risk evaluation with this ID in this brand and mode.
- [`risk_evaluation_not_held`](https://ownrecord.io/docs/reference/errors.md#risk_evaluation_not_held): The evaluation held no payment for review.
- [`risk_review_not_pending`](https://ownrecord.io/docs/reference/errors.md#risk_review_not_pending): The review was already approved or rejected.
- [`refund_payment_not_refundable`](https://ownrecord.io/docs/reference/errors.md#refund_payment_not_refundable): The payment can't be refunded (disputed, or refunded already): reject with `refund: false`.
- [`refund_nothing_to_refund`](https://ownrecord.io/docs/reference/errors.md#refund_nothing_to_refund): Nothing is left to refund (the credits were used): reject with `refund: false`.
- [`refund_limit_exceeded`](https://ownrecord.io/docs/reference/errors.md#refund_limit_exceeded): The refund is above your role's limit: ask finance.
- [`refund_outside_policy`](https://ownrecord.io/docs/reference/errors.md#refund_outside_policy): Support can't refund these credits under the brand's policy.
- [`version_conflict`](https://ownrecord.io/docs/reference/errors.md#version_conflict): The review changed since `expectedVersion`, or at the same moment.
- [`permission_denied`](https://ownrecord.io/docs/reference/errors.md#permission_denied): You can't refund this brand's payments.

### Example

**Refund and block a stolen card**

Arguments:

```json
{
  "id": "rsk_01m4ttwd3veh9apbewxheq5xr1",
  "reason": "The cardholder doesn't know the customer.",
  "brand_id": "brd_01jbx4m3v8e9t0s6k2c5n7q1wz",
  "idempotency_key": "8d0c5f8e-4b7a-4e43-9b0f-2f6a0c1d9e21"
}
```

Result `output`:

```json
{
  "id": "rsk_01m4ttwd3veh9apbewxheq5xr1",
  "object": "risk_evaluation",
  "livemode": true,
  "brandId": "brd_01m4ttwd3veh9apbewxheq5xh5",
  "subject": {
    "type": "checkout_session",
    "checkoutSessionId": "cs_01m4ttwd3veh9apbewxheq5xr4",
    "walletId": null
  },
  "customerId": "cus_01m4ttwd3veh9apbewxheq5xr5",
  "paymentId": "pay_01m4ttwd3veh9apbewxheq5xr6",
  "stage": "confirm",
  "decision": "review",
  "score": 70,
  "reasons": [
    {
      "code": "first_payment",
      "action": "require_3ds",
      "points": null,
      "detail": "The customer's first payment."
    },
    {
      "code": "new_customer",
      "action": "score",
      "points": 10,
      "detail": "A new customer."
    },
    {
      "code": "country_mismatch_ip_billing",
      "action": "score",
      "points": 20,
      "detail": "IP country DE isn't the billing country HR."
    },
    {
      "code": "country_mismatch_card_billing",
      "action": "score",
      "points": 25,
      "detail": "Card country US isn't the billing country HR."
    },
    {
      "code": "country_mismatch_ip_card",
      "action": "score",
      "points": 15,
      "detail": "IP country DE isn't the card country US."
    },
    {
      "code": "score_review",
      "action": "review",
      "points": null,
      "detail": "Score 70 ≥ 70."
    }
  ],
  "signals": {
    "emailDomain": "corp.example",
    "ipNetwork": "203.0.113.0",
    "ipCountry": "DE",
    "billingCountry": "HR",
    "cardCountry": "US",
    "cardFingerprint": "Xo1abC9dEf2GhI3j",
    "amount": {
      "amount": "90000000",
      "currency": "EUR"
    },
    "topup": true,
    "newCustomer": true,
    "firstPayment": true,
    "disposableEmail": false
  },
  "history": [
    {
      "at": "2026-10-20T09:00:00.000Z",
      "stage": "intent",
      "decision": "require_3ds",
      "score": 30
    },
    {
      "at": "2026-10-20T09:01:00.000Z",
      "stage": "payment_method",
      "decision": "review",
      "score": 70
    },
    {
      "at": "2026-10-20T09:01:30.000Z",
      "stage": "confirm",
      "decision": "review",
      "score": 70
    }
  ],
  "review": {
    "status": "rejected",
    "openedAt": "2026-10-20T09:02:00.000Z",
    "decidedAt": "2026-10-20T11:30:00.000Z",
    "decidedBy": "usr_01m4ttwd3veh9apbewxheq5xh6",
    "note": "The cardholder doesn't know the customer.",
    "refundId": "re_01m4ttwd3veh9apbewxheq5xr8",
    "blocklistEntryIds": ["rbl_01m4ttwd3veh9apbewxheq5xr2", "rbl_01m4ttwd3veh9apbewxheq5xr3"],
    "frozenWalletIds": ["wal_01m4ttwd3veh9apbewxheq5xr7"]
  },
  "createdAt": "2026-10-20T09:00:00.000Z",
  "updatedAt": "2026-10-20T11:30:00.000Z"
}
```

## `risk_settings_get`

**Get the risk settings.** Operation [`risk.settings.get`](https://ownrecord.io/docs/reference/risk-settings-get.md) · Brand level · permission `brands:read` · risk tier `read` · since M9

Returns the brand's risk rules in the mode of the request (spec §20). Until someone changes them the documented
defaults apply (`isDefault: true`, `version: 0`), suited to prepaid credits:

- **New customers** (no payment older than `newCustomer.ageHours`, 168): at most 2 top-ups in 24 hours, a first
  top-up of at most 100 EUR, USD, GBP or CHF, and 3-D Secure on the first payment.
- **Velocity**: per IP network (/24 or /48; 10 attempts and 3 cards an hour), per card (5 attempts in 24 hours) and
  per email domain of new customers (10 an hour; large mail providers exempt).
- **Score**: country mismatches between the IP, the billing address and the card add points (20, 25, 15), so do a
  new customer (10) and an elevated one (40); 20 points ask for 3-D Secure, 75 hold the payment for review.
- **Disposable email** addresses are blocked; blocklists always apply.
- **Fresh balances**: no usage cap until set (`wallet.usageCapUntilAgeHours`).

The counting rules (velocity and the new-customer top-up limits) are on in live mode and off in test mode, where
everyone pays with the same test cards from the same machine; turn them on to try them. Amounts are integer micros
as strings, per currency; a currency without an amount has no limit.

Annotations: `readOnlyHint: true` · `destructiveHint: false` · `idempotentHint: true` · `openWorldHint: false`

### Arguments

| Argument    | Type         | Required | Description                                                                                                                              |
| ----------- | ------------ | -------- | ---------------------------------------------------------------------------------------------------------------------------------------- |
| `entity_id` | ID (`ent_…`) | no       | Optional: the brand's legal entity (ent\_…); `brand_id` alone is enough.                                                                 |
| `brand_id`  | ID (`brd_…`) | no       | The brand to act on (brd\_…), inside your API key's reach. Needed with an organization or entity key; a brand key acts on its own brand. |

- **Brand:** pass `brand_id` with an organization or entity key; a brand key acts on its own brand.
- **Read-only:** changes nothing; `idempotency_key` is ignored.

### Errors

- [`permission_denied`](https://ownrecord.io/docs/reference/errors.md#permission_denied): You can't read this brand's settings.

### Example

**The live-mode defaults**

Arguments:

```json
{
  "brand_id": "brd_01jbx4m3v8e9t0s6k2c5n7q1wz"
}
```

Result `output`:

```json
{
  "object": "risk_settings",
  "brandId": "brd_01m4ttwd3veh9apbewxheq5xh5",
  "livemode": true,
  "isDefault": true,
  "version": 0,
  "updatedAt": null,
  "newCustomer": {
    "ageHours": 168,
    "topups": {
      "enabled": true,
      "limit": 2,
      "windowHours": 24,
      "action": "block"
    },
    "firstTopupMax": {
      "enabled": true,
      "amounts": {
        "CHF": "100000000",
        "EUR": "100000000",
        "GBP": "100000000",
        "USD": "100000000"
      },
      "action": "block"
    },
    "threeDSecureFirstPayment": true
  },
  "velocity": {
    "ipNetwork": {
      "enabled": true,
      "limit": 10,
      "windowHours": 1,
      "action": "block",
      "cardLimit": 3
    },
    "cardFingerprint": {
      "enabled": true,
      "limit": 5,
      "windowHours": 24,
      "action": "block"
    },
    "emailDomain": {
      "enabled": true,
      "limit": 10,
      "windowHours": 1,
      "action": "block",
      "exemptDomains": [
        "aol.com",
        "gmail.com",
        "gmx.at",
        "gmx.de",
        "gmx.net",
        "googlemail.com",
        "hotmail.com",
        "icloud.com",
        "live.com",
        "mail.com",
        "me.com",
        "msn.com",
        "outlook.com",
        "proton.me",
        "protonmail.com",
        "t-online.de",
        "web.de",
        "yahoo.com",
        "yandex.com"
      ]
    }
  },
  "points": {
    "ipBillingMismatch": 20,
    "cardBillingMismatch": 25,
    "ipCardMismatch": 15,
    "elevatedCustomer": 40,
    "newCustomer": 10
  },
  "thresholds": {
    "threeDSecure": 20,
    "review": 75,
    "block": null
  },
  "disposableEmail": {
    "enabled": true,
    "action": "block"
  },
  "wallet": {
    "usageCapUntilAgeHours": null,
    "usageCap": {}
  }
}
```

## `risk_settings_update`

**Update the risk settings.** Operation [`risk.settings.update`](https://ownrecord.io/docs/reference/risk-settings-update.md) · Brand level · permission `brands:write` · risk tier `write` · since M9

Changes the brand's risk rules in the mode of the request. Give only what changes: any group
(`newCustomer`, `velocity`, `points`, `thresholds`, `disposableEmail`, `wallet`) and, within it, any field;
the rest keeps its value (the defaults until the first change). Per-currency amounts (`firstTopupMax.amounts`,
`wallet.usageCap`, integer micros as strings) and `velocity.emailDomain.exemptDomains` are replaced as a whole.

Each rule's `action` is `block` (the payment is refused before it reaches the card), `review` (it goes through,
and waits in the review queue with the customer's wallet frozen) or `require_3ds` (the bank authenticates the
customer). Thresholds must rise: `threeDSecure` ≤ `review` ≤ `block` (null: no score blocks). Windows are 1–168
hours. A usage cap for fresh balances (`wallet.usageCapUntilAgeHours`, 1–720, with `wallet.usageCap`) limits
how much of the credits bought in that time can be reserved or spent; null turns it off.

Pass `expectedVersion` to refuse the change if someone else changed the settings meanwhile. Test and live mode
have their own settings. Needs `brands:write` (owners and admins).

Annotations: `readOnlyHint: false` · `destructiveHint: false` · `idempotentHint: true` · `openWorldHint: false`

### Arguments

| Argument          | Type         | Required | Description                                                                                                                                                                                              |
| ----------------- | ------------ | -------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `newCustomer`     | object       | no       | –                                                                                                                                                                                                        |
| `velocity`        | object       | no       | –                                                                                                                                                                                                        |
| `points`          | object       | no       | –                                                                                                                                                                                                        |
| `thresholds`      | object       | no       | –                                                                                                                                                                                                        |
| `disposableEmail` | object       | no       | –                                                                                                                                                                                                        |
| `wallet`          | object       | no       | –                                                                                                                                                                                                        |
| `expectedVersion` | integer      | no       | (0–9007199254740991)                                                                                                                                                                                     |
| `entity_id`       | ID (`ent_…`) | no       | Optional: the brand's legal entity (ent\_…); `brand_id` alone is enough.                                                                                                                                 |
| `brand_id`        | ID (`brd_…`) | no       | The brand to act on (brd\_…), inside your API key's reach. Needed with an organization or entity key; a brand key acts on its own brand.                                                                 |
| `idempotency_key` | string       | no       | A unique string for this change. Retrying with the same key and arguments never acts twice. When left out, the server generates one and returns it in the result's `idempotency_key`. (1–255 characters) |
| `dry_run`         | boolean      | no       | true: check permissions and rules and compute the result, then roll everything back. Nothing is saved. (default `false`)                                                                                 |

- **Brand:** pass `brand_id` with an organization or entity key; a brand key acts on its own brand.
- **Idempotency:** the result returns the `idempotency_key` used, yours or one the server generated. Retry with it: a call with the same key and arguments never acts twice (keys are kept for 24 hours).
- **Dry run:** supported. `dry_run: true` checks permissions and rules and computes the result, then rolls everything back.

### Errors

- [`validation_failed`](https://ownrecord.io/docs/reference/errors.md#validation_failed): A value is out of range, a currency is unknown, or the thresholds don't rise.
- [`version_conflict`](https://ownrecord.io/docs/reference/errors.md#version_conflict): The settings changed since `expectedVersion`, or at the same moment.
- [`permission_denied`](https://ownrecord.io/docs/reference/errors.md#permission_denied): You can't change this brand's settings.

### Examples

**Hold riskier payments sooner and cap fresh balances**

Arguments:

```json
{
  "thresholds": {
    "review": 60
  },
  "wallet": {
    "usageCapUntilAgeHours": 24,
    "usageCap": {
      "EUR": "20000000"
    }
  },
  "expectedVersion": 0,
  "brand_id": "brd_01jbx4m3v8e9t0s6k2c5n7q1wz",
  "idempotency_key": "8d0c5f8e-4b7a-4e43-9b0f-2f6a0c1d9e21"
}
```

Result `output`:

```json
{
  "object": "risk_settings",
  "brandId": "brd_01m4ttwd3veh9apbewxheq5xh5",
  "livemode": true,
  "isDefault": false,
  "version": 1,
  "updatedAt": "2026-10-20T09:00:00.000Z",
  "newCustomer": {
    "ageHours": 168,
    "topups": {
      "enabled": true,
      "limit": 2,
      "windowHours": 24,
      "action": "block"
    },
    "firstTopupMax": {
      "enabled": true,
      "amounts": {
        "CHF": "100000000",
        "EUR": "100000000",
        "GBP": "100000000",
        "USD": "100000000"
      },
      "action": "block"
    },
    "threeDSecureFirstPayment": true
  },
  "velocity": {
    "ipNetwork": {
      "enabled": true,
      "limit": 10,
      "windowHours": 1,
      "action": "block",
      "cardLimit": 3
    },
    "cardFingerprint": {
      "enabled": true,
      "limit": 5,
      "windowHours": 24,
      "action": "block"
    },
    "emailDomain": {
      "enabled": true,
      "limit": 10,
      "windowHours": 1,
      "action": "block",
      "exemptDomains": [
        "aol.com",
        "gmail.com",
        "gmx.at",
        "gmx.de",
        "gmx.net",
        "googlemail.com",
        "hotmail.com",
        "icloud.com",
        "live.com",
        "mail.com",
        "me.com",
        "msn.com",
        "outlook.com",
        "proton.me",
        "protonmail.com",
        "t-online.de",
        "web.de",
        "yahoo.com",
        "yandex.com"
      ]
    }
  },
  "points": {
    "ipBillingMismatch": 20,
    "cardBillingMismatch": 25,
    "ipCardMismatch": 15,
    "elevatedCustomer": 40,
    "newCustomer": 10
  },
  "thresholds": {
    "threeDSecure": 20,
    "review": 60,
    "block": null
  },
  "disposableEmail": {
    "enabled": true,
    "action": "block"
  },
  "wallet": {
    "usageCapUntilAgeHours": 24,
    "usageCap": {
      "EUR": "20000000"
    }
  }
}
```

**Try the velocity rules in test mode**

Arguments:

```json
{
  "velocity": {
    "ipNetwork": {
      "enabled": true
    },
    "cardFingerprint": {
      "enabled": true
    },
    "emailDomain": {
      "enabled": true
    }
  },
  "brand_id": "brd_01jbx4m3v8e9t0s6k2c5n7q1wz",
  "idempotency_key": "8d0c5f8e-4b7a-4e43-9b0f-2f6a0c1d9e21"
}
```

Result `output`:

```json
{
  "object": "risk_settings",
  "brandId": "brd_01m4ttwd3veh9apbewxheq5xh5",
  "livemode": false,
  "isDefault": false,
  "version": 1,
  "updatedAt": "2026-10-20T09:00:00.000Z",
  "newCustomer": {
    "ageHours": 168,
    "topups": {
      "enabled": false,
      "limit": 2,
      "windowHours": 24,
      "action": "block"
    },
    "firstTopupMax": {
      "enabled": false,
      "amounts": {
        "CHF": "100000000",
        "EUR": "100000000",
        "GBP": "100000000",
        "USD": "100000000"
      },
      "action": "block"
    },
    "threeDSecureFirstPayment": true
  },
  "velocity": {
    "ipNetwork": {
      "enabled": true,
      "limit": 10,
      "windowHours": 1,
      "action": "block",
      "cardLimit": 3
    },
    "cardFingerprint": {
      "enabled": true,
      "limit": 5,
      "windowHours": 24,
      "action": "block"
    },
    "emailDomain": {
      "enabled": true,
      "limit": 10,
      "windowHours": 1,
      "action": "block",
      "exemptDomains": [
        "aol.com",
        "gmail.com",
        "gmx.at",
        "gmx.de",
        "gmx.net",
        "googlemail.com",
        "hotmail.com",
        "icloud.com",
        "live.com",
        "mail.com",
        "me.com",
        "msn.com",
        "outlook.com",
        "proton.me",
        "protonmail.com",
        "t-online.de",
        "web.de",
        "yahoo.com",
        "yandex.com"
      ]
    }
  },
  "points": {
    "ipBillingMismatch": 20,
    "cardBillingMismatch": 25,
    "ipCardMismatch": 15,
    "elevatedCustomer": 40,
    "newCustomer": 10
  },
  "thresholds": {
    "threeDSecure": 20,
    "review": 75,
    "block": null
  },
  "disposableEmail": {
    "enabled": true,
    "action": "block"
  },
  "wallet": {
    "usageCapUntilAgeHours": null,
    "usageCap": {}
  }
}
```
