Warddocs
Capabilities

Account takeover

A cardholder disputes a transaction. Was the account taken over first, or was it the holder? Ward reads the login and account-change logs before the transaction and answers with a likelihood, the evidence, a timeline and a dispute view.

Type: ato · Endpoint: POST /api/v1/ato/review

Request

curl https://api.mandatelabs.ai/api/v1/decide \
  -H "X-API-Key: $WARD_API_KEY" -H "Content-Type: application/json" \
  -d '{"type": "ato", "input": {
        "disputed": {"occurred_at": "2026-10-30T02:14:00Z", "amount": 1200, "merchant": "GIFTCARDS4U", "device_id": "dv_new_91", "country": "ROU", "known_devices": ["dv_iphone_12"]},
        "logs": [
          {"event_type": "sim_swap", "occurred_at": "2026-10-29T21:02:00Z"},
          {"event_type": "password_reset", "occurred_at": "2026-10-29T21:40:00Z", "device_id": "dv_new_91", "country": "ROU"},
          {"event_type": "new_device_login", "occurred_at": "2026-10-30T02:05:00Z", "device_id": "dv_new_91", "ip_address": "185.220.101.4"}
        ]}}'
d = client.decide("ato", {"disputed": {"occurred_at": "2026-10-30T02:14:00Z", "amount": 1200, "device_id": "dv_new_91"},
                          "logs": [{"event_type": "sim_swap", "occurred_at": "2026-10-29T21:02:00Z"}]})
const d = await client.decide("ato", { disputed: { occurred_at: "2026-10-30T02:14:00Z", amount: 1200, device_id: "dv_new_91" },
  logs: [{ event_type: "sim_swap", occurred_at: "2026-10-29T21:02:00Z" }] });

Input

Field Description
disputed (required) occurred_at, and optional amount, merchant, device_id, country, known_devices
logs[] Up to 90 days before: event_type, occurred_at, device_id, ip_address, country
cardholder_ref Also read the events already sent to POST /api/v1/assess/events
prior_undisputed_with_merchant Earlier purchases at the merchant that were not disputed

Event types: login_success, failed_login, new_device_login, password_reset, credential_change, contact_change, mfa_change, sim_swap, otp_to_new_number, payee_added, wallet_provisioned, card_replacement, session. Device ids are hashed per client before comparison; nothing is stored by the endpoint.

What it weighs

Points to a takeover Weight
SIM swap within 72 h 0.55
Code sent to a newly added number within 24 h 0.45
Contact or two-factor change within 7 days 0.35
Password reset or credential change within 72 h 0.30
New-device login within 24 h; disputed transaction from that device 0.30; +0.25
New payee or wallet token within 24 h 0.30
5+ failed logins in 24 h 0.25
Points to the holder in control Weight
Disputed transaction from a long-used device 0.30–0.45
Earlier undisputed purchases at the merchant 0.30
No account change in 30 days 0.25

likelihood = takeover × (1 − 0.5 × holder), each a noisy-OR.

Result and decision

likelihood, evidence, timeline (relative to the transaction), dispute_view (third-party fraud vs first-party misuse, with the usual scheme categories such as Visa 10.4 and Mastercard 4837), needs and typologies.

Likelihood Decision Meaning
≥ 0.60 DECLINE Takeover likely: secure the account, accept the fraud claim
≥ 0.30 STEP_UP Possible takeover: review
holder evidence ≥ 0.50 STEP_UP First-party indicators: review before accepting a fraud claim
otherwise APPROVE No takeover evidence