All articles Advanced signals

Closing the Loop: Reporting Fraud Outcomes to Improve Detection

Every fraud decision is a guess made with incomplete information. Some time later, you find out whether it was right: the chargeback arrives, the “new user” turns out to be the same person on their sixth account, the blocked signup emails support and is obviously a real customer. That later knowledge is the most valuable data your fraud program will ever have, and most teams throw it away.

A feedback loop means writing it down where your detection can use it. This post covers why that matters, which outcomes to report, and how Prynt uses them.

Why labels matter

Without labels, you’re tuning blind. You can see how many signups you blocked, but not how many of them were fraud. You can see a risk score distribution, but not where the bad actors actually sit in it. Every threshold change is a guess about a guess.

Labels give you three things:

  1. Memory. A device or account confirmed as abusive is recognized on its next visit, even if everything else about it looks clean.
  2. Measurement. With outcomes attached to decisions, you can compute precision and recall for each rule and reason code instead of eyeballing.
  3. Shared intelligence. Confirmed-bad entities can, if you opt in, warn other sites about the same device or IP.

What to report

Not every event needs a label. Report the ones where you learned something definite.

OutcomeLabelTypical source
Chargeback or dispute lostchargebackPayment processor webhook
Stolen card or payment fraud confirmedfraudReview, processor alert
Trial farm, multi-account ring, promo abuseabuseAnalyst investigation
Scripted signup or scraper confirmedbotReview, honeypot hit
Account taken overaccount_takeoverCustomer report, support
Spam submissionsspamModeration
Blocked or flagged user who was legitimatelegitSupport ticket, appeal
Known-good, high-value customertrustedAccount management

The good labels are the ones teams forget. A false positive you never record is invisible in every report you’ll ever run. When support unblocks someone, label it legit. That’s how you find the rules that are hurting real users. Tuning fraud thresholds depends on having both sides.

Reporting through the API

POST /v1/outcomes takes your secret key and a label, plus at least one of requestId, visitorId or linkedId:

curl -X POST https://api.pryntid.com/v1/outcomes \
  -H "Authorization: Bearer sk_live_…" \
  -H "Content-Type: application/json" \
  -d '{
    "label": "chargeback",
    "requestId": "req_…",
    "notes": "dispute on order 48213"
  }'

The response is { "recorded": true, "label": "chargeback" }. When you pass a requestId, Prynt fills in the visitorId, linkedId and IP from that event, so one id is usually enough.

The easiest wiring is to hang it off events you already receive. A chargeback webhook from your processor:

async function onDisputeCreated(dispute) {
  const order = await db.orders.findByPayment(dispute.payment_id);
  if (!order?.pryntRequestId) return;
  await fetch('https://api.pryntid.com/v1/outcomes', {
    method: 'POST',
    headers: {
      Authorization: `Bearer ${process.env.PRYNT_SECRET_KEY}`,
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({ label: 'chargeback', requestId: order.pryntRequestId, notes: `dispute ${dispute.id}` }),
  });
}

This only works if you stored the requestId (or visitorId) on the order or account when it was created. If you take one thing from this post: store it everywhere a decision was made.

Choose the key deliberately

A label recorded by requestId also records that event’s IP, and later visits from a labeled IP match too. That’s useful for an abuser on a dedicated server and harmful for one on a mobile carrier or office network, where the same IP is shared by many people. When the bad actor was on a shared network, label by visitorId or linkedId instead:

{ "label": "abuse", "visitorId": "…", "notes": "trial farm, 7 accounts" }

Labeling in the console

Not every outcome comes from a webhook. Analysts confirm farms, support resolves appeals, moderators remove spam. The console’s case view lets them label an identification directly, and those labels go into the same store as API labels, recorded with the analyst who made them. If you run a review queue, make labeling the last step of every case, not an optional one. The review queue playbook covers how to structure that.

What happens to a label

A bad label marks the entity. The next time that visitorId, linkedId or IP is identified, the decision carries the KNOWN_ABUSER reason code (risk decisions run on the plans with Smart Signals, Pro and above). It’s weighted heavily, so with the default weights and thresholds it’s enough on its own to push the decision to block. The person can change their email, clear cookies and switch networks; the device still matches.

A good label is stored as ground truth. It doesn’t override a rule by itself; for known-good users you want to wave through, use the console’s allow list (by visitorId, linkedId, IP or country). What good labels give you is the denominator: they’re how you see which reason codes fire on real customers.

All labels also become training data for the risk model, which is the long-term reason to report consistently even when a label doesn’t change anything today.

The reputation network

If you opt in to the cross-customer reputation network, confirmed-bad entities from every participating account are combined into a shared feed. What leaves your account is a one-way salted hash of the entity, not raw signals or personal data. When a device or IP burned on another site visits yours, its decision carries NETWORK_REPUTATION.

That’s the payoff for labeling well: an abuser who gets caught once doesn’t start fresh at the next site. It’s also why accuracy matters. A careless fraud label on a real customer affects more than your own decisions, so reserve bad labels for outcomes you’ve actually confirmed. How the reputation network works goes into the mechanics and the privacy model.

Start small

You don’t need to label everything on day one. Start with the two easiest sources: chargebacks from your processor webhook (chargeback) and unblocked users from support (legit). After a month, compare the reason codes on each group. You’ll see which signals predict real losses and which ones are mostly catching your customers, and you’ll have evidence instead of instinct for the next threshold change.

Try it free

Prynt is device intelligence with a free tier — visitor IDs, bot & fraud Smart Signals, and behavioral biometrics, powered by a cross-site network. Start free.

Keep reading