/v1/admin/fraud/flags/{flag}Everything the inspector of the Review queue shows to decide one flag: what the detector saw, who the flag is about and what it took from each of them, other traders seen on the same address, and other flags of the same people.
Opening a flag decides nothing. Deciding is a change of status, and lifting one person's restriction is its own call.
Needs a firm. Our own staff name one with the Propper-Workspace header.
Request
curl "https://api.proppertrading.com/v1/admin/fraud/flags/fflag_yhkjqnd8h67ggtbf" \
-H "Authorization: Bearer ptat_9f2c1a44_3b8e7d2f5c9a1b4e6d8f0a2c4e6b8d1f" \
-H "Propper-Workspace: acme"
Response
Every field of a row of the list, and more:
{ "data": { "object": "fraud_flag", "id": "fflag_yhkjqnd8h67ggtbf", "detector": "shared_ip", "category": "ip", "label": "Shared IP", "score": 15, "severity": "low", "risk": 15, "level": "restrict", "status": "open", "subject": "Nikolai Johnson", "others": 3, "ip": "203.0.113.12", "restricted": true, "created_at": "2026-08-21T12:14:51+00:00", "reviewed_at": null, "description": "Several accounts logging in from the exact same address.", "access": false, "last_seen_at": "2026-08-21T16:49:51+00:00", "reviewer": null, "network": { "location": "Sao Paulo, BR", "country_code": "BR", "isp": "Vivo", "org": "Vivo", "asn": "AS44932 Vivo", "classification": "residential", "is_tor": false, "is_proxy": false, "is_hosting": false, "is_mobile": false }, "evidence": { "isp": "British Telecommunications PLC", "location": "London, GB", "user_count": 4 }, "traders": [ { "id": "usr_fr6xeczydychxcvu", "name": "Nikolai Johnson", "email": "[email protected]", "level": "restrict", "exempt": false, "restriction": { "id": "frest_jdbk9qmced79kyft", "since": "2026-08-21T12:14:51+00:00", "lifted_at": "2026-08-21T17:14:51+00:00", "lifted_by": null }, "suspended": false, "open_flags": 1, "risk": { "score": 10, "sum": 10, "threshold": 80, "window_days": 90, "lines": [ { "flag": "fflag_yhkjqnd8h67ggtbf", "kind": "detector", "flags": 1, "label": null, "level": "restrict", "exempt": false, "points": null, "seen_at": "2026-08-21T16:49:51+00:00", "detector": "shared_ip" }, { "flag": "fflag_c2zy2b4yy7j33qmm", "kind": "detector", "flags": 1, "label": null, "level": "flag", "exempt": false, "points": 10, "seen_at": "2026-08-20T09:12:03+00:00", "detector": "vpn" } ] }, "joined_at": "2026-08-31T06:19:14+00:00" }, { "id": "usr_z7edd96kjp5nrdcg", "name": "Julia Hughes", "email": "[email protected]", "level": "restrict", "exempt": false, "restriction": { "id": "frest_ytz98bnpqvxc3s53", "since": "2026-08-21T12:14:51+00:00", "lifted_at": null, "lifted_by": null }, "suspended": false, "open_flags": 1, "risk": { "score": 0, "sum": 0, "threshold": 80, "window_days": 90, "lines": [ { "flag": "fflag_yhkjqnd8h67ggtbf", "kind": "detector", "flags": 1, "label": null, "level": "restrict", "exempt": false, "points": null, "seen_at": "2026-08-21T16:49:51+00:00", "detector": "shared_ip" } ] }, "joined_at": "2026-09-06T02:22:54+00:00" }, { "id": "usr_h4wnyaajk37bn3st", "name": "Camila Fischer", "email": "[email protected]", "level": null, "exempt": true, "restriction": null, "suspended": false, "open_flags": 1, "risk": { "score": 0, "sum": 0, "threshold": 80, "window_days": 90, "lines": [ { "flag": "fflag_yhkjqnd8h67ggtbf", "kind": "detector", "flags": 1, "label": null, "level": null, "exempt": true, "points": null, "seen_at": "2026-08-21T16:49:51+00:00", "detector": "shared_ip" } ] }, "joined_at": "2026-09-11T10:01:22+00:00" }, { "id": "usr_8yrcbhmqm4sa5kvj", "name": "Tariq Kim", "email": "[email protected]", "level": "flag", "exempt": false, "restriction": null, "suspended": false, "open_flags": 1, "risk": { "score": 15, "sum": 15, "threshold": 80, "window_days": 90, "lines": [ { "flag": "fflag_yhkjqnd8h67ggtbf", "kind": "detector", "flags": 1, "label": null, "level": "flag", "exempt": false, "points": 15, "seen_at": "2026-08-21T16:49:51+00:00", "detector": "shared_ip" } ] }, "joined_at": "2026-04-05T21:41:25+00:00" } ], "neighbours": [ { "id": "usr_6dtx95uysmvhqhhz", "name": "Nadia Martin", "last_seen_at": "2026-09-11T19:26:51+00:00" }, { "id": "usr_8putksyq9xvz42k4", "name": "Lotte Oliveira", "last_seen_at": "2026-09-11T19:26:51+00:00" } ], "takes": [ "block_new_orders", "hold_payouts" ], "history": [], "action_url": "/admin/fraud?flag=fflag_yhkjqnd8h67ggtbf", "can": { "manage": true, "traders": true, "affiliates": true, "rules": true } }, "meta": { "request_id": "req_01m50zckycazn8zmqsahnqswcz" } }
| Field | Description |
|---|---|
description | What the detector looks for, in one sentence in the admin's language. Null for a trading rule without one |
access | Whether the detector decides who may connect at all. At Block such a detector refuses the session rather than suspending the account |
last_seen_at | When the flag last changed. A detector that sees the same situation again refreshes the flag rather than raising a second one, but a decision moves this too |
reviewer | Who decided it, by name, null while it is active. Propper when one of our own staff decided it |
network | What the address is, from the lookup, when the flag has one address and the lookup ran: classification is residential, mobile, datacenter, vpn, residential_proxy, tor, local or unknown |
evidence | What the detector measured, as it stored it, with every internal number taken out. Its keys depend on the detector, see below |
traders | Each person the flag is about: the level they were held to, exempt when an override kept them out, the restriction this flag placed on them (lifted_at set once it no longer holds, and lifted_by naming who lifted it the same way as reviewer), suspended when they cannot log in, how many open_flags they have, and their risk score. id and email are null for somebody outside the firm, and so is risk |
traders[].risk | The trader's risk score and where it comes from. score is the total, capped at 100, and sum what the lines add up to before the cap. threshold is the score that suspends a trader when a new flag reaches it, null while escalation is off. window_days is how long a flag counts after it was last seen, 0 for until it is decided. lines has one entry per detector the trader has an active flag from, see below |
neighbours | Up to six other traders of the firm seen on the flag's address, newest sighting first |
takes | What a restriction takes away at this firm today: block_new_orders, hold_payouts, block_purchases, hold_affiliate_payouts. Empty when Restrict takes nothing |
history | Up to eight other flags of the same people, newest first, as rows of the list |
can | What this person may do here: manage decides flags and lifts restrictions, traders opens a trader, affiliates an affiliate, rules a trading rule |
Risk score lines
Each line is one detector, once however many flags it raised for this trader.
| Line field | Description |
|---|---|
detector | The detector's key, or a trading rule's |
kind | detector, trading for a trading rule, manual for a flag raised by somebody of the team, or blocklist for an entry of the firm's blocklist. Only detector ever adds points |
label | The rule's name for a trading rule, the reason for a manual flag, the value that matched for blocklist, null for a detector |
level | The level the detector has for this trader now, null when exempt or for a trading rule. For manual and blocklist, the level the flag was raised at |
points | What it adds. Null when it adds nothing: at restrict, block or off the level is the consequence, an exempt trader was kept out of a group flag by an override, and a trading rule never counts |
exempt | An override kept this trader out of the flag |
flag | The id of the flag of this detector seen most recently |
flags | How many active flags of this detector the trader has |
seen_at | When a detector last saw it |
Evidence
The keys a detector stores, all of them optional:
| Detector | Keys |
|---|---|
vpn, tor, residential_proxy, datacenter | classification, isp, org, location |
shared_ip | user_count, isp, location |
shared_subnet | subnet, user_count, ip_count |
concurrent_sessions | active_ip_count, window_minutes, ips |
impossible_travel | from and to (each location and ip), distance_km, gap_minutes, speed_kmh |
new_country | country_code, known_countries |
country_mismatch | registration_country, login_country, location |
blocked_country | country_code, policy, location |
max_countries | count, window_days, countries |
shared_device | device, fingerprint, user_count |
emulator | device, fingerprint, webgl_renderer |
headless_browser | device, fingerprint, webgl_renderer, webdriver |
no_fingerprint | grace_minutes |
group_hedging | occurrence_count, window_seconds, and occurrences, each with opened_at, instrument, lots (the two sizes) and gap_seconds |
copy_trading | similarity_pct, matched_trades, window_days |
shared_payment | fingerprint, user_count |
shared_identity | phone_masked, user_count |
affiliate_shared_device, affiliate_shared_ip | referral_count, shared, referrals (each id and name), affiliate |
affiliate_signup_burst | referral_count, window_days, referrals, affiliate |
affiliate_refund_pattern | purchases, refunded, refund_pct, window_days, referrals, affiliate |
manual | reason, trader_message (what the trader reads instead of the fixed banner), expires_at (when the restriction ends), raised_by (a name) |
blocklist | entry (the blocklist entry's id), type (email, email_domain, ip, device, payment or phone), value, where (sign_in, device or payment) |
| A trading rule | measured, threshold and unit (%, s or none), rule (the rule's id), rule_name, and whatever the rule measured: violation_count, window_hours, symbol, lots, open_price, stop_loss, ticket, close_reason, size_multiplier, first_lots, last_lots, worst_lots, median_lots, trade_count, buys, sells, instrument_count, max_instruments, best_trade_profit, net_profit, since, require_no_sl, tickets |
Countries are ISO codes of two letters. affiliate is the affiliate's id, a
referrals entry's id is null for somebody outside the firm.
Errors
| Status | Code | Meaning |
|---|---|---|
| 400 | workspace_required | Asked by our own staff without naming a firm |
| 401 | invalid_token | Not a token, or the secret does not match |
| 401 | revoked_token | Signed out here or from another device |
| 401 | expired_token | Ninety days without use, or a set expiry passed |
| 403 | admin_access_required | This account no longer helps run the environment |
| 403 | insufficient_scope | This device does not hold admin:read |
| 403 | workspace_not_permitted | The Propper-Workspace header names an environment this account cannot act in |
| 403 | forbidden | Without view_fraud |
| 404 | resource_not_found | No flag with that id in this firm |