{"slug": "import-ip99-s-openapi-once-postman-codegen-and-gpt-actions", "title": "Import IP99's OpenAPI Once: Postman, Codegen, and GPT Actions", "summary": "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'.", "body_md": "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.\n\nThis is a practical import walkthrough. Every curl below runs **without an API key**. Live samples were captured on **2026-10-31** (UTC).\n\n```\ncurl -s https://ip99.com/openapi.json | head -c 200\n# → {\"openapi\":\"3.1.0\",\"info\":{\"title\":\"IP99 IP risk and geolocation API\",...\n```\n\nAs 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:\n\n| Path | What it is | \n|---|---|\n| `GET /v1/ip/{ip}` | Free risk + geo + network profile (key optional) | \n| `GET /v1/me` | Your current tier and remaining quota | \n| `GET /pulse/v1/ip/{ip}` | Same score with per-evidence detail (professional key) | \n\n`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`).\n\nThe free endpoint is still the one you should try first:\n\n```\ncurl https://ip99.com/v1/ip/8.8.8.8\n```\n\nCaptured ~2026-10-31 13:05 UTC:\n\n```\n{\n  \"ip\": \"8.8.8.8\",\n  \"computed_at\": \"2026-10-31T13:05:33Z\",\n  \"evidence_state\": \"none\",\n  \"geo\": {\n    \"continent\": \"NA\",\n    \"country\": \"US\",\n    \"region\": \"California\",\n    \"city\": \"Mountain View\",\n    \"district\": \"\",\n    \"tz\": \"America/Los_Angeles\"\n  },\n  \"network\": { \"asn\": 15169, \"usage_type\": \"IDC\" },\n  \"risk\": {\n    \"score\": 0,\n    \"level\": \"none\",\n    \"signals\": [\"hosting\"]\n  }\n}\n```\n\n`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.\"\n\n`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.\n\nAny OpenAPI 3.1 generator that understands 3.1 will work. Example with the official CLI (install once, then pin the URL):\n\n```\nnpx @openapitools/openapi-generator-cli generate \\\n  -i https://ip99.com/openapi.json \\\n  -g typescript-fetch \\\n  -o ./ip99-client\n```\n\nOr Python:\n\n```\nopenapi-generator-cli generate \\\n  -i https://ip99.com/openapi.json \\\n  -g python \\\n  -o ./ip99-py\n```\n\nWhat you should assert in a smoke test after generation:\n\n`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`.\nA second live call, using IP99's documented demo address (mask the last octet of **real** customer IPs in tickets):\n\n```\ncurl https://ip99.com/v1/ip/27.22.66.200\n```\n\nSame window:\n\n```\n{\n  \"ip\": \"27.22.66.200\",\n  \"computed_at\": \"2026-10-31T13:05:57Z\",\n  \"evidence_state\": \"active\",\n  \"geo\": {\n    \"country\": \"CN\",\n    \"region\": \"Hubei\",\n    \"city\": \"Xiangyang\",\n    \"district\": \"Yicheng\",\n    \"tz\": \"Asia/Shanghai\"\n  },\n  \"network\": { \"asn\": 4134, \"usage_type\": \"DYN\" },\n  \"risk\": {\n    \"score\": 7,\n    \"level\": \"low\",\n    \"signals\": [\"dialup_pool\", \"hijacked_proxy\", \"proxy\"]\n  }\n}\n```\n\nResidential `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.\n\nCustom GPTs / Actions that accept an OpenAPI URL can point at the same file. Practical checklist:\n\n`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.\"\nIf 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.\n\nEvery 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.\n\nDo 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.\n\nAlso 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.\n\n`/v1/ip/8.8.8.8` with no key.\nHuman reference: [https://ip99.com/api](https://ip99.com/api). Product home: [https://ip99.com](https://ip99.com).", "url": "https://wpnews.pro/news/import-ip99-s-openapi-once-postman-codegen-and-gpt-actions", "canonical_source": "https://dev.to/ip99/import-ip99s-openapi-once-postman-codegen-and-gpt-actions-53a7", "published_at": "2026-10-31 13:08:29+00:00", "updated_at": "2026-10-31 13:19:52.230405+00:00", "lang": "en", "topics": ["ai-tools", "developer-tools", "ai-agents", "ai-products"], "entities": ["IP99", "ThreatHunter", "Postman", "Insomnia", "OpenAPI Generator", "OpenAPI 3.1"], "also_reported_by": [], "alternates": {"html": "https://wpnews.pro/news/import-ip99-s-openapi-once-postman-codegen-and-gpt-actions", "markdown": "https://wpnews.pro/news/import-ip99-s-openapi-once-postman-codegen-and-gpt-actions.md", "text": "https://wpnews.pro/news/import-ip99-s-openapi-once-postman-codegen-and-gpt-actions.txt", "jsonld": "https://wpnews.pro/news/import-ip99-s-openapi-once-postman-codegen-and-gpt-actions.jsonld"}}