IP99 OpenAPI 一次匯入:Postman、程式碼生成與 GPT Actions
Import IP99's OpenAPI Once: Postman, Codegen, and GPT Actions
IP99 提供穩定網址的 OpenAPI 3.1.0 文件,可匯入 Postman、Insomnia、openapi-generator 或 GPT Actions,涵蓋免費查詢、配額及需專業密鑰的 Pulse 路徑。匿名配額目前為每個客戶端 IP 每日 500 次、每分鐘 60 次;配額可能變動,應以回應標頭或 /v1/me 為準。
Most IP-risk vendors hand you a PDF and a support ticket. IP99 by ThreatHunter publishes an OpenAPI 3.1 document at a stable URL you can import the same way you import any other public API: Postman, Insomnia, openapi-generator, or a GPT Action. One file describes the free profile, the quota endpoint, and the professional Pulse path — so your clients, types, and agent tools stay in sync with the live service instead of a blog post you copied six months ago.
This is a practical import walkthrough. Every curl below runs without an API key. Live samples were captured on 2026-10-31 (UTC).
What the spec actually covers
curl -s https://ip99.com/openapi.json | head -c 200
# → {"openapi":"3.1.0","info":{"title":"IP99 IP risk and geolocation API",...
As of today the document advertises OpenAPI 3.1.0, title IP99 IP risk and geolocation API, version 1.0.0, server https://ip99.com, and three paths:
| Path | What it is |
|---|---|
GET /v1/ip/{ip} |
Free risk + geo + network profile (key optional) |
GET /v1/me |
Your current tier and remaining quota |
GET /pulse/v1/ip/{ip} |
Same score with per-evidence detail (professional key) |
Access-Control-Allow-Origin: * is set on the OpenAPI JSON itself, so browser-based importers and GPT Action validators can fetch it without a CORS proxy. Security schemes in the file are exactly what the human docs say: X-API-Key header or Authorization: Bearer, never a query string (?key= is rejected with HTTP 400 key_in_query).
The free endpoint is still the one you should try first:
curl https://ip99.com/v1/ip/8.8.8.8
Captured ~2026-10-31 13:05 UTC:
{
"ip": "8.8.8.8",
"computed_at": "2026-10-31T13:05:33Z",
"evidence_state": "none",
"geo": {
"continent": "NA",
"country": "US",
"region": "California",
"city": "Mountain View",
"district": "",
"tz": "America/Los_Angeles"
},
"network": { "asn": 15169, "usage_type": "IDC" },
"risk": {
"score": 0,
"level": "none",
"signals": ["hosting"]
}
}
hosting here is a network attribute, not a risk verdict. Score 0 with evidence_state: none means "no current verifiable evidence," not "safe." Official copy is blunt about that; your generated client should expose evidence_state as a first-class field, not bury it under "extra."
Import into Postman (or Insomnia)
- Copy
https://ip99.com/openapi.json. - Postman: Import → Link → paste the URL → Import. Insomnia: Create → Import From → URL.
- You get three requests. Open
lookupIP(GET /v1/ip/{ip}), setipto8.8.8.8, send. No Authorization needed for anonymous quota. - Optional: add a collection variable
apiKeyand map it to theapiKey/bearerscheme when you create a free key in the console. Fields do not change with a key — only the quota counter does.
Anonymous allowance today (from GET /v1/me): 500 lookups/day per client IP, 60/min, resetting at midnight Asia/Shanghai. Sign in and self-create a key for a higher daily bucket; overseas self-serve Pro / Pro+ buys volume, not a different score. Per-item evidence rows, share_tier, and ?at= history sit on Pulse and need a professional key.
Generate a typed client
Any OpenAPI 3.1 generator that understands 3.1 will work. Example with the official CLI (install once, then pin the URL):
npx @openapitools/openapi-generator-cli generate \
-i https://ip99.com/openapi.json \
-g typescript-fetch \
-o ./ip99-client
Or Python:
openapi-generator-cli generate \
-i https://ip99.com/openapi.json \
-g python \
-o ./ip99-py
What you should assert in a smoke test after generation:
- Response type includes
evidence_stateenum:active|stale|none. -
risk.scoreis documented (and treated in app code) as freshness/strength of evidence, not "probability this visitor is an attacker." -
risk.signalsis an array of slugs;hosting/mobiledescribe the network and are not, by themselves, a ban reason. - Errors are
{ "error": { "code", "message" } }— branch onerror.code, never on the prose inmessage.
A second live call, using IP99's documented demo address (mask the last octet of real customer IPs in tickets):
curl https://ip99.com/v1/ip/27.22.66.200
Same window:
{
"ip": "27.22.66.200",
"computed_at": "2026-10-31T13:05:57Z",
"evidence_state": "active",
"geo": {
"country": "CN",
"region": "Hubei",
"city": "Xiangyang",
"district": "Yicheng",
"tz": "Asia/Shanghai"
},
"network": { "asn": 4134, "usage_type": "DYN" },
"risk": {
"score": 7,
"level": "low",
"signals": ["dialup_pool", "hijacked_proxy", "proxy"]
}
}
Residential usage_type: DYN plus proxy-class signals is exactly why "ban all IDC ASN ranges" fails: the interesting exits often sit on home broadband. Official triage order: read evidence_state first, then signals, then score/level — and prefer step-up verification over hard-banning a whole building when the address may be shared.
Wire it as a GPT Action (or similar)
Custom GPTs / Actions that accept an OpenAPI URL can point at the same file. Practical checklist:
-
Schema URL:
https://ip99.com/openapi.json(CORS already allows browser fetch). -
Auth for free experiments: none. For production volume, header
X-API-Key. -
Restrict the Action to
GET /v1/ip/{ip}(and maybe/v1/me) unless the agent truly has a professional Pulse key. Leaving Pulse in the Action without a key only produces403 professional_requirednoise. -
Prompt the model to report
evidence_stateandcomputed_atalongside the score. A stale or empty evidence state with score 0 must not be summarized as "clean IP."
If you want agents without a custom GPT, IP99 also exposes the same free profile as an MCP tool ip_risk_lookup at https://ip99.com/mcp — same fields as /v1/ip/{ip}. That path is covered in an earlier post; the OpenAPI file remains the right source of truth for HTTP clients and codegen.
Quotas, headers, and what not to invent
Every successful lookup can carry daily quota headers (X-Daily-Limit, X-Daily-Remaining, X-Daily-Reset). Prefer those (or GET /v1/me) over hard-coding numbers from an old article — allowances can change, and the response is authoritative for your tier.
Do not cache risk verdicts across sessions: the product thesis is that every answer is a judgement that expires. computed_at is part of what makes a decision auditable. Pulse's ?at= replay exists for chargeback-style "what did we know then?" questions; the free /v1/ip endpoint answers now only.
Also out of scope for this import guide (and for honest marketing): inventing customer logos, accuracy percentages, funding claims, or equating IP99's free profile with ThreatHunter's full enterprise datasets. IP99 is a ThreatHunter product; the free JSON you get from /v1/ip is exactly what the OpenAPI schema for that path describes — nothing more.
Try it
- Import https://ip99.com/openapi.json.
- Hit
/v1/ip/8.8.8.8with no key. - Branch your app on
evidence_statebefore you trust a zero.
Human reference: https://ip99.com/api. Product home: https://ip99.com.
來源:DEV Community · dev.to