Skip to content

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 · 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

ArgumentTypeRequiredDescription
kindone of email, card_fingerprint, ip_range, countryyes–
valuestringyes(1–320 characters)
reasonstringno(1–500 characters)
entity_idID (ent_…)noOptional: the brand's legal entity (ent_…); brand_id alone is enough.
brand_idID (brd_…)noThe 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_keystringnoA 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_runbooleannotrue: 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

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 · 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

ArgumentTypeRequiredDescription
idID (rbl_…)yes–
entity_idID (ent_…)noOptional: the brand's legal entity (ent_…); brand_id alone is enough.
brand_idID (brd_…)noThe 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_keystringnoA 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_runbooleannotrue: 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

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 · 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

ArgumentTypeRequiredDescription
kindone of email, card_fingerprint, ip_range, countrynoEntries of one kind.
valuestringnoThe entry for one value (with kind; written as you like). (1–320 characters)
limitintegerno(1–100)
starting_afterID (rbl_…)noThe next_cursor of the previous page.
entity_idID (ent_…)noOptional: the brand's legal entity (ent_…); brand_id alone is enough.
brand_idID (brd_…)noThe 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

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 · 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

ArgumentTypeRequiredDescription
idID (rsk_…)yes–
entity_idID (ent_…)noOptional: the brand's legal entity (ent_…); brand_id alone is enough.
brand_idID (brd_…)noThe 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

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 · 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

ArgumentTypeRequiredDescription
paymentIdID (pay_…)noThe evaluation of one payment (pay_…).
checkoutSessionIdID (cs_…)noThe evaluation of one checkout (cs_…).
customerIdID (cus_…)noA customer's evaluations (cus_…).
decisionone of allow, require_3ds, review, blocknoOnly this decision (e.g. block).
limitintegerno(1–100)
starting_afterID (rsk_…)noThe next_cursor of the previous page.
entity_idID (ent_…)noOptional: the brand's legal entity (ent_…); brand_id alone is enough.
brand_idID (brd_…)noThe 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

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 · 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

ArgumentTypeRequiredDescription
idID (rsk_…)yes–
notestringno(1–1000 characters)
expectedVersionintegerno(1–9007199254740991)
entity_idID (ent_…)noOptional: the brand's legal entity (ent_…); brand_id alone is enough.
brand_idID (brd_…)noThe 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_keystringnoA 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_runbooleannotrue: 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

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 · 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

ArgumentTypeRequiredDescription
idID (rsk_…)yes–
entity_idID (ent_…)noOptional: the brand's legal entity (ent_…); brand_id alone is enough.
brand_idID (brd_…)noThe 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

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 · 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

ArgumentTypeRequiredDescription
statusone of pending, approved, rejectednoDefault pending: the queue.
customerIdID (cus_…)noReviews of one customer (cus_…).
limitintegerno(1–100)
starting_afterID (rsk_…)noThe next_cursor of the previous page.
entity_idID (ent_…)noOptional: the brand's legal entity (ent_…); brand_id alone is enough.
brand_idID (brd_…)noThe 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

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 · 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

ArgumentTypeRequiredDescription
idID (rsk_…)yes–
reasonstringyes(1–1000 characters)
refundbooleanno–
blockobjectno–
expectedVersionintegerno(1–9007199254740991)
entity_idID (ent_…)noOptional: the brand's legal entity (ent_…); brand_id alone is enough.
brand_idID (brd_…)noThe 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_keystringnoA 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_runbooleannotrue: 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

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 · 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

ArgumentTypeRequiredDescription
entity_idID (ent_…)noOptional: the brand's legal entity (ent_…); brand_id alone is enough.
brand_idID (brd_…)noThe 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

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 · 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

ArgumentTypeRequiredDescription
newCustomerobjectno–
velocityobjectno–
pointsobjectno–
thresholdsobjectno–
disposableEmailobjectno–
walletobjectno–
expectedVersionintegerno(0–9007199254740991)
entity_idID (ent_…)noOptional: the brand's legal entity (ent_…); brand_id alone is enough.
brand_idID (brd_…)noThe 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_keystringnoA 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_runbooleannotrue: 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

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": {}
  }
}