Antifrauder API v1 Open app

Checks · Phone

Phone check

Validate a phone number and score its fraud risk from a multi-source consensus of three independent telecom data sources. The extended tier adds a fourth voter plus an identity / breaches block.

POST /api/v1/check/phone

Body parameters

Field Type Required Description
phone string required Phone in any common format; normalized to E.164. Bad input → 400 invalid_target.
extended_check boolean optional Run the extended tier (4th voter + advanced block). Default false.
use_storage boolean optional Reuse your own prior result of equal-or-higher tier for free. Default false.
external_id string optional Your own correlation id; stored with the check, echoed back in the response, and searchable in the mini-app history. Max 128 chars.
cURL
curl -X POST https://antifrauder.app/api/v1/check/phone \
  -H "X-API-Key: $ANTIFRAUDER_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: 7e3b1c9a-2f44-4d10-9a8e-c0ffee000001" \
  -d '{ "phone": "+1 415 555 0132", "extended_check": true }'

Response

Every check returns the same envelope. result holds the phone-specific view; the other fields describe the transaction.

200 — JSON
{
  "checkId": "665f1a9c8e4b2a0012ab34cd",
  "externalId": "order-12345",
  "charged": 22,
  "extended": true,
  "fromStorage": false,
  "balance": 4798,
  "result": {
    "extended": true,
    "intel": {
      "number": {
        "e164": "+14155550132",
        "formatInternational": "+1 415 555 0132", "formatNational": "(415) 555-0132",
        "country": { "code": "US", "name": "United States", "prefix": "1" },
        "geo": { "city": "San Francisco", "zip": "94103", "timezone": "America/Los_Angeles" }
      },
      "valid":  { "value": true, "agreement": { "count": 3, "total": 3 }, "source": "consensus" },
      "line": {
        "type":     { "value": "mobile", "agreement": { "count": 3, "total": 3 }, "source": "consensus" },
        "carrier":  { "value": "T-Mobile", "agreement": { "count": 2, "total": 3 },
                      "source": "consensus", "variants": ["T-Mobile USA", "T-Mobile"] },
        "network":  { "mcc": "310", "mnc": "260", "mccmnc": "310260" },
        "activity": { "value": "active", "agreement": { "count": 3, "total": 3 }, "source": "consensus" }
      },
      "portability": {
        "ported": { "value": "no", "agreement": { "count": 2, "total": 3 }, "source": "consensus" },
        "possiblyPorted": false, "currentCarrier": null, "currentNetwork": null
      },
      "roaming": { "status": "no", "carrier": null, "country": { "code": null, "name": null } },
      "risk": {
        "fraudScore": 12, "recentAbuse": false, "risky": false,
        "leaked": false, "spammer": false, "prepaid": true, "disposable": false
      },
      "intel": {
        "social": { "whatsapp": true, "telegram": true, "facebook": true, "instagram": false },
        "breaches": { "count": 1, "first": "2019-03-01", "last": "2019-03-01", "list": ["Collection#1"] },
        "callerType": "consumer", "scoreCluster": "high",
        "identity": { "firstName": "John", "lastName": "Doe" }
      },
      "meta": { "extended": true, "sources": { "ok": 3, "total": 4 } }
    },
    "fraud": {
      "score": 0, "level": "low",
      "positive": [
        { "code": "PH-T-01", "key": "has_whatsapp", "name": "WhatsApp active", "description": "The number has an active WhatsApp account.", "points": -5 },
        { "code": "PH-T-02", "key": "has_google", "name": "Google account", "description": "The number is linked to a Google account.", "points": -5 }
      ],
      "negative": []
    },
    "basicErrors": {},
    "advancedError": null
  }
}

Envelope fields

