# Seller and profile risk API

The seller and profile risk API `POST /v1/assess` takes a website, email, phone, up to 10 other links and a payout wallet. Bewary checks each as its lookup endpoint would. The `decision` is `deny` when a field's verdict is `scam`, `review` when one is `suspicious`, otherwise `pass`. Reasons of medium severity or above carry the field's JSON pointer. A `pass` means nothing Bewary holds names the contact points. It does not establish account safety. Free text is not an input. A call costs 1 credit, a free key gets 1,000 credits a month, no card.

Updated 2026-10-30.

## At a glance

- Endpoint: POST https://api.bewary.app/v1/assess
- Price: 1 credit
- Free key: 1,000 credits a month, no card
- Returns: verdict, p_scam, entities with typed facts, reason codes

## Used for

- Marketplaces check a new seller's website, email, phone and payout wallet in one call during onboarding.
- Rental platforms can recheck a host's contact points when the website, phone number or payout wallet changes.
- Dating apps send a new profile's phone and links at signup and route `review` decisions to moderators.

## Call it

curl:

```bash
curl -X POST "https://api.bewary.app/v1/assess" \
  -H "Authorization: Bearer $BEWARY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"event":{"type":"account.onboarding","id":"seller_8841"},"account":{"website":"paypal-login-secure.top","email":"payouts@mailinator.com","phone":"+18008291040"}}'
```

Python:

```python
import os
import requests

r = requests.post(
    "https://api.bewary.app/v1/assess",
    json={
        "event": {"type":"account.onboarding","id":"seller_8841"},
        "account": {"website":"paypal-login-secure.top","email":"payouts@mailinator.com","phone":"+18008291040"},
    },
    headers={"Authorization": f"Bearer {os.environ['BEWARY_API_KEY']}"},
    timeout=30,
)
result = r.json()
print(result["verdict"], result["p_scam"], result["reason_codes"])
```

JavaScript:

```javascript
const res = await fetch("https://api.bewary.app/v1/assess", {
  method: "POST",
  headers: { Authorization: `Bearer ${process.env.BEWARY_API_KEY}`, 'Content-Type': 'application/json' },
  body: JSON.stringify({
    "event": {
      "type": "account.onboarding",
      "id": "seller_8841"
    },
    "account": {
      "website": "paypal-login-secure.top",
      "email": "payouts@mailinator.com",
      "phone": "+18008291040"
    }
  }),
})
const result = await res.json()
console.log(result.verdict, result.p_scam, result.reason_codes)
```

## Act on the result

Python:

```python
import os, requests

def assess_seller(seller_id, website=None, email=None, phone=None, wallet=None):
    key = os.environ["BEWARY_API_KEY"]          # a free key: bewary.app/account
    headers = {"Authorization": f"Bearer {key}"}
    account = {k: v for k, v in {"website": website, "email": email, "phone": phone}.items() if v}
    if wallet:
        account["wallet"] = {"address": wallet}
    r = requests.post("https://api.bewary.app/v1/assess",
                      json={"event": {"type": "account.onboarding", "id": seller_id}, "account": account},
                      headers=headers, timeout=30)
    r.raise_for_status()
    result = r.json()
    return result["decision"], [(x["pointer"], x["code"]) for x in result["reasons"]]

print(assess_seller("seller_8841", website="paypal-login-secure.top", email="payouts@mailinator.com"))
# ('deny', [('/account/website', 'DOMAIN_BRAND_ON_ABUSED_TLD'), ('/account/email', 'EMAIL_DISPOSABLE'), ...])
```

TypeScript, with the types from https://bewary.app/types/bewary.d.ts:

```typescript
import type { AssessResponse } from "./bewary"

export async function assessSeller(sellerId: string, account: { website?: string; email?: string; phone?: string }) {
  const key = process.env.BEWARY_API_KEY!     // a free key: bewary.app/account
  const headers: Record<string, string> = { Authorization: `Bearer ${key}` }
  const res = await fetch("https://api.bewary.app/v1/assess", {
    method: "POST",
    headers: { ...headers, "Content-Type": "application/json" },
    body: JSON.stringify({ event: { type: "account.onboarding", id: sellerId }, account }),
    signal: AbortSignal.timeout(30_000),
  })
  if (!res.ok) throw new Error(`Bewary ${res.status}`)
  const r: AssessResponse = await res.json()
  return { decision: r.decision, reasons: r.reasons.map((x) => `${x.pointer}: ${x.code}`) }
}
```

## The fields you will use

- `decision`: deny when a field's verdict is scam, review when one is suspicious, otherwise pass.
- `reasons[]`: Every signal of severity medium or above, strongest first, with the JSON pointer of its field (/account/website).
- `fields[]`: Each field's own lookup answer, in request order.
- `credits`: One per valid field. An invalid field gets an error and costs nothing.

