Detect money mule accounts
Decide whether an account is a money mule, whether the holder is complicit or was deceived by a job or romance scam, and whether to restrict or close it.
Grayson decides whether an account is being used as a money mule, whether the holder is complicit or was deceived by a fake job or romance scam, and whether to keep monitoring, restrict the account and contact the customer, or close it and refer it for a suspicious activity report (SAR). It reads data your institution already holds, from the customer profile and transactions to devices, linked accounts and the customer's own messages, and costs about $0.08 per 1,000 decisions.
- Decides: Whether an account is passing other people's money through, whether the holder knows, and what to do
- Call it: When monitoring flags pass-through activity on an account
- Questions: 1 yes/no, 2 choice, 1 score
- Cost: $0.000083 per decision, $0.08 per 1,000, for this example's 2,349 input tokens
- Latency: 208 ms for this example, the median of 5 calls through api.finic.ai from US-West
Example
A checking account dormant for 14 months has taken in $22,125 from seven people and two businesses in three weeks, with about 90% of each earlier payment leaving within two days; the customer has written that they "process payments" for an employer, and a sender's bank has reported one credit as rental-scam proceeds.
| Question | Grayson's answer |
|---|---|
is_mule | Yes, P(yes) 59% |
holder_role | unwitting, 65% |
fraud_proceeds | Likely (60-90%), 41% |
action | close_and_refer, 77% |
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.
{
"model": "grayson-1",
"context": {
"alert": {
"id": "alrt_88412",
"created": "2026-10-06T14:05:00Z",
"rules": [
"Dormant account reactivated: more than $5,000 in credits within 30 days after 12 or more months without customer activity",
"5 or more first-time senders in 14 days",
"80% or more of incoming funds moved out within 48 hours"
]
},
"customer": {
"customer_id": "cus_58213",
"customer_since": "2018-04-11",
"occupation": "Part-time retail sales associate",
"stated_annual_income_usd": 24000,
"expected_monthly_deposits_usd": 1500,
"identity_verified": true,
"prior_alerts": 0,
"contact_details_changed_last_12_months": false
},
"account": {
"account": "Personal checking x4821",
"history": "Payroll and everyday spending until June 2025, then no customer-initiated activity from 2025-06-30 to 2026-09-15",
"balance_on_2026_09_15_usd": 38.12,
"payroll_deposits_since_reactivation": 0,
"p2p_daily_send_limit_usd": 2500,
"linked_transfer_rule": "Transfers over $2,500 to linked external accounts are released after 1 business day"
},
"devices_and_logins": {
"devices": [
{
"device": "iPhone 12",
"first_seen": "2021-11-03",
"other_customers_seen_on_device": 0
}
],
"logins_since_reactivation": "All from the customer's home metro area, all on the iPhone 12"
},
"linked_external_accounts": [
{
"type": "Crypto exchange account",
"added": "2026-09-16T23:40:00Z",
"name_on_account": "Matches the customer",
"other_customers_linking_it": 0
}
],
"activity": [
{
"ts": "2026-09-15T23:02:00Z",
"type": "login",
"detail": "First login since 2025-06-30, on the customer's usual iPhone"
},
{
"ts": "2026-09-16T23:40:00Z",
"type": "linked_account_added",
"detail": "Crypto exchange account in the customer's name, verified by micro-deposits"
},
{
"ts": "2026-09-17T15:02:00Z",
"type": "p2p_in",
"amount_usd": 1850,
"from": "D. Larkin",
"first_time_sender": true,
"memo": "apartment deposit"
},
{
"ts": "2026-09-17T22:15:00Z",
"type": "transfer_to_linked_account",
"amount_usd": 1660,
"to": "Crypto exchange account"
},
{
"ts": "2026-09-19T13:44:00Z",
"type": "p2p_in",
"amount_usd": 2400,
"from": "S. Pruitt",
"first_time_sender": true,
"memo": "invoice 2291"
},
{
"ts": "2026-09-19T20:02:00Z",
"type": "transfer_to_linked_account",
"amount_usd": 2160,
"to": "Crypto exchange account"
},
{
"ts": "2026-09-23T16:10:00Z",
"type": "ach_credit",
"amount_usd": 4800,
"from": "Brookhollow Dental Group PLLC",
"first_time_sender": true,
"addenda": "INV 1043 EQUIPMENT"
},
{
"ts": "2026-09-24T15:30:00Z",
"type": "transfer_to_linked_account",
"amount_usd": 4320,
"to": "Crypto exchange account",
"note": "Over $2,500: held 1 business day, released 2026-09-25"
},
{
"ts": "2026-09-26T14:25:00Z",
"type": "p2p_in",
"amount_usd": 975,
"from": "T. Brandt",
"first_time_sender": true,
"memo": "car deposit"
},
{
"ts": "2026-09-26T19:10:00Z",
"type": "scam_warning_shown",
"detail": "Shown before the first payment to a new P2P payee. Customer chose 'I know this person' and continued"
},
{
"ts": "2026-09-26T19:12:00Z",
"type": "p2p_out",
"amount_usd": 880,
"to": "C. Rowe",
"payee_added": "2026-09-26T19:08:00Z"
},
{
"ts": "2026-09-29T17:31:00Z",
"type": "p2p_in",
"amount_usd": 2150,
"from": "L. Fenwick",
"first_time_sender": true,
"memo": "1st month + deposit"
},
{
"ts": "2026-09-30T12:05:00Z",
"type": "p2p_in",
"amount_usd": 1200,
"from": "K. Mercer",
"first_time_sender": true,
"memo": "invoice"
},
{
"ts": "2026-09-30T15:40:00Z",
"type": "transfer_to_linked_account",
"amount_usd": 3000,
"to": "Crypto exchange account",
"note": "Over $2,500: held 1 business day, released 2026-10-01"
},
{
"ts": "2026-10-01T13:22:00Z",
"type": "secure_message",
"from": "customer",
"text": "Why is my transfer to my exchange account still pending? I process payments for my employer's clients and I'm supposed to send them out the same day."
},
{
"ts": "2026-10-01T14:05:00Z",
"type": "secure_message",
"from": "bank",
"text": "Transfers over $2,500 to linked external accounts are released after one business day. Your transfer will be available tomorrow."
},
{
"ts": "2026-10-02T15:48:00Z",
"type": "ach_credit",
"amount_usd": 3250,
"from": "Quarry Lane Tile & Stone LLC",
"first_time_sender": true,
"addenda": "PMT INV 7781"
},
{
"ts": "2026-10-03T14:10:00Z",
"type": "transfer_to_linked_account",
"amount_usd": 2450,
"to": "Crypto exchange account"
},
{
"ts": "2026-10-03T14:31:00Z",
"type": "atm_withdrawal",
"amount_usd": 475
},
{
"ts": "2026-10-05T13:20:00Z",
"type": "p2p_in",
"amount_usd": 2900,
"from": "A. Holloway",
"first_time_sender": true,
"memo": "deposit"
},
{
"ts": "2026-10-05T18:02:00Z",
"type": "p2p_out",
"amount_usd": 2450,
"to": "C. Rowe"
},
{
"ts": "2026-10-05T18:20:00Z",
"type": "atm_withdrawal",
"amount_usd": 160
},
{
"ts": "2026-10-06T12:15:00Z",
"type": "recall_request",
"detail": "The sender's bank asks for the return of the 2026-09-29 P2P credit of $2,150.00 from L. Fenwick. The sender reports paying a deposit on a rental listing that turned out not to exist."
},
{
"ts": "2026-10-06T13:52:00Z",
"type": "p2p_in",
"amount_usd": 2600,
"from": "B. Yates",
"first_time_sender": true,
"memo": "for the car"
}
],
"summary_since_2026_09_15": {
"credits_from_others": 9,
"distinct_senders": 9,
"credits_from_others_usd": 22125,
"received_before_today_usd": 19525,
"moved_out_within_48_hours_usd": 17555,
"debit_card_purchases": "14 purchases, $1,912.60: grocery, fuel, phone bill, restaurants",
"balance_before_2026_10_06_credit_usd": 95.52,
"current_balance_usd": 2695.52
}
},
"questions": {
"is_mule": {
"type": "noul",
"instructions": "Is this account being used as a money mule account, receiving money from other people and passing it on to someone else?"
},
"holder_role": {
"type": "choice",
"instructions": "Which best describes the account holder's part in the money moving through this account?",
"options": {
"complicit": "The account holder knowingly moves money for others, for example for a cut of each payment or by selling or renting out the account",
"unwitting": "The account holder moves money for someone else without knowing it is criminal proceeds, for example after being recruited through a fake job offer or an online relationship",
"not_in_control": "Someone other than the account holder controls the account, for example after an account takeover or because it was opened with a stolen identity",
"no_mule_activity": "The account is not being used to move other people's money"
}
},
"fraud_proceeds": {
"type": "score",
"instructions": "How likely is it that most of the money other people sent to this account came from victims of fraud or scams?",
"levels": [
"Very unlikely (under 10%)",
"Unlikely (10-40%)",
"Uncertain (40-60%)",
"Likely (60-90%)",
"Very likely (over 90%)"
]
},
"action": {
"type": "choice",
"instructions": "What should the institution do with this account now?",
"options": {
"monitor": "Keep the account open without restrictions and continue normal monitoring",
"restrict": "Restrict outbound transfers and cash withdrawals, and contact the customer about the activity",
"close_and_refer": "Close the account and refer it to the BSA/AML team for a suspicious activity report"
}
}
}
}Probabilities are shortened to four decimals here; responses carry full precision.
{
"id": "dec_7b33b1ad6dc0403984896db938fc945d",
"model": "grayson-1",
"answers": {
"is_mule": {
"type": "noul",
"value": true,
"probability": 0.5926
},
"holder_role": {
"type": "choice",
"value": "unwitting",
"probabilities": {
"complicit": 0.1632,
"unwitting": 0.6453,
"not_in_control": 0.0284,
"no_mule_activity": 0.1632
}
},
"fraud_proceeds": {
"type": "score",
"value": 2.67,
"level": "Likely (60-90%)",
"probabilities": [
0.0911,
0.1169,
0.1032,
0.4082,
0.2805
]
},
"action": {
"type": "choice",
"value": "close_and_refer",
"probabilities": {
"monitor": 0.014,
"restrict": 0.2196,
"close_and_refer": 0.7664
}
}
},
"usage": {
"input_tokens": 2349
}
}is_mule: below a threshold chosen on your past alerts, close the alert as a false positive; above it, act on the role and action answers.holder_role: give a close call betweencomplicitandunwittingto an investigator who can call the customer, and sendnot_in_controlto your takeover team.action: sendclose_and_referandrestrictabove their thresholds to your exit and restriction workflows, and everything below them to an analyst queue.
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.jsonThe problem
A mule account rarely breaks a rule with any single transaction. What gives it away is the shape over days: many unrelated senders, money that leaves within hours, a balance that keeps returning to near zero. Rules that flag that shape also flag roommates splitting rent and small side businesses, and they can't read a customer's message about their new job.
What to send
Send the account as an analyst would review it, with the alert that raised it:
- Who sends money in. Many new, unrelated senders with memos like "deposit" or "rent" suggest scam proceeds.
- How fast and where it leaves. A roughly fixed share left behind after each fast exit can be the mule's cut.
- Account history against the stated profile. A dormant account suddenly taking in many times its expected volume is a common sign of recruitment.
- Amounts against limits. Transfers just under a hold threshold, or cash under the $10,000 CTR threshold, show amounts being shaped.
- Shared devices and accounts. Sharing with other customers points to an organized network, not an isolated, deceived customer.
- What the customer has said, word for word. A remote job "processing payments" often separates an unwitting mule from a complicit one.
Add your own criteria
Some institutions exit every account that has passed on fraud proceeds, while others keep a deceived long-time customer, stop the money and explain the scam, so put your procedure in the context in your team's words. This one keeps deceived long-time customers after a first occurrence, restricting the account and calling the customer instead of closing it.
Your deceived-customer procedure adds this to the context:
{
"institution_policy": "Money mule procedure, section 4 (revised 2026-06): For a customer of more than three years whose own messages show they believe the payments are legitimate work or help for someone they trust, and who shares no device, phone number or external account with other customers: restrict outbound transfers, return any reported funds still in the account to the sending institution, and call the customer to explain the scam. Do not close the account on a first occurrence, even when a sending institution has reported a credit as fraud. Close it and refer it to the BSA/AML team only if the activity continues after that call, or if the evidence shows the customer knew the money was stolen. Whether to file a SAR on the activity is decided by the BSA/AML team in every case."
}| Question | Without | With your deceived-customer procedure |
|---|---|---|
is_mule | Yes, P(yes) 59% | Yes, P(yes) 80% |
holder_role | unwitting, 65% | unwitting, 90% |
fraud_proceeds | Likely (60-90%), 41% | Likely (60-90%), 43% |
action | close_and_refer, 77% | restrict, 95% |
This customer has banked here since 2018, wrote that they process payments for an employer and shares no device or account with other customers, so the action should move from closing the account to restricting it and calling the customer, while their role stays the same.
Where to call it
- On each monitoring alert, before it reaches an analyst, and again when another institution reports a credit.
- Before money leaves an alerted account, in the payment path for P2P payments, external transfers and wires.
- When the answer is uncertain, send it to an analyst; whoever contacts the customer must not say whether a SAR has been or will be filed.
Cost and latency
This example is 2,349 input tokens, so a decision costs $0.000083: $0.08 per 1,000 decisions, or $83.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 208 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/money-mule-detection/questions.json --label is_mule=<column> --label holder_role=<column> --label fraud_proceeds=<column> --label action=<column>Each --label names the column with that question's right answer:
is_mule:trueorfalseholder_role:complicit,unwitting,not_in_control,no_mule_activityfraud_proceeds: a level, such as "Very likely (over 90%)"action:monitor,restrict,close_and_refer
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 Grayson tell a complicit mule from one recruited through a job scam?
It can when the evidence is in the context. Long tenure, the customer's usual device, transfers to an account in their own name and a message about a new job point to an unwitting mule; a new account, devices shared with other customers, explanations that change and cash kept under reporting thresholds point to a complicit one. If your team also uses the FBI's middle category, witting (a customer who ignores obvious red flags), add it as an option with that definition.
Do we still file a SAR if the customer was deceived?
Often, yes. The obligation to file depends on what the institution knows or suspects about the transactions, not on whether the customer meant to launder money, so an unwitting mule's activity can still need a SAR. What usually differs is how you treat the customer, and the filing decision stays with your BSA officer.
What if we don't have device data or customer messages?
Send what you have: credits, debits, tenure and the stated profile are usually enough to answer is_mule. Without messages or device data, expect more of holder_role's probability to sit between complicit and unwitting, and route those cases to someone who can call the customer.
Related recipes
Detect fraudulent incoming ACH credits and transfers
Release, hold or return an incoming credit that may be proceeds of BEC, account takeover or payroll diversion.
Detect account opening fraud and synthetic identities
Approve, step up or decline a deposit account application at risk of stolen or synthetic identity fraud.
Recipes
Every use case, with its questions and cost per decision.