Field Type Description
checkId string Stored check id — use it with GET /api/v1/result/:checkId.
externalId string Your external_id from the request (or the stored one), echoed back. Absent when none was supplied.
charged integer Cents debited (0 when served from storage).
extended boolean Whether the extended tier ran.
fromStorage boolean true when reused from a prior check (no charge).
balance integer Your balance after the charge, in cents.
result object The phone view: extended, intel, fraud, basicErrors (per-source error map, {} when all answered) and advancedError (the extended source's error, or null).

Intel (result)

result.intel is the consolidated, presentation-ready view. We fuse the sources into one canonical vocabulary (lowercase tokens like mobile / active), so a field is named the same everywhere. Each consolidated attribute carries its provenance:

{ "value": "mobile", "agreement": { "count": 2, "total": 3 }, "source": "consensus" }

source is consensus (2+ sources agree), single (only one source supplies it — e.g. carrier or reputation), or derived (inferred by us). agreement.total is the number of providers that responded. Abstentions count: for connectivity, porting and roaming, if most responders answer “unknown” the value is unknown — we never assert a status off a single source against an undecided majority. (Exception: a single voip line type still wins — it is the strongest fraud signal.)

Field Type Description
number object e164, formatInternational, formatNational, country{code,name,prefix}, and geo{city,zip,timezone} (or null).
valid consolidated<boolean> Whether the number is a valid, assignable MSISDN.
line.type consolidated<string> mobile, landline, voip, toll_free, premium_rate, short_code, pager, unknown.
line.carrier consolidated + variants[] Carrier brand (or null); variants lists the legal-name spellings seen across sources.
line.network object | null { mcc, mnc, mccmnc } when a source resolved it.
line.activity consolidated<string> active, inactive, off, unknown. Live reachability — fixed lines are often unknown (no mobile-network HLR record).
portability object ported (consolidated yes/no/unknown), possiblyPorted, currentCarrier, currentNetwork.
roaming object | null status (yes/no/unknown), carrier, country{code,name}.
risk object | null Reputation: fraudScore, recentAbuse, risky, leaked, spammer, prepaid, disposable.
intel object | null Extended identity block — see Extended block. null on a basic check.
meta object extended (was the 4th source queried) and sources{ok,total} — how many providers responded.

Fraud score

One accumulative score, 0–100, capped — higher is riskier. Triggered signals are split into negative (risk — raise the score) and positive (trust — e.g. an active WhatsApp — lower it). Each signal carries a stable code (e.g. PH-R-06), a name, a description and its points, so you can explain the score. Codes are stable — the table below lists the most significant ones.

Level Score
low 0 – 25
medium 26 – 50
high 51 – 75
critical 76 – 100

Key phone signals

Code Signal Points Trigger
PH-R-01 not_valid +100 No source considers it valid.
PH-R-06 voip_line +100 Number type VOIP.
PH-R-13 disposable_number +100 Flagged disposable by the extended layer.
PH-R-08 / PH-R-10 premium_rate / short_code +90 Premium-rate / short-code line.
PH-R-02 disconnected +50 Number not reachable on the network.
PH-R-05 unknown_connectivity +20 No source could confirm the line is reachable.
PH-R-18 no_social_presence +20 Extended: no linked social/messenger accounts.
PH-R-11 number_ported +10 Recently ported.
PH-T-01 / PH-T-02 has_whatsapp / has_google −5 Active mainstream account lowers risk.

Extended block (intel.intel)

The identity block lives at result.intel.intel. It is populated only when extended_check: true and the 4th source responded; otherwise it is null and advancedError explains why. (Reputation fields under intel.risk come from a basic source and are present on basic checks too.)

Field Type Description
social object Platform → boolean (account exists): whatsapp, telegram, facebook, instagram, google, apple, amazon, office365, twitter.
breaches object { count, first, last, list[] } — known data-breach exposure.
callerType string | null business / consumer / null.
scoreCluster string | null Extended trust band: very_low, low, review, high.
identity object | null { firstName, lastName } — a potential name behind the number, low confidence. Each field may be null; the whole block is null when no name is resolved.

Retrieve & batch

Fetch a stored result without paying again, or check thousands of numbers from a CSV.

GET/api/v1/result/phone?phone=+14155550132
GET/api/v1/result/:checkId

Both return your latest stored result for that value / id, or 404 not_found.

CSV batch

POST/api/v1/batch/phone

multipart/form-data with a file field (one number per row, max 10 000 rows) and an optional extended_check field. The cost is pre-estimated against your balance; rows are charged individually as a background job processes them.

cURL
curl -X POST https://antifrauder.app/api/v1/batch/phone \
  -H "X-API-Key: $ANTIFRAUDER_KEY" \
  -F "[email protected]" \
  -F "extended_check=true"
200 — JSON
{ "jobId": "665f...e1", "total": 1240, "validRows": 1187, "estimate": 26114 }
GET/api/v1/batch/:jobId

Poll job status: { jobId, status, total, done, charged, fileId? }.

GET/api/v1/batch/:jobId/result

When status: "completed", returns a short-lived signed download URL for the result CSV: { url, expiresAt }.