## Example response: undefined

Request: `POST /v1/assess` with {"event":{"type":"account.onboarding","id":"seller_8841"},"account":{"website":"paypal-login-secure.top","email":"payouts@mailinator.com","phone":"+18008291040"}}. Captured from the live API on 2026-10-31.

```json
{
  "schema_version": "1.7.0",
  "request_id": "req_01M69WJH5VNBZQFWTNNF20C582",
  "checked_at": "2026-10-31T21:06:43Z",
  "engine": "bewary-engine/3.0.0",
  "models": {
    "calibration": "interim-band-v0"
  },
  "event": {
    "type": "account.onboarding",
    "id": "seller_8841"
  },
  "decision": "deny",
  "p_scam": 0.9116,
  "reasons": [
    {
      "code": "DOMAIN_BRAND_ON_ABUSED_TLD",
      "pointer": "/account/website",
      "severity": "high",
      "source_class": "heuristic"
    },
    {
      "code": "EMAIL_DISPOSABLE",
      "pointer": "/account/email",
      "severity": "high",
      "source_class": "heuristic"
    },
    {
      "code": "DOMAIN_LOOKALIKE_BRAND_WORD",
      "pointer": "/account/website",
      "severity": "medium",
      "source_class": "heuristic"
    }
  ],
  "fields": [
    {
      "pointer": "/account/website",
      "type": "url",
      "value": "paypal-login-secure.top",
      "verdict": "scam",
      "p_scam": 0.9116,
      "reason_codes": [
        "DOMAIN_BRAND_ON_ABUSED_TLD",
        "DOMAIN_LOOKALIKE_BRAND_WORD"
      ],
      "entities": [
        {
          "id": "e1",
          "type": "url",
          "value": "https://paypal-login-secure.top",
          "normalized": "https://paypal-login-secure.top",
          "role": "link_target",
          "verdict": "scam",
          "p_scam": 0.9116,
          "risk_score": 91,
          "reason_codes": [
            "DOMAIN_BRAND_ON_ABUSED_TLD",
            "DOMAIN_LOOKALIKE_BRAND_WORD"
          ],
          "facts": {
            "scheme": "https",
            "host": "e2",
            "final_url": "https://paypal-login-secure.top",
            "redirect_chain": null,
            "shortener": false,
            "redirect_resolved": true,
            "short_link": null,
            "page": null,
            "target_countries": null,
            "list_count": null,
            "platform_status": null
          },
          "related": [
            "e2"
          ],
          "datasets": [
            {
              "dataset": "threat_feeds",
              "coverage": "WW",
              "in_coverage": true
            },
            {
              "dataset": "threat_aggregates",
              "coverage": "WW",
              "in_coverage": true
            },
            {
              "dataset": "web_pages",
              "coverage": "WW",
              "in_coverage": true
            },
            {
              "dataset": "short_links",
              "coverage": "WW",
              "in_coverage": false
            },
            {
              "dataset": "platform_pages",
              "coverage": "WW",
              "in_coverage": true
            },
            {
              "dataset": "community_reports",
              "coverage": "WW",
              "in_coverage": true
            }
          ]
        },
        {
          "id": "e2",
          "type": "domain",
          "value": "paypal-login-secure.top",
          "normalized": "paypal-login-secure.top",
          "role": "link_target",
          "verdict": "scam",
          "p_scam": 0.9116,
          "risk_score": 91,
          "reason_codes": [
            "DOMAIN_BRAND_ON_ABUSED_TLD",
            "DOMAIN_LOOKALIKE_BRAND_WORD"
          ],
          "facts": {
            "registrable_domain": "paypal-login-secure.top",
            "registered_domain": "paypal-login-secure.top",
            "tld": "top",
            "tld_abuse": "high",
            "registered_at": null,
            "expires_at": null,
            "age_days": null,
            "age_bucket": "unknown",
            "registrar": null,
            "dns": {
              "resolves": false,
              "a": null,
              "mx": null,
              "ns": null
            },
            "status": "gone",
            "cert_first_seen": null,
            "lookalike": {
              "brand_id": "paypal",
              "technique": "brand_word"
            },
            "platform": "none",
            "allowlisted": false,
            "listed": false,
            "seen_in_checks_7d": null,
            "country": null,
            "target_countries": null,
            "list_count": null,
            "site": null,
            "platform_status": null,
            "registry_status": null,
            "hold": null,
            "registered": false,
            "registration_checked_at": "2026-10-30T19:18:58Z",
            "archive": {
              "checked_at": "2026-10-30T19:20:08Z",
              "captured": false,
              "first_capture_at": null,
              "last_capture_at": null,
              "captured_before_registration": null,
              "months_before_registration": null,
              "last_capture_before_registration_at": null
            },
            "first_seen_by_bewary": null,
            "first_listed_publicly": null
          },
          "related": [],
          "datasets": [
            {
              "dataset": "registration",
              "coverage": "WW",
              "in_coverage": true
            },
            {
              "dataset": "dns",
              "coverage": "WW",
              "in_coverage": true
            },
            {
              "dataset": "certificates",
              "coverage": "WW",
              "in_coverage": true
            },
            {
              "dataset": "web_archive",
              "coverage": "WW",
              "in_coverage": true
            },
            {
              "dataset": "threat_feeds",
              "coverage": "WW",
              "in_coverage": true
            },
            {
              "dataset": "threat_aggregates",
              "coverage": "WW",
              "in_coverage": true
            },
            {
              "dataset": "brand_registry",
              "coverage": "WW",
              "in_coverage": true
            },
            {
              "dataset": "platform_pages",
              "coverage": "WW",
              "in_coverage": true
            },
            {
              "dataset": "community_reports",
              "coverage": "WW",
              "in_coverage": true
            }
          ]
        }
      ],
      "signals": [
        {
          "code": "DOMAIN_BRAND_ON_ABUSED_TLD",
          "entity": "e2",
          "severity": "high",
          "weight": 55,
          "source_class": "heuristic",
          "p": null,
          "dataset": "brand_registry",
          "coverage": "WW",
          "evidence": {
            "brand_id": "paypal",
            "tld": "top"
          }
        },
        {
          "code": "DOMAIN_LOOKALIKE_BRAND_WORD",
          "entity": "e2",
          "severity": "medium",
          "weight": 35,
          "source_class": "heuristic",
          "p": null,
          "dataset": "brand_registry",
          "coverage": "WW",
          "evidence": {}
        }
      ]
    },
    {
      "pointer": "/account/email",
      "type": "email",
      "value": "payouts@mailinator.com",
      "verdict": "suspicious",
      "p_scam": 0.5,
      "reason_codes": [
        "EMAIL_DISPOSABLE"
      ],
      "entities": [
        {
          "id": "e1",
          "type": "email",
          "value": "payouts@mailinator.com",
          "normalized": "payouts@mailinator.com",
          "role": "mentioned",
          "verdict": "suspicious",
          "p_scam": 0.5,
          "risk_score": 50,
          "reason_codes": [
            "EMAIL_DISPOSABLE"
          ],
          "facts": {
            "domain": "e2",
            "mx": true,
            "disposable": true,
            "free_provider": false,
            "role_account": false,
            "disposable_status": "unknown",
            "disposable_checked_at": null
          },
          "related": [
            "e2"
          ],
          "datasets": [
            {
              "dataset": "email_providers",
              "coverage": "WW",
              "in_coverage": true
            },
            {
              "dataset": "dns",
              "coverage": "WW",
              "in_coverage": true
            },
            {
              "dataset": "registration",
              "coverage": "WW",
              "in_coverage": true
            },
            {
              "dataset": "breaches",
              "coverage": "WW",
              "in_coverage": true
            },
            {
              "dataset": "community_reports",
              "coverage": "WW",
              "in_coverage": true
            }
          ]
        },
        {
          "id": "e2",
          "type": "domain",
          "value": "mailinator.com",
          "normalized": "mailinator.com",
          "role": "mentioned",
          "verdict": "safe",
          "p_scam": 0.0013,
          "risk_score": 0,
          "reason_codes": [
            "DOMAIN_AGE_GT_1Y"
          ],
          "facts": {
            "registrable_domain": "mailinator.com",
            "registered_domain": "mailinator.com",
            "tld": "com",
            "tld_abuse": "low",
            "registered_at": "2003-07-02T13:50:53Z",
            "expires_at": "2028-07-02T13:50:53Z",
            "age_days": 8521,
            "age_bucket": "gt_1y",
            "registrar": "GoDaddy.com, LLC",
            "dns": {
              "resolves": true,
              "a": [
                "104.20.46.162",
                "172.66.146.138"
              ],
              "mx": null,
              "ns": [
                "betty.ns.cloudflare.com",
                "james.ns.cloudflare.com"
              ]
            },
            "status": "live",
            "cert_first_seen": null,
            "lookalike": null,
            "platform": "none",
            "allowlisted": false,
            "listed": false,
            "seen_in_checks_7d": null,
            "country": null,
            "target_countries": null,
            "list_count": null,
            "site": null,
            "platform_status": null,
            "registry_status": [
              "client_delete_prohibited",
              "client_renew_prohibited",
              "client_transfer_prohibited",
              "client_update_prohibited"
            ],
            "hold": "none",
            "registered": true,
            "registration_checked_at": "2026-10-30T19:19:20Z",
            "archive": {
              "checked_at": "2026-10-30T19:20:44Z",
              "captured": true,
              "first_capture_at": "2003-07-24T11:42:16Z",
              "last_capture_at": "2026-10-18T15:10:53Z",
              "captured_before_registration": false,
              "months_before_registration": null,
              "last_capture_before_registration_at": null
            },
            "first_seen_by_bewary": null,
            "first_listed_publicly": null
          },
          "related": [],
          "datasets": [
            {
              "dataset": "registration",
              "coverage": "WW",
              "in_coverage": true
            },
            {
              "dataset": "dns",
              "coverage": "WW",
              "in_coverage": true
            },
            {
              "dataset": "certificates",
              "coverage": "WW",
              "in_coverage": true
            },
            {
              "dataset": "web_archive",
              "coverage": "WW",
              "in_coverage": true
            },
            {
              "dataset": "threat_feeds",
              "coverage": "WW",
              "in_coverage": true
            },
            {
              "dataset": "threat_aggregates",
              "coverage": "WW",
              "in_coverage": true
            },
            {
              "dataset": "brand_registry",
              "coverage": "WW",
              "in_coverage": true
            },
            {
              "dataset": "platform_pages",
              "coverage": "WW",
              "in_coverage": true
            },
            {
              "dataset": "community_reports",
              "coverage": "WW",
              "in_coverage": true
            }
          ]
        }
      ],
      "signals": [
        {
          "code": "EMAIL_DISPOSABLE",
          "entity": "e1",
          "severity": "high",
          "weight": 50,
          "source_class": "heuristic",
          "p": null,
          "dataset": "email_providers",
          "coverage": "WW",
          "evidence": {
            "domain": "mailinator.com"
          }
        },
        {
          "code": "DOMAIN_AGE_GT_1Y",
          "entity": "e2",
          "severity": "info",
          "weight": -45,
          "source_class": "first_party",
          "p": null,
          "dataset": "registration",
          "coverage": "WW",
          "evidence": {
            "age_days": 8521
          }
        }
      ]
    },
    {
      "pointer": "/account/phone",
      "type": "phone",
      "value": "+18008291040",
      "verdict": "unknown",
      "p_scam": 0.2,
      "reason_codes": [],
      "entities": [
        {
          "id": "e1",
          "type": "phone",
          "value": "+18008291040",
          "normalized": "+18008291040",
          "role": "mentioned",
          "verdict": "unknown",
          "p_scam": 0.2,
          "risk_score": 20,
          "reason_codes": [],
          "facts": {
            "e164": "+18008291040",
            "country": "US",
            "number_type": "toll_free",
            "original_carrier": null,
            "line_type": null,
            "complaints": {
              "ftc": null,
              "fcc": null,
              "callbacks": null,
              "pushed_by": null
            },
            "honeypot_hits_30d": 0,
            "listed": false,
            "public_listing": null,
            "indexable": false,
            "target_countries": null,
            "list_count": null
          },
          "related": [],
          "datasets": [
            {
              "dataset": "phone_numbering",
              "coverage": "WW",
              "in_coverage": true
            },
            {
              "dataset": "us_numbering",
              "coverage": "US",
              "in_coverage": true
            },
            {
              "dataset": "phone_complaints",
              "coverage": "US",
              "in_coverage": true
            },
            {
              "dataset": "honeypot_lines",
              "coverage": "US",
              "in_coverage": true
            },
            {
              "dataset": "phone_reports_de",
              "coverage": "DE",
              "in_coverage": false
            },
            {
              "dataset": "community_reports",
              "coverage": "WW",
              "in_coverage": true
            }
          ]
        }
      ],
      "signals": []
    }
  ],
  "credits": 3
}
```

## Parameters

| Name | In | Type | Required | Description |
|---|---|---|---|---|
| `event` | body | string | yes |  |
| `account` | body | string | yes |  |

## Questions

### How do I check a seller's website, email and phone in one call?

Send the website, email, phone, links and payout wallet to `POST /v1/assess`. Bewary runs each field's lookup and returns a `decision` of `deny`, `review` or `pass`. The request accepts up to 10 other links and costs 1 credit per valid field.

### Does a `pass` decision mean a seller or profile is safe?

No. A `pass` means Bewary holds nothing naming the supplied contact points. The `decision` follows field verdicts only, so an `unknown` verdict can still yield `pass`.

### Can `POST /v1/assess` check a profile bio or listing text?

No. `POST /v1/assess` accepts contact points, including a website, email, phone, links and payout wallet. Free text such as a profile bio is outside its input.
