Changes for version 1.1.0 - 2026-11-03

  • The API server's TLS certificate is now verified with every HTTP::Tiny version: verify_SSL => 1 is passed explicitly (HTTP::Tiny before 0.083 verified only when asked to, and 0.083+ can be told not to through an environment variable), with a new constructor option verify_ssl (default 1; 0 disables the check) and a matching accessor
  • The User-Agent header is now ipdata-perl/<version> (was Net-IPData-Perl/<version>)
  • Content-Type: application/json is sent only with the bulk POST, no longer as a default header on GET requests too
  • Single-field lookups (/{ip}/{field}) decode their bare JSON value with every JSON::PP version: JSON::PP before 4.0 (core before Perl 5.30) rejects a top-level string, number or null, so null came back as the string "null" and escape sequences in strings stayed undecoded
  • The test suite no longer needs network access (t/02-validation.t used to send requests to api.ipdata.co with a placeholder key)
  • Documentation: the threat shape lists is_vpn and scores (vpn_score, proxy_score, threat_score, trust_score), which the API returns
  • Connection reuse: the HTTP::Tiny user agent keeps one HTTPS connection alive across requests (keep_alive => 1, now explicit and configurable); HTTP/2 is not available with HTTP::Tiny, so the saving is the TLS handshake, not multiplexing
  • New constructor options keep_alive (default 1), keep_alive_timeout (idle timeout in seconds, honoured by HTTP::Tiny 0.092 and later, forwarded only when set) and ua (inject any object with HTTP::Tiny-compatible get/post), with matching accessors
  • bulk() retries the POST once when a kept-alive connection turns out to be dead before any response arrived (HTTP::Tiny status 599 with Socket closed / Unexpected end of stream / Connection reset); HTTP statuses are never retried
  • Require HTTP::Tiny 0.049 or later (fork- and thread-safe keep-alive)
  • CI runs on every push and pull request and installs the declared prerequisites before testing
  • New API response fields: top-level is_satellite and is_anycast (present only when true; a missing key reads as false) and first_seen, last_seen and days_seen on threat.blocklists entries (optional; dates kept as YYYY-MM-DD strings); the JSON passes through unchanged
  • is_satellite and is_anycast are accepted in fields => and lookup_field, with is_satellite($ip) and is_anycast($ip) convenience methods

Documentation

Modules

Perl client for the ipdata.co IP geolocation and threat intelligence API