Batch
Answers up to 1000 addresses in one call. Each distinct string in ips
is one lookup: it costs exactly what GET /{ip} costs for that address
and comes back with exactly the fields that call would carry for your
plan. Exact duplicates collapse to one entry and one lookup.
Both maps in the answer are keyed by the string you sent, so nothing has
to be lined up by position; the ip inside each result is the
normalized form. An address that could not be answered sits in errors
with the status and message the single lookup would have given, and
never disturbs the others: a string that is not an address is a 400
there, and an allowance that runs out part way through leaves the
remaining entries as 429s.
The call itself fails only for the reasons below, and a 429 on the
call always carries Retry-After: the batch is admitted or refused
whole by the rate limit, so a per-entry 429 is always a spent
allowance and never a throttle.
?apikey=<key>. Convenient in a browser; prefer a header elsewhere.
In: query
Request Body
application/json
TypeScript Definitions
Use the request body type in TypeScript.
Response Body
application/json
application/json
application/json
application/json
application/json
application/json
curl -X POST "https://api.vpndetection.io/batch" \ -H "Content-Type: application/json" \ -d '{ "ips": [ "1.1.1.1", "2606:4700:4700:0:0:0:0:1111", "192.168.1.1", "not-an-ip" ] }'{
"results": {
"1.1.1.1": {
"ip": "1.1.1.1",
"is_vpn": false
},
"2606:4700:4700:0:0:0:0:1111": {
"ip": "2606:4700:4700::1111",
"is_vpn": false
},
"192.168.1.1": {
"ip": "192.168.1.1",
"is_vpn": false
}
},
"errors": {
"not-an-ip": {
"status": 400,
"error": "not a valid IP address"
}
}
}{
"error": "body must be a JSON object whose ips member is an array of strings"
}{
"error": "invalid API key"
}{
"error": "source address not allowed for this API key"
}{
"error": "request body too large"
}{
"error": "rate limit exceeded"
}My IP GET
Answers what is known about the address this request came from, which is the same answer `GET /{ip}` gives for that address: the plan behind the presented key decides which fields come back, and the request counts against the same allowance. The address is the one our edge observed, so a request through a proxy or a VPN reports the exit it left through rather than the machine that made it. That is usually the point of asking.
List GET
Every database this organization may SEE, with where its license stands. Not just the ones you hold: a customer with one grant should be able to tell what else is published without asking. `standing` is the difference - `licensed`, `expired`, or `unlicensed` for one never bought.