The problem

A voicemail says it was your bank. A text says a parcel is held. A missed call leaves a number to ring about your account.

The advice every regulator gives is the same: do not use the number in the message, use the number printed on your own card or bill. That tells you which number to dial. It does not tell you what to ask when somebody picks up. It leaves you with nothing you can keep.

What it does

It dials that printed number once. In its first sentence it says it is an automated assistant calling on behalf of a named person, with their permission, that it is not a person and that what they say is written down. It asks one question: did anyone there contact this customer in the last hour about this. Then it hands back the verdict, the words the person on the line actually said and the number the customer should be using.

It verifies a contact event rather than a standing fact. Not "is this number really the bank" but "did you call this person in the last hour". Every reverse lookup and every number reputation service answers the first question. The first question is not the one that decides whether somebody moves their savings.

A bank saying no is the answer, not a failure

refused_to_confirm is the outcome to expect from a bank rather than the edge case. The app is built to be useful when it lands. The institution is following the law rather than stonewalling.

  • Regulation P protects the bare fact that somebody is a customer. 12 CFR 1016.3(q)(2)(i)(C) counts "the fact that an individual is or has been one of your customers" as personally identifiable financial information.
  • 12 CFR 1016.10(a)(1) then bars disclosing that to a nonaffiliated third party outside the notice and opt out machinery. An app ringing on a customer's behalf is a third party.
  • A clinic has a harder rule again. Confirming it called a named person reveals that the person is a patient, so HIPAA at 45 CFR 164.514(h)(1)(i) makes a covered entity verify the identity and the authority of whoever is asking.

So a refusal still tells the customer more than the message did. The institution would not confirm it either way, so treat it as unverified and ring them on the printed number. Every outcome ends with that number, which is the one number worth ringing whatever came back.

The five outcomes

Outcome When
confirmed_genuine a call CALL-E finished cleanly plus a turn supporting "yes we contacted them"
no_such_contact a finished call plus a turn supporting "no record of that"
refused_to_confirm a finished call where the institution declines to discuss a third party's account
unreachable a finished call that reached nobody, reached a machine or ended before the question
outcome_unknown a call CALL-E has not finished with, a call this app could not read, an ambiguous create

A status says how a call ended. It is not a statement about what the transcript holds, so it is not read as one. A denial or a refusal already in a transcript stands even when the call ended failed. A confirmation does not, because that is the one answer which could leave somebody trusting a message they should not.

What it refuses to do

The three refusals are the product. Each runs twice: once when the claim file loads, then again on the claim and the words about to be sent, so a claim assembled any other way still cannot get past the second one.

  • It will not dial a number that came out of the suspicious message. Only a number the customer read off their own card, bill or statement.
  • It will not speak anything about the customer that the claim did not authorize.
  • It will not read out a code, a password or a card number, whatever the file says.

How it was built

TypeScript on @call-e/calle, tsx plus node:test, no build step, a local fake CALL-E so it runs with no account. Every legal claim in the code, the docs and this description was read at the primary source and pinned to its citation, which is also how two widely quoted scam figures got left out: the 250,000 FTC complaints number could not be sourced. The 442% vishing rise is H1 2024 against H2 2024 from CrowdStrike's 2025 report rather than a year on year figure.

What is real

172 tests, tsc --noEmit clean, npm run demo exit 0. Nothing here has ever rung a real bank.

Built With

  • anti-fraud
  • call-e
  • call-e-sdk
  • hipaa
  • json-schema
  • node-test-runner
  • node.js
  • regulation-p
  • typescript
  • vishing
Share this project:

Updates

Submission history