Detect fraudulent incoming ACH credits and transfers

Decide whether an incoming ACH credit is the proceeds of fraud at the sender, and whether to release, hold or return it, from account, login and transfer data.

Grayson tells a receiving bank or fintech whether an incoming ACH credit or transfer is likely the proceeds of fraud at the sender, how likely its own customer is acting as a money mule, and whether to release the funds, hold them while it contacts the sending bank, or return the credit. It reads the account profile, recent logins and profile changes, the credit itself and what happened after it posted, and costs about $0.05 per 1,000 decisions.

  • Decides: Release, hold or return an incoming credit that may be proceeds of BEC, account takeover or payroll diversion.
  • Call it: When a large or out-of-pattern incoming ACH credit or transfer posts
  • Questions: 1 yes/no, 1 score, 1 choice
  • Cost: $0.000050 per decision, $0.05 per 1,000, for this example's 1,414 input tokens
  • Latency: 173 ms for this example, the median of 5 calls through api.finic.ai from US-West

Example

A rideshare driver's six-month-old checking account receives a $38,400 corporate vendor payment addressed to a supply company, three days after a new device linked a crypto exchange account, and money starts leaving within minutes.

Open in PlaygroundEdit and run this request in the Finic portal.
QuestionGrayson's answer
proceeds_of_fraudYes, P(yes) 82%
mule_likelihoodVery likely (over 90%), 68%
actionhold_and_contact, 91%

Each percentage is Grayson's probability for the answer shown; for a yes/no question it's the probability of yes. A multiple-choice answer lists the options at 50% or more.

  • proceeds_of_fraud: above your threshold, delay availability of the funds; Nacha's funds-availability exception requires you to notify the sending bank promptly when you use it.
  • mule_likelihood: route a high sum of "Likely" and "Very likely" to your mule-account team, separately from the decision about this credit.
  • action: when return and hold_and_contact are close, hold and restrict outbound transfers; a hold can be released, but a return can't be taken back.

Call it from your code

Save request.json and send it with your API key in GRAYSON_API_KEY:

curl https://api.finic.ai/v1/decide \
  -H "Authorization: Bearer $GRAYSON_API_KEY" \
  -H "Content-Type: application/json" \
  --data @request.json

The problem

The receiving institution sees only an ACH credit with a company name, an entry description and a receiver name, not the compromise that produced it. Once the funds move on, they are rarely recovered. Simple rules separate the cases poorly: name mismatches are common on legitimate credits, and a large-credit threshold flags every insurance settlement and tax refund.

What to send

Send what your operations team would see on the account and the credit, cut at the moment you decide:

  • The name on the entry and the account's owners. A company or another person's name on a consumer account suggests the sender was misled.
  • What kind of credit it is. A corporate SEC code or vendor-payment description on a personal account that never received one.
  • The account's normal. A credit far above the average balance, or to a dormant account, is out of pattern.
  • Access and profile changes before the credit. New devices, contact changes and linked accounts show an account being prepared or taken over.
  • What happened after it posted. Money leaving within hours is the strongest sign of a mule account.
  • What the customer said. A customer forwarding a "client's" payment to "their supplier" is describing a mule arrangement.

Add your own criteria

When to return rather than hold is a business decision the data alone can't settle: some institutions always hold and call the sending bank first, while others return on the spot when the evidence is strong. This one returns, the same day, a large corporate credit to a consumer account with an unexplained name mismatch while money is already moving to new payees.

Your return policy for name mismatches adds this to the context:

{
  "institution_policy": "ACH-14, name mismatches on incoming credits. We post ACH credits by account number, but we do not hold a CCD or CTX credit over $10,000 to a consumer account for a call to the sending bank when all three of these are true: (1) the receiver name in the entry matches no owner of the account; (2) we have no business relationship on file between the member and the originator or the named receiver; (3) money has started leaving the account, or a transfer is pending, to a payee or external account added in the last 14 days. In that case, return the full credit the same banking day with return reason R17 and QUESTIONABLE in the addenda, block outbound transfers, and refer the member to BSA. Holding the funds and contacting the sending bank is for mismatches that do not meet all three conditions."
}
QuestionWithoutWith your return policy for name mismatches
proceeds_of_fraudYes, P(yes) 82%Yes, P(yes) 93%
mule_likelihoodVery likely (over 90%), 68%Very likely (over 90%), 84%
actionhold_and_contact, 91%return, 98%

All three conditions hold here (the receiver name matches no owner, nothing on file ties the member to the originator or the named receiver, and money is going to a payee and an exchange account added this week), so the action should move from holding the funds to returning the credit.

Where to call it

  • When the credit posts, for credits your screening routes for review, before the funds become available.
  • Again when money starts to leave an account holding a recent large credit, with the outbound activity added.
  • When the answer is uncertain, hold the funds and call the sending bank, which can ask its own customer whether the payment was intended.

Cost and latency

This example is 1,414 input tokens, so a decision costs $0.000050: $0.05 per 1,000 decisions, or $50.00 per million. You pay only for input tokens, at $0.035 per million, and each request is rounded up to the next millionth of a dollar. A larger context costs proportionally more; every response reports its size in usage.input_tokens.

Grayson answered this example in 173 ms, the median of 5 calls through api.finic.ai from US-West. Latency grows with the number of input tokens. Add your own network time to api.finic.ai.

Evaluate on your own data

Score Grayson on your own past cases before you use it: a CSV with one row per case and a column with the right answer to each question. Every other column is sent as the case.

pipx install https://docs.finic.ai/downloads/grayson_cli-0.2.2-py3-none-any.whl
grayson eval my-cases.csv --questions https://docs.finic.ai/recipes/incoming-payment-fraud/questions.json --label proceeds_of_fraud=<column> --label mule_likelihood=<column> --label action=<column>

Each --label names the column with that question's right answer:

  • proceeds_of_fraud: true or false
  • mule_likelihood: a level, such as "Very likely (over 90%)"
  • action: release, hold_and_contact, return

Or run grayson on its own to set up your questions step by step. You get each question's accuracy and a CSV with Grayson's answer next to yours for every case.

FAQ

Should I hold or return a credit I think is fraudulent?

Nacha rules allow either: since October 2024, a receiving bank that reasonably suspects a credit is unauthorized or induced by false pretenses may delay its availability (notifying the sending bank promptly) and may return it with R17 and QUESTIONABLE in the addenda. Many teams hold and contact the sending bank first, because a return can't be undone. Whichever you choose, restrict outbound transfers at once: a return is for the full amount, so you fund whatever has already left.

Can Grayson tell an unwitting mule from a complicit one?

The mule_likelihood question covers both on purpose, because the decision about the credit is the same either way. To separate them, add a question such as "Does the account holder appear to be the victim of a job, romance or investment scam that is using their account?" and include the customer's messages and call notes. Intent often becomes clear only after someone talks to the customer, so ask again with the call notes added.

What if the name on the credit matches my customer?

Then the most common giveaway is missing, and the other signals carry the decision: a new or recently reactivated account, a type of credit the account has never received, new devices or profile changes beforehand, and money leaving soon after. Fraudsters also open accounts, including business accounts, in names that match what the sender expects to see.

On this page