Detect check fraud in mobile and branch deposits

Grayson decides whether a deposited check is counterfeit, altered, stolen or a duplicate, and whether to release funds, place an exception hold or reject it.

Grayson decides whether a check deposited through a mobile app or at a branch is counterfeit, altered, stolen or a duplicate, and whether to make the funds available on your normal schedule, place an exception hold or reject the deposit. It reads the account's deposit history, your image-analysis, duplicate-detection and check-verification results, and what happened on the account around the deposit, and costs about $0.04 per 1,000 decisions.

  • Decides: Release, hold or reject a check deposit that may be counterfeit, altered, stolen or a duplicate.
  • Call it: When a mobile or branch check deposit is submitted
  • Questions: 1 score, 2 choice
  • Cost: $0.000045 per decision, $0.04 per 1,000, for this example's 1,274 input tokens
  • Latency: 172 ms for this example, the median of 5 calls through api.finic.ai from US-West

Example

A member whose four-month-old account is paid by payroll ACH deposits a $3,950 business check in the app from a company that has never paid them before, then tries to send $3,600 to a new P2P recipient five minutes later.

Open in PlaygroundEdit and run this request in the Finic portal.
QuestionGrayson's answer
return_likelihoodLikely (60-90%), 30%
check_problemcounterfeit, 69%
funds_actionexception_hold, 84%

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.

  • funds_action routes the deposit. An exception_hold on a check covered by Regulation CC means sending a notice that gives the reason.
  • check_problem sets the follow-up: call a likely scam victim the same day, contact the paying bank for altered or stolen checks, find a duplicate's first deposit.
  • return_likelihood: set hold thresholds on the sum of "Likely" and "Very likely", choosing the cut-off from your own return history.

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

Customers expect deposited funds within a day or two, but a bad check can come back days later, after the money has left by P2P, ATM or debit card. Many people who deposit counterfeit checks are scam victims, and holding every unusual check frustrates good customers.

What to send

Send the account's history, the item with your vendors' results on it, and what happened around the deposit:

  • Account age and deposit history. A young account whose first large credit is a check fits scam victims and mules alike.
  • The maker and the customer's history with it. A first check from a business that has never paid them raises the question why.
  • Check number against the maker's range. A number far outside the maker's recent range is a strong counterfeit signal.
  • Image analysis. Mismatched amounts, or different ink on the payee or amount line, point to alteration.
  • Duplicate detection. Whether the same item was already deposited, at your institution or through a shared image network.
  • Activity around the deposit. Money that leaves straight away suggests someone expects the check to bounce, or a scammer is pressing.

Add your own criteria

Grayson follows your mobile deposit procedure when it's in the request, even where it's stricter than a general reviewer would be. This one rejects a mobile deposit instead of holding it when the member has never deposited a check from the maker and the check-verification service reports the number out of range or the maker's account closed, because members treat a held deposit as money they have.

Your mobile deposit procedure adds this to the context:

{
  "institution_policy": "Cobalt Ridge Credit Union mobile deposit procedure MD-4. Reject a mobile check deposit, rather than accepting it with a hold, when both of these are true: (1) the member has never deposited a check from this maker before; (2) the check-verification service reports the check number outside the maker's recent range, or the maker's account as closed. Do not credit the account. Call the member the same day, explain that the check appears to be counterfeit, and tell them not to send money to whoever gave them the check. We reject instead of holding because members see a held deposit in their balance, treat it as money they have, and send their own funds on before the check comes back. Branch deposits, and checks from makers the member has deposited before, follow the standard hold rules."
}
QuestionWithoutWith your mobile deposit procedure
return_likelihoodLikely (60-90%), 30%Very likely (over 90%), 48%
check_problemcounterfeit, 69%counterfeit, 94%
funds_actionexception_hold, 84%reject, 99%

Both conditions hold here (no earlier checks from this maker, and a check number far outside its recent range), so the funds decision should move from an exception hold to rejecting the deposit.

Where to call it

  • Mobile deposits: after image analysis, duplicate detection and check verification return, and before the app confirms the deposit.
  • Branch deposits: when the teller scans the item, so a rejection happens while the check is still at the window.
  • When the answer is uncertain, hold rather than release and verify with the paying bank; call again if the customer tries to move the money.

Cost and latency

This example is 1,274 input tokens, so a decision costs $0.000045: $0.04 per 1,000 decisions, or $45.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 172 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/check-deposit-fraud/questions.json --label return_likelihood=<column> --label check_problem=<column> --label funds_action=<column>

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

  • return_likelihood: a level, such as "Very likely (over 90%)"
  • check_problem: none, counterfeit, altered, stolen, duplicate
  • funds_action: normal_availability, exception_hold, reject

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

Can an exception hold be based on Grayson's answer under Regulation CC?

For checks deposited at a branch or ATM, Regulation CC lets you extend a hold when you have reasonable cause to believe the check is uncollectible, based on facts that would cause a well-grounded belief in the mind of a reasonable person, not on the check or the depositor belonging to a particular class. The hold notice has to give the reason, so cite the facts Grayson weighed, such as a check number outside the maker's range, not a score. Regulators haven't settled whether Regulation CC's availability schedule covers mobile deposits, so many institutions set mobile availability in their mobile deposit agreement; confirm yours with your compliance team.

Can it tell a scam victim from someone depositing a bad check on purpose?

Add a question for it, such as a noul asking whether the account holder appears to be the victim of a fake-check scam rather than a participant. A message about a new job, an online sale or an overpayment and a long, ordinary account history point one way; a new account followed by ATM withdrawals at several locations points the other. The answer changes the conversation with the customer, not the hold.

What if I don't have check-verification or duplicate-detection data?

Send what you have. Without a check-verification service, Grayson can't compare the check number with the maker's range or confirm that the maker's account is open, so its answers will be less certain. Treat an uncertain answer as a reason to hold and verify with the paying bank, not to release.

On this page