---
title: "Score an IP address"
method: GET
path: "/v1/score/ip"
tags: ["Scoring"]
---

# Score an IP address

`GET /v1/score/ip`

## Request

- Base URL: `https://www.layercall.com`
- URL: `https://www.layercall.com/v1/score/ip`
- Auth: one of:
  - API key in header `x-api-key`
  - HTTP bearer

Detects VPNs, proxies, Tor exit nodes and datacenter ranges, and returns geo/ASN context plus reputation from LayerCall's first-seen network.

## Query parameters

- `ip` string, required
- `strictness` 'lenient' | 'balanced' | 'strict'

## Response `200`

Score

- IpScore
  - `ip` string, required
  - `risk_score` integer, required: 0 = clean, 100 = certain fraud.
  - `verdict` 'allow' | 'review' | 'block', required: Recommended action. Thresholds move with `strictness`.
  - `signals` object, required
    - `is_vpn` boolean
    - `is_proxy` boolean
    - `is_datacenter` boolean
    - `is_tor` boolean
    - `recent_abuse` boolean
    - `is_private_or_reserved` boolean: RFC1918 / loopback / reserved. Cannot be meaningfully scored.
  - `geo` object, required
    - `country` string, nullable: ISO 3166-1 alpha-2.
    - `city` string, nullable
    - `asn` string, nullable
    - `isp` string, nullable
  - `first_seen` string, date-time, nullable: First time this value was seen across the LayerCall network.
  - `times_seen` integer
  - `abuse_reports` integer: Confirmed-fraud reports from distinct accounts.
  - `cached` boolean, required: Served from cache. Cached lookups are never billed.
  - `request_id` string, required
  - `warning` string: Present only when the input needs attention.
  - `vpn_provider` string, nullable: Name of the VPN operating this exit node (e.g. "NordVPN", "Mullvad", "Surfshark"), taken from the operator's own published server list. null when is_vpn was inferred from an ASN or third-party feed rather than confirmed by the operator — absence is not evidence the IP is not a VPN.
  - `signals_unavailable` string[]: Signals that could not be measured on this request — e.g. ["tor", "vpn_providers"]. Absent entirely when every feed answered, so the happy-path shape is unchanged. Present means the score was built on incomplete data: a "clean" answer and a "we could not check" answer are otherwise identical.
  - `hijacked_source` unknown
  - `processing_time_sec` number
  - `billable_lookups` integer

## Other responses

- `400`: Missing or malformed input.
- `401`: Missing, invalid, or revoked API key.
- `429`: Monthly quota or spend cap reached, or the 600 requests-per-minute rate limit exceeded.

---

[API](https://skmtc.dev/layercall/apis/layercall-api.md) · [All operations](https://skmtc.dev/layercall/apis/layercall-api/llms.txt) · [OpenAPI document](https://skmtc.dev/layercall/apis/layercall-api/revisions/b1258307dc91?raw)
