For AI agents

The whole contract, on one page.

If you are an autonomous client, this page is for you. What we sell is a file, not an answer: there is no lookup endpoint to call per address. Below is every call that exists, the shape each one returns, and the five refusals you have to tell apart. Nothing here needs another page to be actionable.

The same facts are at /llms.txt as plain text, and the full reference is at docs.internetdata.io/api.

Five calls, no lookups

Access is granted by contract, one database family at a time, to a key carrying the db.download scope. Keys are default-deny: an existing key gains nothing until the scope is added to it. The same key presents three ways — a bearer token, X-Api-Key, or ?apikey= for a browser or a one-liner.

Request
# a 302 to object storage is the success case
curl -L -H "Authorization: Bearer $KEY" \
"https://internetdata.io/api/v2/database/download?id=vpn_ip_v1&format=csvgz" \
-o vpn_ip_v1.csv.gz
# and verify what landed
curl -s -H "X-Api-Key: $KEY" \
"https://internetdata.io/api/v2/database/checksum?id=vpn_ip_v1&format=csvgz"
Basehttps://internetdata.io
AuthBearer · X-Api-Key · ?apikey=
Scopedb.download
CatalogGET /api/v2/database/list
MetadataGET /api/v2/database/metadata?id=
DownloadGET /api/v2/database/download?id=&format=
ChecksumsGET /api/v2/database/checksum?id=&format=
HistoryGET /api/v2/database/downloads?limit=
Formatscsvgz · mmdb
Refusals400 · 401 · 403 · 404 · 503, each with an rc

What comes back

Poll metadata to decide whether today's build is worth fetching: it carries the build date, the row count and the size of each format without moving any bytes.

200 application/json
GET /api/v2/database/metadata?id=vpn_ip_v1
{
"id": "vpn_ip_v1",
"update_freq": "daily",
"updated": "2026-09-21",
"entries": 17328905,
"size": { "csvgz": 119755873,
"mmdb": 575833040 },
"schema": {
"csvgz": [
{ "name": "start_ip", "type": "ipaddress" },
]
}
}
id
The versioned id. This is what download, checksum and metadata take.
update_freq
How often a new build is published. Daily for every database in the catalog.
updated
The date the published build was generated. Fetch only when this moves.
entries
Row count in the current build: ranges for a range database, not addresses.
size
Bytes per format. A format absent here is not built for this database.
schema
Columns keyed by format: name, type and description, in file order.
sample
A few real rows, keyed by format, when the build carries them.

Seven things that will bite you otherwise

Each of these is a place where the obvious reading of the API is the wrong one.

01A 302 is the success case

Download answers a redirect to a time-limited link on object storage; the bytes never come through the API. Follow it (curl -L). The link authorizes the START of a transfer, so one already running is not interrupted when it lapses.

02Keys are default-deny

A key does not gain database access until db.download is added to it. Missing key, wrong key, missing scope and a key belonging to no organization all answer 401 with rc UNAUTHORIZED.

03403 is a licensing answer, not an auth one

rc NOT_LICENSED means your organization never bought this family; LICENSE_EXPIRED means the term ended. Neither is retryable — it needs a contract, not a backoff.

04503 means licensed but not published yet

rc NOT_AVAILABLE means the current build has not been published yet. Retry later; do not treat it as an error, and do not substitute a different database for it.

05Not every format exists for every database

csvgz for every database, mmdb for most. The provider catalogs are keyed by provider id, so there is nothing for an mmdb to index, and asking one for it is a 400 INVALID_FORMAT — a deliberate refusal, not a gap in coverage. list names the formats each version is built in.

06A license covers a family, a download names an id

list returns a family (base, e.g. vpn_ip) with your standing, and the id to pass onward to metadata and download. Read that id from list rather than composing it yourself.

07There is no address endpoint to call

No lookup API exists, by design — nothing here answers "is 45.83.91.1 a VPN". You license the database and answer that question inside your own infrastructure.

What a license lets you do

Every database is available under either grant, and the list endpoint reports which one you hold against each family. Full detail is on the licensing page.

evaluation
A full current build for internal testing only, time-boxed and under NDA. Integrating it across a product or serving customer use cases with it needs written permission first.
standard
Unlimited internal use: detection, decisions and operations inside your own product. The rows do not leave your walls.
redistribute
The rows, or per-address answers derived from them, may reach your own customers, within the scope written into the contract.
null
No license. Every family with standing unlicensed reports this, and download refuses with 403.

When you need more than one database

Do not crawl this site for what the catalog already answers in one call.

Read the catalog

One call to /api/v2/database/list returns every published family with its versions, its formats and your standing beside it. That is the machine-readable form of the published catalog.

Watch for new builds

Poll metadata once a day per family and fetch only when updated moves. Your own attempt history, refusals included, is at /api/v2/database/downloads — a denial is what answers "it stopped working", and its absence answers nothing.

00 · Evaluate

Test the real build first.

An evaluation license puts a full current build in your hands — every row, every column, no sampling — so you can measure it against your own traffic before anyone talks about terms.

01 · License

Then license what you use.

Standard, for detection and decisions inside your own product and operations.
Redistribution, when the data ships onward inside what you sell — priced by scope, not by seat.
Annual terms, a named contact, and flexible payment terms — monthly, quarterly or yearly.