Reviewing fraud flags

Inspect why a click was flagged and dismiss false alarms.

Partli runs cheap fraud checks at click and sale time and flags suspicious activity rather than blocking it. A flagged click still redirects and still counts for attribution — nothing is silently dropped. As a workspace admin or manager, you review these flags on the partner page, dismiss the false alarms, and ban partners whose pattern actually looks abusive.

What gets flagged

Each flag carries a raw flag_reason that the UI translates into a plain-English label:

  • Automated user-agent — the click came from a bot-like user-agent (crawler, script, or headless browser). Raw reason starts with bot_ua.
  • Social link preview — a bot_ua flag whose user-agent matches a social/messaging unfurl crawler. Marked benign: this happens when a partner shares their link. Not fraud.
  • Missing user-agent — no (or a suspiciously short) user-agent. Raw reason empty_or_short_user_agent.
  • Repeated clicks from one IP — the same IP produced N clicks within 10 minutes (possible click inflation). Raw reason ip_spam:N_in_10m.

In the dashboard

  1. Spot flagged partners

    On /<workspace>/partners, the Fraud column shows an amber warning icon and an N flags badge for any partner with open (unresolved) flags.

  2. Open the partner and read the Flagged activity card

    Click into /<workspace>/partners/<partnerId>. The Flagged activity card lists each flagged click with its label, an explanation, timestamp, country, and the raw user-agent. The badge in the card header reads N open flags.

  3. Dismiss false alarms

    Each flagged click has a Dismiss button. If a partner has more than one open flag, a Dismiss all button appears in the card header to resolve them in one shot. Dismissed clicks get a green Dismissed badge and dim out.

  4. Reopen if you dismissed by mistake

    A resolved flag shows a Reopen button that puts it back into the open set.

  5. Ban a genuinely abusive partner

    Dismissing a flag never touches the partner's status. If the pattern really is abusive, ban the partner from their status controls instead.

Via the API / for agents

The dashboard buttons all call one endpoint. It requires a manager role (or above) on the workspace — the check is canManage(role), so viewers get a 403.

POST /api/workspaces/<slug>/partners/<partnerId>/resolve-flags

Body (all fields optional):

{
  "clickId": "<uuid>",        // omit to act on ALL open flags for the partner
  "action": "resolve"          // "resolve" (default) or "reopen"
}

Dismiss one flagged click as a false alarm:

curl -X POST \
  https://app.partli.com/api/workspaces/acme/partners/PARTNER_ID/resolve-flags \
  -H "content-type: application/json" \
  -d '{ "clickId": "CLICK_UUID", "action": "resolve" }'

Dismiss every open flag for the partner at once (omit clickId):

curl -X POST \
  https://app.partli.com/api/workspaces/acme/partners/PARTNER_ID/resolve-flags \
  -H "content-type: application/json" \
  -d '{ "action": "resolve" }'

The response reports how many click rows were updated:

{ "ok": true, "count": 3 }

resolve only touches currently-open flags (rows with flagResolvedAt still null) and records who resolved them in flagResolvedBy. Pass action: "reopen" to undo — that only touches already-resolved flags and clears both fields.

Gotchas

Dismissing is not un-flagging, and it never pays or blocks anyone

Resolving a flag only clears it from the open set for review — the click row stays flagged = true, it's just marked resolved via flagResolvedAt. A few things worth knowing:

  • Flags never block: the click already redirected and already counted for attribution before you ever saw the flag.
  • The endpoint is scoped to the workspace's own partner — a manager can't touch another workspace's clicks (you get a 404 if the partner isn't yours).
  • Social link-preview crawlers (Facebook, Slack, LinkedIn, etc.) are dropped upstream and never create a flag; a Social link preview label only appears on older data. Real fraud checks are bot_ua, empty_or_short_user_agent, ip_spam, and self-referral (partner converting on their own link).
  • Dismissing does not pay out or approve anything — commissions follow their own approval flow.