Import IP99's OpenAPI Once: Postman, Codegen, and GPT Actions IP99 by ThreatHunter publishes an OpenAPI 3.1 document at a stable URL, letting developers import its IP risk and geolocation API directly into Postman, Insomnia, openapi-generator, or a GPT Action instead of working from a PDF. The spec covers three paths — a free risk/geo/network profile, a quota endpoint, and a professional Pulse endpoint with per-evidence detail — and uses X-API-Key or Bearer auth, rejecting keys passed in the query string. Anonymous callers get 500 lookups per day at 60 per minute, and the free response exposes evidence_state as a first-class field, where a score of 0 with evidence_state 'none' means no verifiable evidence rather than 'safe'. 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 . 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." https://ip99.com/openapi.json . lookupIP GET /v1/ip/{ip} , set ip to 8.8.8.8 , send. No Authorization needed for anonymous quota. apiKey and map it to the bearer scheme when you create a free key in the console. Fields do 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. 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: evidence state enum: active | stale | none . risk.score is documented and treated in app code as risk.signals is an array of slugs; hosting / mobile describe the network and are not, by themselves, a ban reason. { "error": { "code", "message" } } — branch on error.code , never on the prose in message . 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. Custom GPTs / Actions that accept an OpenAPI URL can point at the same file. Practical checklist: X-API-Key . /v1/me unless the agent truly has a professional Pulse key. Leaving Pulse in the Action without a key only produces 403 professional required noise. computed at alongside 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. 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. /v1/ip/8.8.8.8 with no key. Human reference: https://ip99.com/api https://ip99.com/api . Product home: https://ip99.com https://ip99.com .