---
title: "Evaluate a planned ACH transaction"
method: POST
path: "/processor/signal/evaluate"
tags: ["plaid"]
---

# Evaluate a planned ACH transaction

`POST /processor/signal/evaluate`

Use `/processor/signal/evaluate` to evaluate a planned ACH transaction to get a return risk assessment and additional risk signals.

`/processor/signal/evaluate` uses Rulesets that are configured on the end customer's Dashboard and can be used with either the Signal Transaction Scores product or the Balance product. Which product is used will be determined by the `ruleset_key` that you provide. Note that only customer-configured rulesets work with this endpoint; as a processor partner, you cannot create or configure your own rulesets. For more details, see [Signal Rules](https://plaid.com/docs/signal/signal-rules/).

Note: This request may have higher latency if Signal Transaction Scores is being added to an existing Item for the first time, or when using a Balance-only ruleset. This is because Plaid must communicate directly with the institution to request data.

## Request body

- ProcessorSignalEvaluateRequest — ProcessorSignalEvaluateRequest defines the request schema for `/processor/signal/evaluate`
  - `client_id` string — Your Plaid API `client_id`. The `client_id` is required and may be provided either in the `PLAID-CLIENT-ID` header or as part of a request body.
  - `secret` string — Your Plaid API `secret`. The `secret` is required and may be provided either in the `PLAID-SECRET` header or as part of a request body.
  - `processor_token` string, required — The processor token obtained from the Plaid integration partner. Processor tokens are in the format: `processor-<environment>-<identifier>`
  - `client_transaction_id` string, required — The unique ID that you would like to use to refer to this transaction. For your convenience mapping your internal data, you could use your internal ID/identifier for this transaction. The max length for this field is 36 characters.
  - `amount` number, double, required — The transaction amount, in USD (e.g. `102.05`)
  - `user_present` boolean, nullable — `true` if the end user is present while initiating the ACH transfer and the endpoint is being called; `false` otherwise (for example, when the ACH transfer is scheduled and the end user is not present, or you call this endpoint after the ACH transfer but before submitting the Nacha file for ACH processing).
  - `client_user_id` string — A unique ID that identifies the end user in your system. This ID is used to correlate requests by a user with multiple Items. Personally identifiable information, such as an email address or phone number, should not be used in the `client_user_id`.
  - `is_recurring` boolean, nullable — **true** if the ACH transaction is a recurring transaction; **false** otherwise.
  - `default_payment_method` string, nullable — The default ACH payment method to complete the transaction. `SAME_DAY_ACH`: Same Day ACH by Nacha. The debit transaction is processed and settled on the same day. `STANDARD_ACH`: Standard ACH by Nacha. `MULTIPLE_PAYMENT_METHODS`: If there is no default debit rail or there are multiple payment methods. Possible values: `SAME_DAY_ACH`, `STANDARD_ACH`, `MULTIPLE_PAYMENT_METHODS`
  - `user` SignalUser — Details about the end user initiating the transaction (i.e., the account holder). These fields are optional, but strongly recommended to increase the accuracy of results when using Signal Transaction Scores. When using a Balance-only ruleset, if the Signal Addendum has been signed, these fields are ignored; if the Addendum has not been signed, using these fields will result in an error.
    - `name` SignalPersonName, nullable — The user's legal name
      - `prefix` string, nullable — The user's name prefix (e.g. "Mr.")
      - `given_name` string, nullable — The user's given name. If the user has a one-word name, it should be provided in this field.
      - `middle_name` string, nullable — The user's middle name
      - `family_name` string, nullable — The user's family name / surname
      - `suffix` string, nullable — The user's name suffix (e.g. "II")
    - `phone_number` string, nullable — The user's phone number, in E.164 format: +{countrycode}{number}. For example: "+14151234567"
    - `email_address` string, nullable — The user's email address.
    - `address` SignalAddressData, nullable — Data about the components comprising an address.
      - `city` string — The full city name
      - `region` string, nullable — The region or state Example: `"NC"`
      - `street` string — The full street address Example: `"564 Main Street, APT 15"`
      - `postal_code` string, nullable — The postal code
      - `country` string, nullable — The ISO 3166-1 alpha-2 country code
  - `device` SignalDevice — Details about the end user's device. These fields are optional, but strongly recommended to increase the accuracy of results when using Signal Transaction Scores. When using a Balance-only Ruleset, these fields are ignored if the Signal Addendum has been signed; if it has not been signed, using these fields will result in an error.
    - `ip_address` string, nullable — The IP address of the device that initiated the transaction
    - `user_agent` string, nullable — The user agent of the device that initiated the transaction (e.g. "Mozilla/5.0")
  - `ruleset_key` string, nullable — The key of the ruleset to use for this transaction. You can configure a ruleset using the Plaid Dashboard, under [Signal->Rules](https://dashboard.plaid.com/signal/risk-profiles). If not provided, for customers who began using Signal Transaction Scores before October 15, 2025, by default, no ruleset will be used; for customers who began using Signal Transaction Scores after that date, or for Balance customers, the `default` ruleset will be used. For more details, or to opt out of using a ruleset, see [Signal Rules](https://plaid.com/docs/signal/signal-rules/).

## Response `200`

OK

- ProcessorSignalEvaluateResponse — ProcessorSignalEvaluateResponse defines the response schema for `/processor/signal/evaluate`
  - `request_id` string, required — A unique identifier for the request, which can be used for troubleshooting. This identifier, like all Plaid identifiers, is case sensitive.
  - `scores` SignalScores, nullable, required — Risk scoring details broken down by risk category. When using a Balance-only ruleset, this object will not be returned.
    - `customer_initiated_return_risk` CustomerInitiatedReturnRisk — The object contains a risk score and a risk tier that evaluate the transaction return risk of an unauthorized debit. Common return codes in this category include: "R05", "R07", "R10", "R11", "R29". These returns typically have a return time frame of up to 60 calendar days. During this period, customers of financial institutions can dispute a transaction as unauthorized.
      - `score` integer, required — A score from 1-99 that indicates the transaction return risk: a higher risk score suggests a higher return likelihood.
      - `risk_tier` integer, required — DEPRECATED. Use Signal Rules instead to transform the `score` into a useful action. A tier corresponding to the projected likelihood that the transaction, if initiated, will be subject to a return. In the `customer_initiated_return_risk` object, there are five risk tiers corresponding to the scores: 1: Predicted customer-initiated return incidence rate between 0.00% - 0.02% 2: Predicted customer-initiated return incidence rate between 0.02% - 0.05% 3: Predicted customer-initiated return incidence rate between 0.05% - 0.1% 4: Predicted customer-initiated return incidence rate between 0.1% - 0.5% 5: Predicted customer-initiated return incidence rate greater than 0.5%
    - `bank_initiated_return_risk` BankInitiatedReturnRisk — The object contains a risk score and a risk tier that evaluate the transaction return risk because an account is overdrawn or because an ineligible account is used. Common return codes in this category include: "R01", "R02", "R03", "R04", "R06", "R08", "R09", "R13", "R16", "R17", "R20", "R23". These returns have a turnaround time of 2 banking days.
      - `score` integer, required — A score from 1-99 that indicates the transaction return risk: a higher risk score suggests a higher return likelihood.
      - `risk_tier` integer, required — DEPRECATED. Use Signal Rules instead to transform the `score` into a useful action. In the `bank_initiated_return_risk` object, there are eight risk tiers corresponding to the scores: 1: Predicted bank-initiated return incidence rate between 0.0% - 0.5% 2: Predicted bank-initiated return incidence rate between 0.5% - 1.5% 3: Predicted bank-initiated return incidence rate between 1.5% - 3% 4: Predicted bank-initiated return incidence rate between 3% - 5% 5: Predicted bank-initiated return incidence rate between 5% - 10% 6: Predicted bank-initiated return incidence rate between 10% - 15% 7: Predicted bank-initiated return incidence rate between 15% and 50% 8: Predicted bank-initiated return incidence rate greater than 50%
  - `core_attributes` SignalEvaluateCoreAttributes — The core attributes object contains additional data that can be used to assess the ACH return risk. If using a Balance-only ruleset, only `available_balance` and `current_balance` will be returned as core attributes. If using a Signal Transaction Scores ruleset, over 80 core attributes will be returned. Examples of attributes include: `available_balance` and `current_balance`: The balance in the ACH transaction funding account `days_since_first_plaid_connection`: The number of days since the first time the Item was connected to an application via Plaid `plaid_connections_count_7d`: The number of times the Item has been connected to applications via Plaid over the past 7 days `plaid_connections_count_30d`: The number of times the Item has been connected to applications via Plaid over the past 30 days `total_plaid_connections_count`: The number of times the Item has been connected to applications via Plaid `is_savings_or_money_market_account`: Indicates whether the ACH transaction funding account is a savings/money market account For the full list and detailed documentation of core attributes available, or to request that core attributes not be returned, contact sales or your Plaid account manager.
    - `unauthorized_transactions_count_7d` integer, nullable — We parse and analyze historical transaction metadata to identify the number of possible past returns due to unauthorized transactions over the past 7 days from the account that will be debited.
    - `unauthorized_transactions_count_30d` integer, nullable — We parse and analyze historical transaction metadata to identify the number of possible past returns due to unauthorized transactions over the past 30 days from the account that will be debited.
    - `unauthorized_transactions_count_60d` integer, nullable — We parse and analyze historical transaction metadata to identify the number of possible past returns due to unauthorized transactions over the past 60 days from the account that will be debited.
    - `unauthorized_transactions_count_90d` integer, nullable — We parse and analyze historical transaction metadata to identify the number of possible past returns due to unauthorized transactions over the past 90 days from the account that will be debited.
    - `nsf_overdraft_transactions_count_7d` integer, nullable — We parse and analyze historical transaction metadata to identify the number of possible past returns due to non-sufficient funds/overdrafts over the past 7 days from the account that will be debited.
    - `nsf_overdraft_transactions_count_30d` integer, nullable — We parse and analyze historical transaction metadata to identify the number of possible past returns due to non-sufficient funds/overdrafts over the past 30 days from the account that will be debited.
    - `nsf_overdraft_transactions_count_60d` integer, nullable — We parse and analyze historical transaction metadata to identify the number of possible past returns due to non-sufficient funds/overdrafts over the past 60 days from the account that will be debited.
    - `nsf_overdraft_transactions_count_90d` integer, nullable — We parse and analyze historical transaction metadata to identify the number of possible past returns due to non-sufficient funds/overdrafts over the past 90 days from the account that will be debited.
    - `days_since_first_plaid_connection` integer, nullable — The number of days since the first time the Item was connected to an application via Plaid
    - `plaid_connections_count_7d` integer, nullable — The number of times the Item has been connected to applications via Plaid over the past 7 days
    - `plaid_connections_count_30d` integer, nullable — The number of times the Item has been connected to applications via Plaid over the past 30 days
    - `total_plaid_connections_count` integer, nullable — The total number of times the Item has been connected to applications via Plaid
    - `is_savings_or_money_market_account` boolean, nullable — Indicates if the ACH transaction funding account is a savings/money market account
    - `total_credit_transactions_amount_10d` number, double, nullable — The total credit (inflow) transaction amount over the past 10 days from the account that will be debited
    - `total_debit_transactions_amount_10d` number, double, nullable — The total debit (outflow) transaction amount over the past 10 days from the account that will be debited
    - `p50_credit_transactions_amount_28d` number, double, nullable — The 50th percentile of all credit (inflow) transaction amounts over the past 28 days from the account that will be debited
    - `p50_debit_transactions_amount_28d` number, double, nullable — The 50th percentile of all debit (outflow) transaction amounts over the past 28 days from the account that will be debited
    - `p95_credit_transactions_amount_28d` number, double, nullable — The 95th percentile of all credit (inflow) transaction amounts over the past 28 days from the account that will be debited
    - `p95_debit_transactions_amount_28d` number, double, nullable — The 95th percentile of all debit (outflow) transaction amounts over the past 28 days from the account that will be debited
    - `days_with_negative_balance_count_90d` integer, nullable — The number of days within the past 90 days when the account that will be debited had a negative end-of-day available balance
    - `p90_eod_balance_30d` number, double, nullable — The 90th percentile of the end-of-day available balance over the past 30 days of the account that will be debited
    - `p90_eod_balance_60d` number, double, nullable — The 90th percentile of the end-of-day available balance over the past 60 days of the account that will be debited
    - `p90_eod_balance_90d` number, double, nullable — The 90th percentile of the end-of-day available balance over the past 90 days of the account that will be debited
    - `p10_eod_balance_30d` number, double, nullable — The 10th percentile of the end-of-day available balance over the past 30 days of the account that will be debited
    - `p10_eod_balance_60d` number, double, nullable — The 10th percentile of the end-of-day available balance over the past 60 days of the account that will be debited
    - `p10_eod_balance_90d` number, double, nullable — The 10th percentile of the end-of-day available balance over the past 90 days of the account that will be debited
    - `available_balance` number, double, nullable — Available balance, as of the `balance_last_updated` time. The available balance is the current balance less any outstanding holds or debits that have not yet posted to the account.
    - `current_balance` number, double, nullable — Current balance, as of the `balance_last_updated` time. The current balance is the total amount of funds in the account.
    - `balance_last_updated` string, date-time, nullable — Timestamp in [ISO 8601](https://wikipedia.org/wiki/ISO_8601) format (YYYY-MM-DDTHH:mm:ssZ) indicating the last time that the balance for the given account has been updated.
    - `phone_change_count_28d` integer, nullable — The number of times the account's phone numbers on file have changed over the past 28 days
    - `phone_change_count_90d` integer, nullable — The number of times the account's phone numbers on file have changed over the past 90 days
    - `email_change_count_28d` integer, nullable — The number of times the account's email addresses on file have changed over the past 28 days
    - `email_change_count_90d` integer, nullable — The number of times the account's email addresses on file have changed over the past 90 days
    - `address_change_count_28d` integer, nullable — The number of times the account's addresses on file have changed over the past 28 days
    - `address_change_count_90d` integer, nullable — The number of times the account's addresses on file have changed over the past 90 days
    - `plaid_non_oauth_authentication_attempts_count_3d` integer, nullable — The number of non-OAuth authentication attempts via Plaid for this bank account over the past 3 days
    - `plaid_non_oauth_authentication_attempts_count_7d` integer, nullable — The number of non-OAuth authentication attempts via Plaid for this bank account over the past 7 days
    - `plaid_non_oauth_authentication_attempts_count_30d` integer, nullable — The number of non-OAuth authentication attempts via Plaid for this bank account over the past 30 days
    - `failed_plaid_non_oauth_authentication_attempts_count_3d` integer, nullable — The number of failed non-OAuth authentication attempts via Plaid for this bank account over the past 3 days
    - `failed_plaid_non_oauth_authentication_attempts_count_7d` integer, nullable — The number of failed non-OAuth authentication attempts via Plaid for this bank account over the past 7 days
    - `failed_plaid_non_oauth_authentication_attempts_count_30d` integer, nullable — The number of failed non-OAuth authentication attempts via Plaid for this bank account over the past 30 days
    - `debit_transactions_count_10d` integer, nullable — The total number of debit (outflow) transactions over the past 10 days from the account that will be debited
    - `credit_transactions_count_10d` integer, nullable — The total number of credit (inflow) transactions over the past 10 days from the account that will be debited
    - `debit_transactions_count_30d` integer, nullable — The total number of debit (outflow) transactions over the past 30 days from the account that will be debited
    - `credit_transactions_count_30d` integer, nullable — The total number of credit (inflow) transactions over the past 30 days from the account that will be debited
    - `debit_transactions_count_60d` integer, nullable — The total number of debit (outflow) transactions over the past 60 days from the account that will be debited
    - `credit_transactions_count_60d` integer, nullable — The total number of credit (inflow) transactions over the past 60 days from the account that will be debited
    - `debit_transactions_count_90d` integer, nullable — The total number of debit (outflow) transactions over the past 90 days from the account that will be debited
    - `credit_transactions_count_90d` integer, nullable — The total number of credit (inflow) transactions over the past 90 days from the account that will be debited
    - `total_debit_transactions_amount_30d` number, double, nullable — The total debit (outflow) transaction amount over the past 30 days from the account that will be debited
    - `total_credit_transactions_amount_30d` number, double, nullable — The total credit (inflow) transaction amount over the past 30 days from the account that will be debited
    - `total_debit_transactions_amount_60d` number, double, nullable — The total debit (outflow) transaction amount over the past 60 days from the account that will be debited
    - `total_credit_transactions_amount_60d` number, double, nullable — The total credit (inflow) transaction amount over the past 60 days from the account that will be debited
    - `total_debit_transactions_amount_90d` number, double, nullable — The total debit (outflow) transaction amount over the past 90 days from the account that will be debited
    - `total_credit_transactions_amount_90d` number, double, nullable — The total credit (inflow) transaction amount over the past 90 days from the account that will be debited
    - `p50_eod_balance_30d` number, double, nullable — The 50th percentile of the end-of-day available balance over the past 30 days of the account that will be debited
    - `p50_eod_balance_60d` number, double, nullable — The 50th percentile of the end-of-day available balance over the past 60 days of the account that will be debited
    - `p50_eod_balance_90d` number, double, nullable — The 50th percentile of the end-of-day available balance over the past 90 days of the account that will be debited
    - `p50_eod_balance_31d_to_60d` number, double, nullable — The 50th percentile of the end-of-day available balance between day 31 and day 60 over the past 60 days of the account that will be debited
    - `p50_eod_balance_61d_to_90d` number, double, nullable — The 50th percentile of the end-of-day available balance between day 61 and day 90 over the past 90 days of the account that will be debited
    - `p90_eod_balance_31d_to_60d` number, double, nullable — The 90th percentile of the end-of-day available balance between day 31 and day 60 over the past 60 days of the account that will be debited
    - `p90_eod_balance_61d_to_90d` number, double, nullable — The 90th percentile of the end-of-day available balance between day 61 and day 90 over the past 90 days of the account that will be debited
    - `p10_eod_balance_31d_to_60d` number, double, nullable — The 10th percentile of the end-of-day available balance between day 31 and day 60 over the past 60 days of the account that will be debited
    - `p10_eod_balance_61d_to_90d` number, double, nullable — The 10th percentile of the end-of-day available balance between day 61 and day 90 over the past 90 days of the account that will be debited
    - `transactions_last_updated` string, date-time, nullable — Timestamp in [ISO 8601](https://wikipedia.org/wiki/ISO_8601) format (YYYY-MM-DDTHH:mm:ssZ) indicating the last time that the transactions for the given account have been updated.
    - `is_account_closed` boolean, nullable — Indicates if the account that will be debited is closed
    - `is_account_frozen_or_restricted` boolean, nullable — Indicates if the account that will be debited is either frozen or restricted
    - `distinct_ip_addresses_count_3d` integer, nullable — The number of distinct IP addresses linked to the same bank account during Plaid authentication in the last 3 days
    - `distinct_ip_addresses_count_7d` integer, nullable — The number of distinct IP addresses linked to the same bank account during Plaid authentication in the last 7 days
    - `distinct_ip_addresses_count_30d` integer, nullable — The number of distinct IP addresses linked to the same bank account during Plaid authentication in the last 30 days (max 100)
    - `distinct_ip_addresses_count_90d` integer, nullable — The number of distinct IP addresses linked to the same bank account during Plaid authentication in the last 90 days (max 100)
    - `distinct_user_agents_count_3d` integer, nullable — The number of distinct user agents linked to the same bank account during Plaid authentication in the last 3 days
    - `distinct_user_agents_count_7d` integer, nullable — The number of distinct user agents linked to the same bank account during Plaid authentication in the last 7 days
    - `distinct_user_agents_count_30d` integer, nullable — The number of distinct user agents linked to the same bank account during Plaid authentication in the last 30 days
    - `distinct_user_agents_count_90d` integer, nullable — The number of distinct user agents linked to the same bank account during Plaid authentication in the last 90 days
    - `distinct_ssl_tls_connection_sessions_count_3d` integer, nullable — The number of distinct SSL/TLS connection sessions linked to the same bank account during Plaid authentication in the last 3 days
    - `distinct_ssl_tls_connection_sessions_count_7d` integer, nullable — The number of distinct SSL/TLS connection sessions linked to the same bank account during Plaid authentication in the last 7 days
    - `distinct_ssl_tls_connection_sessions_count_30d` integer, nullable — The number of distinct SSL/TLS connection sessions linked to the same bank account during Plaid authentication in the last 30 days
    - `distinct_ssl_tls_connection_sessions_count_90d` integer, nullable — The number of distinct SSL/TLS connection sessions linked to the same bank account during Plaid authentication in the last 90 days
    - `days_since_account_opening` integer, nullable — The number of days since the bank account was opened, as reported by the financial institution
    - `balance_to_transaction_amount_ratio` number, double, nullable — Taking `available_or_current_balance` and dividing it by the transaction amount. Useful to say "10% buffer", for example. This is a convenience function to build Signal Rules upon.
  - `ruleset` Ruleset, nullable — Details about the transaction result after evaluation by the requested Ruleset. If a `ruleset_key` is not provided, for customers who began using Signal Transaction Scores before October 15, 2025, by default, this field will be omitted. To learn more, see [Signal Rules](https://plaid.com/docs/signal/signal-rules/).
    - `ruleset_key` string — The key of the Ruleset used for this transaction.
    - `result` 'ACCEPT' | 'REROUTE' | 'REVIEW', required — The result of the rule that was triggered for this transaction. `ACCEPT`: Accept the transaction for processing. `REROUTE`: Reroute the transaction to a different payment method, as this transaction is too risky. `REVIEW`: Review the transaction before proceeding.
    - `triggered_rule_details` RuleDetails, nullable — Rules are run in numerical order. The first rule with a logic match is triggered. These are the details of that rule.
      - `internal_note` string — An optional message attached to the triggered rule, defined within the Dashboard, for your internal use. Useful for debugging, such as "Account appears to be closed."
      - `custom_action_key` string — A string key, defined within the Dashboard, used to trigger programmatic behavior for a certain result. For instance, you could optionally choose to define a "3-day-hold" `custom_action_key` for an ACCEPT result.
    - `outcome` string — The evaluated outcome for this transaction. This field is deprecated, use `result` or `triggered_rule_details.custom_action_key` instead.
  - `warnings` SignalWarning[] — If bank information was not available to be used in the Signal Transaction Scores model, this array contains warnings describing why bank data is missing. If you want to receive an API error instead of scores in the case of missing bank data, file a support ticket or contact your Plaid account manager.
    - `warning_type` string — A broad categorization of the warning. Safe for programmatic use.
    - `warning_code` string — The warning code identifies a specific kind of warning that pertains to the error causing bank data to be missing. Safe for programmatic use. For more details on warning codes, please refer to Plaid standard error codes documentation. If you receive the `ITEM_LOGIN_REQUIRED` warning, we recommend re-authenticating your user by implementing Link's update mode. This will guide your user to fix their credentials, allowing Plaid to start fetching data again for future requests.
    - `warning_message` string — A developer-friendly representation of the warning type. This may change over time and is not safe for programmatic use.

## Other responses

- `default` — Error response.

---

[API](https://skmtc.net/plaid/apis/the-plaid-api.md) · [All operations](https://skmtc.net/plaid/apis/the-plaid-api/llms.txt) · [OpenAPI document](https://skmtc-service-staging.skmtc.workers.dev/v1/apis/plaid/the-plaid-api/versions/64c4514ea59b/schema)
