API reference
A small REST API over HTTPS. Every response is JSON; every error carries a stable code.
Authentication
Send your key as a bearer token. X-API-Key is accepted too, for clients that cannot set an Authorization header.
curl https://geopass.site/api/v1/lookup/1.1.1.1 \
-H "Authorization: Bearer gp_live_…"
# equivalent
curl https://geopass.site/api/v1/lookup/1.1.1.1 \
-H "X-API-Key: gp_live_…"Keys are stored hashed and shown once at creation. Revoking a key takes effect on the next request.
Endpoints
https://geopass.site/api/v1/lookup/{ip}Resolve one address.https://geopass.site/api/v1/lookup/meResolve the caller’s address.https://geopass.site/api/v1/lookup/batchResolve many at once.https://geopass.site/api/v1/usageCheck what is left. Free.A batch takes a JSON body and bills one lookup per valid address:
curl -X POST https://geopass.site/api/v1/lookup/batch \
-H "Authorization: Bearer gp_live_…" \
-H "Content-Type: application/json" \
-d '{"ips": ["1.1.1.1", "8.8.8.8"]}'Checking your usage
/v1/usage reports where you stand without drawing on the allowance, so a client can poll it or show a meter without spending a lookup to ask. It is rate limited like any other call.
curl https://geopass.site/api/v1/usage -H "Authorization: Bearer gp_live_…"
{
"plan": { "id": "pro", "name": "Pro" },
"quota": {
"limit": 50000,
"used": 1234,
"remaining": 48766,
"resetsAt": "2026-10-01T00:00:00.000Z"
},
"rateLimit": { "limit": 50, "window": "1s" },
"batchLimit": 100
}Response
meta.sources names the upstream behind each half of the answer, and meta.cached tells you whether it was served from our cache. A null source means nothing answered that half, so its fields are defaults rather than findings.
On the privacy block: hosting and anonymous are reported by our upstream. vpn, proxy, tor and relay are not yet broken out and stay false; use anonymous as the signal that an origin is being hidden.
Fields a source does not supply come back null, never invented. Booleans that were never checked are null too, so false always means an actual answer.
{
"ip": "1.1.1.1",
"type": "ipv4",
"location": {
"country": "AU", // ISO 3166-1 alpha-2
"countryName": "Australia",
"region": "Queensland",
"regionCode": "QLD",
"city": "Brisbane",
"postalCode": "9010",
"latitude": -27.4679,
"longitude": 153.0281,
"timezone": "Australia/Brisbane",
"continent": "Oceania",
"continentCode": "OC",
"publicPlace": false // airport, hotel, campus
},
"network": {
"asn": 13335,
"organization": "Cloudflare, Inc.",
"isp": "Cloudflare, Inc.",
"domain": "cloudflare.com",
"hostname": "one.one.one.one",
"route": null,
"type": "hosting", // hosting, isp, business, education
"mobile": false, // cellular carrier rather than fixed line
"satellite": false,
"anycast": true // announced from many locations
},
"privacy": {
"hosting": true, // datacentre address
"anonymous": false, // origin is obscured
"proxy": false,
"vpn": false,
"tor": false,
"relay": false
},
"meta": {
"sources": { "geo": "ipinfo:core", "privacy": "ipinfo:core" },
"cached": { "geo": true, "privacy": true }
}
}Rate limits and quota
Four headers ride along on every successful response, so a client can back off before it is throttled.
x-ratelimit-limit: 50
x-ratelimit-remaining: 49
x-quota-limit: 500000
x-quota-remaining: 499999| Plan | Monthly | Per second | Batch |
|---|---|---|---|
| Trial | 500 | 2 | 10 |
| Starter | 10,000 | 5 | 25 |
| Pro | 50,000 | 50 | 100 |
| Business | 100,000 | 250 | 500 |
Quotas reset at 00:00 UTC on the first of the month. Rate limits are a fixed one-second window per key.
A new account starts on Trial, which is there to let you check the data against addresses you already know before paying for anything. It is not sized for production traffic.
Errors
{ "error": { "code": "reserved_address", "message": "…" } }| Status | Code | When |
|---|---|---|
| 400 | invalid_request | The address could not be parsed, or the batch body was malformed. |
| 401 | unauthorized | The API key is missing, malformed, revoked, or unknown. |
| 422 | reserved_address | A private, loopback, link-local or documentation address. |
| 429 | rate_limited | Too many requests this second. Retry after the Retry-After header. |
| 429 | quota_exceeded | The monthly allowance is spent. Retry-After gives the reset time. |
| 502 | upstream_unavailable | No provider could resolve the address. Not billed. |
Nothing you cannot use is billed. Malformed and reserved addresses never draw on the quota, and a lookup that fails upstream is refunded.