Rules reference
Learn more about the order in which rules are processed, and how they are structured.
Before creating a rule, it’s important to know the order in which rules are processed, and what payment attributes are available for use when specifying criteria to evaluate. Stripe’s machine-learning fraud systems are able to block many fraudulent payments for you, but if you need to create rules using information that’s unique to your business, there are many supported payment attributes you can make use of.
Rule processing and ordering
When creating a rule, the action it’s going to take determines the order in which it is processed. Each payment is evaluated against the rules you have created and performed in a specific order:
- Request 3DS: Rules that, when used with the Payment Intents API or Checkout, request 3D Secure authentication. These are evaluated before any block, review or allow rules.
- Allow: Rules that allow a payment to be processed. If a payment is allowed, it is not evaluated against any block or review rules.
- Block: Rules that block a payment and reject it. If a payment is rejected, it’s not evaluated against any review rules.
- Review: Rules that allow a payment to be processed but are then placed in review
When evaluating Block, Allow, and Review rules, if a payment should match a rule’s criteria, the respective action is performed and no further rules are evaluated against the payment. If a payment matches an allow rule, it’s processed normally–no block or review rules are subsequently evaluated, even if the payment would also meet their criteria. For instance, an example set of rules might be as follows:
- Allow payments less than
$10
- Allow payments made within the U.S. and with a risk level of
normal
- Block payments where the risk level is
high
- Block payments
greater than $1,000
- Review payments made with a card issued
outside the U.S.
Using the rules above, all payments less than $10 would be processed, regardless of their risk level or where the card used was issued. This is because the first rule allows the payment, so no further rules are evaluated. Similarly, a $1,500 payment made within the U.S. with a normal risk level would also be allowed, despite the rule to block payments over $1,000. This is because of the second rule in the list, allowing payments made within the U.S. and a normal risk level. Once a particular rule is triggered, no further rules are evaluated.
Rule structure
Rules are constructed using two components: the action it should take and the condition to evaluate:
{action} if {condition}
In practice, a rule to block all payments over $1,000 would appear as:
Block if :amount_in_usd: > 1000.00
- The action is
Block
- The condition is
:amount_in_usd: > 1000.00
Actions
A rule can perform one of four actions with a payment that meets its criteria, which are processed in this specific order.
Request 3DS
When used with the Payment Intents API, this rule determines if the customer is prompted to go through 3D Secure authentication. Regardless of matches on this rule, Allow, Block, and Review rules are evaluated after.
Allow
This rule action determines when a payment of a certain criteria should always be allowed, regardless of Stripe’s evaluation and any other rules the payment might match. When a payment matches the criteria in an allow rule, it is processed normally by Stripe and has no further rules evaluated against it. Even when Stripe proceeds with a payment it may nonetheless be declined by the card issuer.
Block
This specifies when a payment should always be blocked by Stripe. If a payment matches the criteria in a block rule, the payment is rejected and no further rules are evaluated.
Review
There might be certain types of payments you want to allow, but still take a closer look at. With review rules, you can place payments in review. This is especially useful to manage payments that aren’t particularly common, such as those with a larger than usual amount or from a country that you don’t often ship to. These payments are still processed, and the customer charged, but you have an additional opportunity to review the order to make sure there are no signs of fraud.
Conditions
If a payment matches a rule’s condition, the corresponding action is taken. A basic condition is, itself, made up of three parts:
[attribute] [operator] [value]
- Attribute: The attribute of a payment (e.g., the amount or type of card)
- Operator: The arithmetic that compares the attribute to the value (e.g., greater than or not equal to)
- Value: The criteria you wish to use (e.g.,
100.00
ordebit
)
Combining both the action and condition together, the structure of a rule is:
{action} if {[attribute] [operator] [value]}
There are four types of conditions that exist, depending on the attribute type:
[string_attribute] [operator] [string_value]
[country_attribute] [operator] [country_value]
[numeric_attribute] [operator] [numeric_value]
[boolean_attribute]
Certain attributes can also be used as a corresponding value within a condition. For instance, you can create a rule to block payments where the country the card was issued does not match against the country the payment was made, using the following attribute and value:
Block if :card_country: != :ip_country:
String attributes
These contain any combination of characters. String attributes and values most commonly represent a piece of text, such as a card’s brand (e.g., visa
, amex
) or risk level (e.g., elevated
). These can be used in rules to allow payments only from a particular country, or block payments made with prepaid cards.
Metadata attributes
These attributes are derived from the metadata you have attached to your payments. Metadata attributes can operate as either strings or numbers. When used as strings, metadata attributes are case-sensitive.
You can use these attributes when creating Stripe Radar rules, enabling you to write rules against any custom business attributes you have passed to Stripe via the metadata field attached to your payments.
Metadata attributes are written in the following structure:
::[metadata_value]
:: [operator]
Suppose we have payments with the following key-value data stored in the metadata field:
Metadata Name | Metadata Value |
---|---|
Customer Age | 22 |
Item ID | 5A381D |
Category ID | groceries |
A rule can be written to place payments that match the following criteria into review.
Review if < 30
You can also write rules using both metadata attributes and other supported attributes mentioned in this document.
For example, you can write a rule that only places a payment in review if the Item ID
matches 5A381D
and the payment amount exceeds US$1,000.
Review if
= '5A381D' and
:amount_in_usd: > 1000
Metadata attributes also support the IN
operator to match against multiple values.
For example, you can write a rule that places a payment in review if the Category ID
is one of “groceries”, “electronics” or “clothing”.
Review if
IN ('groceries', 'electronics', 'clothing')
The INCLUDES
operator can be used with rules for metadata attributes and other string attributes to match substrings.
For example, you can write a rule that places a payment in review if the Item ID
includes the string A381
. This matches “A381”, “5A381D”, “A381D”, “5A381” and more.
Review if
INCLUDES 'A381'
Metadata on Customer and Destination Objects
Metadata can also be accessed on customer and destination objects (if those are used for a given payment). These attributes are written in the following structure:
::[customer|destination]:[metadata_value] :: [operator] |
Suppose you had a customer with the following metadata:
Metadata Name | Metadata Value |
---|---|
Trusted | true |
You could write a rule that always allows payments if the customer’s Trusted
metadata field is true
.
Allow if
= 'true'
Or if you had a destination with the following metadata:
Metadata Name | Metadata Value |
---|---|
Category | new |
You could write a rule that places a payment in review if the destination’s Category
metadata field is new
.
Review if
= 'new'
Country attributes
These make use of two-letter country codes to represent a country, such as US
for United States or CA
for Canada. Country attributes operate the same as string attributes, the only difference being that the value must be a country code.
Numeric attributes
As these contain only numbers, they support more operators than string attributes and values. A payment’s amount is one example of a numeric attribute. You can create a rule to perform an action if the amount is higher, lower, equal, or not equal to the amount you specify.
For numeric attributes that are counts over time windows, the count does not include the payment currently being processed. For example, charge_attempts_per_ip_address_hourly
represents the number of previous charge attempts from a given IP address in the preceding hour. So, for an IP address’s first charge attempt in a given hour, charge_attempts_per_ip_address_hourly
has a value of 0
. For a second charge attempt within the same hour, it has a value of 1
, and so on.
Boolean attributes
A Boolean attribute simply represents whether a particular attribute is true. Unlike string and numeric attributes, there are no operators or values to use. You can use a Boolean attribute to block payments that have been made with a disposable email address, or place payments in review that were made with an anonymous IP address.
Post-authorization attributes
A post-authorization attribute (e.g. :cvc_check:
, :address_zip_check:
, or :address_line1_check:
) requires Stripe to exchange data with card issuers as part of the authorization process. The card issuer verifies this data against the information they have on file for the cardholder and checks that there is a match. Rules that use post-authorization attributes will be executed after rules that don’t use post-authorization attributes. (This won’t affect whether a charge is blocked or not, but may impact which rule the charge is blocked by.)
Also note that if you use a post-authorization attribute in a rule, your customer’s statement may temporarily show an authorization even if the charge is ultimately blocked; the authorization will generally disappear after a few days.
Address and CVC attributes have five possible values:
Attribute value | Explanation |
---|---|
pass |
The data provided is correct. |
fail |
The data provided is incorrect. |
unavailable |
The customer’s card issuer will not check the data provided. Not all card issuers or countries support address verification. |
unchecked |
The data was provided but has not yet been checked. The customer’s card issuer will eventually check the data provided. |
not_provided |
The data was not provided to Stripe. |
Some example rules:
Block if :address_line1_check: = 'fail'
Block if :cvc_check: != 'pass'
Block if :address_zip_check: in ('fail', 'not_provided')
Supported attributes
The payment attributes listed below are supported in rule definitions.
Attribute |
Type | Case Sensitivity | Description |
---|---|---|---|
address_line1_check | String | Yes | A check by the card issuer to match the first line of the provided billing address (typically a street name and number) against the information they have on file for the cardholder. The supported values are: pass, fail, unavailable, unchecked, not_provided. (This is a post-authorization attribute.) |
address_zip_check | String | Yes | A check by the card issuer to match the provided ZIP code against the information they have on file for the cardholder. The supported values are: pass, fail, unavailable, unchecked, not_provided. (This is a post-authorization attribute.) |
amount_in_xyz | Numeric | N/A | The amount of the payment, converted to the currency specified by xyz (e.g., amount_in_usd). Specify one of the following supported currencies and Stripe automatically calculates a converted amount to use: aud, brl, cad, chf, dkk, eur, gbp, hkd, inr, jpy, mxn, nok, nzd, ron, sek, sgd, or usd. For decimal currencies (e.g., usd), rules use the base currency unit rather than sub units (e.g., dollars, not cents) |
auths_per_card_number_daily | Numeric | N/A | The number of times a card number was successfully authorized on your account in the past 24 hours. (The count does not include the payment currently being evaluated.) |
auths_per_card_number_hourly | Numeric | N/A | The number of times a card number was successfully authorized on your account in the past hour. (The count does not include the payment currently being evaluated.) |
auths_per_customer_daily | Numeric | N/A | The number of times a customer was successfully authorized on your account in the past 24 hours. (The count does not include the payment currently being evaluated.) |
auths_per_customer_hourly | Numeric | N/A | The number of times a customer was successfully authorized on your account in the past hour. (The count does not include the payment currently being evaluated.) |
auths_per_ip_address_daily | Numeric | N/A | The number of times an IP address was successfully authorized on your account in the past 24 hours. (The count does not include the payment currently being evaluated.) |
auths_per_ip_address_hourly | Numeric | N/A | The number of times an IP address was successfully authorized on your account in the past hour. (The count does not include the payment currently being evaluated.) |
billing_address | String | No | The full provided cardholder billing address. |
billing_address_line1 | String | No | The first line of the provided cardholder billing address (typically a street name and number). |
billing_address_line2 | String | No | The second line of the provided cardholder billing address (typically an apartment or unit number). |
billing_address_postal_code | String | No | The postal code (ZIP) of the provided cardholder billing address. |
billing_address_city | String | No | The city of the provided cardholder billing address. |
billing_address_state | String | No | The state of the provided cardholder billing address. |
billing_address_country | Country | No | The two-letter code corresponding to the country of the provided cardholder billing address (e.g., US). |
blocks_per_card_number_daily | Numeric | N/A | The number of times a card number was blocked by Stripe’s machine learning models on your account in the past 24 hours. (The count does not include the payment currently being evaluated.) |
blocks_per_card_number_hourly | Numeric | N/A | The number of times a card number was blocked by Stripe’s machine learning models on your account in the past hour. (The count does not include the payment currently being evaluated.) |
blocks_per_customer_daily | Numeric | N/A | The number of times a customer was blocked by Stripe’s machine learning models on your account in the past 24 hours. (The count does not include the payment currently being evaluated.) |
blocks_per_customer_hourly | Numeric | N/A | The number of times a customer was blocked by Stripe’s machine learning models on your account in the past hour. (The count does not include the payment currently being evaluated.) |
blocks_per_ip_address_daily | Numeric | N/A | The number of times an IP address was blocked by Stripe’s machine learning models on your account in the past 24 hours. (The count does not include the payment currently being evaluated.) |
blocks_per_ip_address_hourly | Numeric | N/A | The number of times an IP address was blocked by Stripe’s machine learning models on your account in the past hour. (The count does not include the payment currently being evaluated.) |
card_bin | String | No | The Bank Identification Number (BIN) of the card being used to make the payment. It is the first six digits of the card number. |
card_brand | String | No | The brand of the card being used to make the payment. The supported values are: amex (American Express), visa (Visa), mc (Mastercard), dscvr (Discover), diners (Diners Club), interac (Interac), jcb (JCB), and cup (UnionPay). |
card_country | Country | No | The two-letter code corresponding to the country where the card was issued (e.g., US). |
card_fingerprint | String | Yes | The fingerprint of the card being used to make the payment. The card fingerprint is a unique identifier of a particular card number. |
card_funding | String | No | Whether the card is a prepaid, debit, or credit card. The supported values are: credit, debit, prepaid, unknown. |
card_3d_secure_support | String | No | The level of 3D Secure support for the card being used to make the payment. The supported values are: required, recommended, optional, and not_supported. |
charge_attempts_per_card_number_daily | Numeric | N/A | The number of times a card is charged on your account in the past 24 hours. (The count does not include the payment currently being evaluated.) |
charge_attempts_per_card_number_hourly | Numeric | N/A | The number of times a card is charged on your account in the past hour. (The count does not include the payment currently being evaluated.) |
charge_attempts_per_customer_daily | Numeric | N/A | The number of times a customer is charged on your account in the past 24 hours. (The count does not include the payment currently being evaluated.) |
charge_attempts_per_customer_hourly | Numeric | N/A | The number of times a customer is charged on your account in the past hour. (The count does not include the payment currently being evaluated.) |
charge_attempts_per_ip_address_daily | Numeric | N/A | The number of times an IP address is charged on your account in the past 24 hours. (The count does not include the payment currently being evaluated.) |
charge_attempts_per_ip_address_hourly | Numeric | N/A | The number of times an IP address is charged on your account in the past hour. (The count does not include the payment currently being evaluated.) |
charge_description | String | No | The description supplied with the payment. |
cvc_check | String | Yes | A check by the card issuer to match the provided CVC (also referred to as CVV) against the information they have on file for the cardholder. The supported values are: pass, fail, unavailable, unchecked, not_provided. (This is a post-authorization attribute.) |
declines_per_card_number_daily | Numeric | N/A | The number of times a card number was declined by the card issuer on your account in the past 24 hours. (The count does not include the payment currently being evaluated.) |
declines_per_card_number_hourly | Numeric | N/A | The number of times a card number was declined by the card issuer on your account in the past hour. (The count does not include the payment currently being evaluated.) |
declines_per_customer_daily | Numeric | N/A | The number of times a customer was declined by the card issuer on your account in the past 24 hours. (The count does not include the payment currently being evaluated.) |
declines_per_customer_hourly | Numeric | N/A | The number of times a customer was declined by the card issuer on your account in the past hour. (The count does not include the payment currently being evaluated.) |
declines_per_ip_address_daily | Numeric | N/A | The number of times an IP address was declined by the card issuer on your account in the past 24 hours. (The count does not include the payment currently being evaluated.) |
declines_per_ip_address_hourly | Numeric | N/A | The number of times an IP address was declined by the card issuer on your account in the past hour. (The count does not include the payment currently being evaluated.) |
destination | String | Yes | For Connect users creating destination charges, the destination account on whose behalf the the charge is made (e.g., acct_19KCB9AlaaEw6AgR). |
digital_wallet | String | No | The type of digital wallet used to store payment information. The supported values are: google_pay, amex_express_checkout, apple_pay, masterpass, samsung_pay, unknown, visa_checkout, none. |
String | No | The email address supplied with the payment (e.g., user@example.com). | |
email_domain | String | No | The domain of the email address supplied with the payment (e.g., example.com). |
has_liability_shift | Boolean | N/A | True if the fraud liability has been shifted for this payment. |
ip_address | String | No | The IP address from which the payment originates. |
ip_country | Country | No | The two-letter code corresponding to the country-level geolocation of the IP address from which the payment originates (e.g., GB). |
is_3d_secure | Boolean | N/A | Identifies if the payment uses a 3D Secure source. |
is_3d_secure_authenticated | Boolean | N/A | Identifies if the payment follows a successfully completed 3D Secure verification with authentication. (Authentication may be either risk-based or challenge-based.) |
is_anonymous_ip | Boolean | N/A | Identifies if the IP address from which the payment originates is a known proxy or Tor exit node. This information is updated daily. |
is_checkout | Boolean | N/A | Identifies if the payment is processed through Checkout. (This attribute only applies to payments processed through the new version of Checkout and does not capture payments through legacy Checkout.) |
is_disposable_email | Boolean | N/A | Identifies if the email address supplied with the payment is one used with a known throwaway email address provider. Stripe maintains a list of domains corresponding to throwaway email addresses to provide this attribute. |
is_my_login_ip | Boolean | N/A | Identifies if the IP address from which the payment originates has ever been used to log into your Stripe account. This attribute can be used as a proxy for "is my IP address." |
is_recurring | Boolean | N/A | Identifies if the payment is recurring. (E.g., from subscriptions.) |
risk_level | String | No | The risk level of a given payment, as determined by Stripe. The supported values are: normal, elevated, highest, not_assessed. |
risk_score | Numeric | No | The risk score of a given payment, as determined by Stripe. The values range between 0 (least risky) and 100 (riskiest). A risk score of 65 or above corresponds to a risk level of elevated, while a risk score of 75 or above corresponds to a risk level of highest. |
shipping_address | String | No | The full provided shipping address. |
shipping_address_line1 | String | No | The first line of the provided shipping address (typically a street name and number). |
shipping_address_line2 | String | No | The second line of the provided shipping address (typically an apartment or unit number). |
shipping_address_postal_code | String | No | The postal code (ZIP) of the provided shipping address. |
shipping_address_city | String | No | The city of the provided shipping address. |
shipping_address_state | String | No | The state of the provided shipping address. |
shipping_address_country | Country | No | The two-letter code corresponding to the country of the provided shipping address (e.g., US). |
is_off_session | Boolean | N/A | Indicates when a Stripe Billing payment is not triggered by direct user action, or when the off_session flag is set at PaymentIntent confirmation. |
The email_domain and is_disposable_email attributes make use of an email address found in any of the following fields:
- The
receipt_email
of the payment - The
description
of the payment - The
name
of the card (if an email address has been provided as the cardholder name) - The
email
of the customer that the payment was created on - The
description
of the customer
Converted amounts
When using amount_in_xyz
, Stripe automatically determines the converted amount of any payment when checking if the amount matches your chosen criteria. For example, if you create a rule using amount_in_usd
to block all payments greater than $1,000 USD, Stripe would block a £900.00 GBP payment as its equivalent converted USD value would be approximately $1,200.00.
Operators
A condition’s operator denotes the comparison between the payment’s attribute and the value you provide. There are different operators available, depending on the type of attribute being used.
Operator | String | Metadata | Country | Numeric | Description | Example |
---|---|---|---|---|---|---|
= | ✔︎ | ✔︎ | ✔︎ | ✔︎ | Equal to | :card_country: = 'us' |
!= | ✔︎ | ✔︎ | ✔︎ | ✔︎ | Not equal to | :card_funding: != 'prepaid' |
< | ✔︎ | Less than | :amount_in_gbp: < 10.00 |
|||
> | ✔︎ | Greater than | :amount_in_usd: > 500.00 |
|||
<= | ︎ | ✔︎ | Less than or equal to | :amount_in_eur: <= 100.00 |
||
>= | ✔︎ | Greater than or equal to | :amount_in_cad: >= 10.00 |
|||
IN | ✔ | ✔︎ | ✔ | ✔︎ | Is in the group | :card_country: IN ('gb', 'ie') |
INCLUDES | ✔ | ✔︎ | ✔ | Contains the string | :ip_address: INCLUDES '192.168' |
Lists
You can reference a group of values in your rules through lists. All list aliases referenced in rules must start with @
. To construct a rule referencing a list you need to follow the structure:
{action} [attribute] in [list]
For example, say you have a list of card countries you’d like to block. You could write a rule using several OR
clauses:
Block if :card_country: = 'CA' OR :card_country: = 'DE' OR :card_country: = 'AE'
You could also write a rule using an inline list:
Block if :card_country: IN ('CA', 'DE', 'AE')
You could also create a list of card countries you’d like to block, named card_countries_to_block
. You can then add the countries of your choice to the list and reference that list in a rule:
Block if :card_country: in @card_countries_to_block
Not only is the rule using a list more concise, but it is also much easier to edit and add a large number of items to.
Missing attributes
Typical rule conditions refer to attributes set on every payment, such as :card_country:
(which is set on every card-based charge) or a metadata attribute you always send with your payment requests. However, there are scenarios in which an attribute might be missing, for example:
-
You have different checkout flows on your site, and some of them do not collect customers’ email addresses
-
You’ve only recently started using Stripe.js, and so
:ip_country:
is available on new payments, but not available on historical payments (which we search when previewing rules) -
For some of your payments, a bug in your integration fails to set an expected metadata key
How rule conditions evaluate missing attributes
Consider the rule Block if :email_domain: = 'definitelyfraud.com'
. If you didn’t collect the customer’s email address, the :email_domain:
attribute would be missing, and—as you might expect—the rule condition would not match the payment.
Now consider the rule Review if :email_domain: != 'definitelysafe.com'
. If the :email_domain:
attribute is missing, this rule also does not match the payment. This result might seem a bit surprising, as a missing value is indeed not the same as 'definitelysafe.com'
. But we’ve found it’s best to interpret != 'definitelysafe.com'
to mean “the attribute has some value other than 'definitelysafe.com'
,” which a missing attribute does not satisfy.
More generally: any comparison (e.g., =
, !=
, >
, <
) of a missing feature against another static value or feature (missing or present) always returns false.
Explicit handling with the is_missing
function
If you would like to explicitly check for the existence of an attribute or metadata attribute, use the is_missing
function. Provide this function with the attribute or metadata key that may be missing.
For example, you could write a rule to match all payments where you do not have access to a customer’s email address:
Review if is_missing(:email_domain:)
Or you might write a rule to match all payments for which a certain metadata attribute is set:
Review if !(is_missing( ))
The is_missing
function can also be used in OR
or AND
conjunctions:
Review if is_missing(:email_domain:) OR :email_domain: IN ('yopmail.net', 'yandex.ru')
Complex conditions
You can build complex conditions by joining together basic conditions using the operators AND, OR, and NOT. You can also use their symbolic equivalents: &&, ||, and ! respectively.
Similar to programming languages such as C, Python, and SQL, Stripe supports standard operator precedence (order of operations). For instance, the complex condition:
{condition_X} OR NOT {condition_Y} AND {condition_Z}
is interpreted as:
{condition_X} OR ((NOT {condition_Y}) AND {condition_Z})
Sub-conditional grouping within complex conditions is also supported using parentheses. For instance, the prior example can be amended to explicitly change the evaluation order of sub-predicates:
({condition_X} OR (NOT {condition_Y})) AND {condition_Z}
{condition_X} OR NOT ({condition_Y} AND {condition_Z})
By using parentheses in different locations, each of these complex conditions lead to different results.
Valid conditions
The following conditions are examples of correct use of attributes and a supported operator:
:card_brand: = 'amex'
:card_country: != 'US'
:amount_in_usd: >= 1000.00
:is_anonymous_ip:
Invalid conditions
When creating a rule, you’re provided with feedback if you attempt to use a condition that is invalid. For reference, the following are examples of invalid conditions, where the value for an attribute or the operator used is not supported:
:risk_level: < 'highest'
(string values can only make use of = or != operators):ip_country: = 'Canada'
(country values must be expressed in two-letter short code):amount_in_usd: >= 'one thousand dollars'
(numeric values must be expressed in numbers):is_anonymous_ip: = 'true'
(Boolean attributes are not used with operators or values)