<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>Hextner release notes</title>
    <link>https://hextner.com/changelog</link>
    <description>Dated release notes for the VerifIP IP reputation API, the DetectBT bot detection script, the Hextner console and this site, with an RSS feed of changes.</description>
    <language>en</language>
    <lastBuildDate>Mon, 05 Oct 2026 00:00:00 GMT</lastBuildDate>
    <atom:link href="https://hextner.com/changelog.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>Website: Full-text pages and structured data</title>
      <link>https://hextner.com/changelog#website-2026-10-05</link>
      <guid isPermaLink="true">https://hextner.com/changelog#website-2026-10-05</guid>
      <pubDate>Mon, 05 Oct 2026 00:00:00 GMT</pubDate>
      <category>Website</category>
      <description>&lt;ul&gt;&lt;li&gt;Every public page on hextner.com is now delivered as complete HTML, so tools that do not run JavaScript see the same text you do.&lt;/li&gt;&lt;li&gt;The sitemap now carries last-modified dates. New: &lt;code&gt;llms.txt&lt;/code&gt; and &lt;code&gt;llms-full.txt&lt;/code&gt; (a plain-text copy of the site for language models), and structured data that describes Hextner, VerifIP and DetectBT.&lt;/li&gt;&lt;/ul&gt;</description>
    </item>
    <item>
      <title>DetectBT 3.3.0: One billed evaluation per page load</title>
      <link>https://hextner.com/changelog#detectbt-3-3-0</link>
      <guid isPermaLink="true">https://hextner.com/changelog#detectbt-3-3-0</guid>
      <pubDate>Mon, 05 Oct 2026 00:00:00 GMT</pubDate>
      <category>DetectBT</category>
      <description>&lt;ul&gt;&lt;li&gt;The script checks each tab once when it loads. The page’s first &lt;code&gt;getToken()&lt;/code&gt; or &lt;code&gt;evaluate()&lt;/code&gt; without options now reuses that check, if its token is unused, under 4.5 minutes old and not a bot verdict. A page that loads the script and asks for one token on submit is billed one evaluation, not two.&lt;/li&gt;&lt;li&gt;A page that is prerendered but never opened is not evaluated: the automatic check waits until the page is shown.&lt;/li&gt;&lt;li&gt;Behaviour change: the script no longer evaluates automatically inside an iframe. Add &lt;code&gt;data-allow-iframe=&quot;true&quot;&lt;/code&gt; to the script tag to keep the old behaviour. Calls you make yourself inside a frame still work.&lt;/li&gt;&lt;li&gt;New &lt;code&gt;data-debug=&quot;true&quot;&lt;/code&gt; attribute on the script tag turns on debug logging.&lt;/li&gt;&lt;li&gt;The script is about 23 KB gzipped (64,784 bytes uncompressed).&lt;/li&gt;&lt;/ul&gt;</description>
    </item>
    <item>
      <title>VerifIP API 1.4.2: Quota refusals are free and say when to retry</title>
      <link>https://hextner.com/changelog#verifip-1-4-2</link>
      <guid isPermaLink="true">https://hextner.com/changelog#verifip-1-4-2</guid>
      <pubDate>Sun, 04 Oct 2026 00:00:00 GMT</pubDate>
      <category>VerifIP API</category>
      <description>&lt;ul&gt;&lt;li&gt;A request refused by your quota (429 &lt;code&gt;rate_limit_exceeded&lt;/code&gt;, the free daily cap or your monthly quota) is not billed: &lt;code&gt;X-VerifIP-Units-Billed&lt;/code&gt; is 0, and &lt;code&gt;X-RateLimit-Remaining&lt;/code&gt; no longer counts the refused request.&lt;/li&gt;&lt;li&gt;That 429 now also carries &lt;code&gt;retry_after&lt;/code&gt; in the body: the seconds until your quota resets, the same value as the &lt;code&gt;Retry-After&lt;/code&gt; header.&lt;/li&gt;&lt;li&gt;A batch body that is valid JSON but not an object (&lt;code&gt;null&lt;/code&gt;, an array, a number or a string) now gets 400 &lt;code&gt;invalid_request&lt;/code&gt;, not billed. &lt;code&gt;null&lt;/code&gt; used to get a 500.&lt;/li&gt;&lt;li&gt;A 503 &lt;code&gt;service_unavailable&lt;/code&gt; sent when the quota service cannot be reached now says when to retry: &lt;code&gt;retry_after: 1&lt;/code&gt; in the body and &lt;code&gt;Retry-After: 1&lt;/code&gt;. It is still not billed.&lt;/li&gt;&lt;li&gt;&lt;code&gt;GET /health&lt;/code&gt; now reports &lt;code&gt;commit&lt;/code&gt;, the build of the API that answered.&lt;/li&gt;&lt;li&gt;OpenAPI description: email and phone batch entries list their &lt;code&gt;invalid&lt;/code&gt; flag, and &lt;code&gt;voip_known_provider&lt;/code&gt; is marked as not currently produced.&lt;/li&gt;&lt;/ul&gt;</description>
    </item>
    <item>
      <title>Docs: Burst limits are described as approximate</title>
      <link>https://hextner.com/changelog#docs-burst-limits-2026-10-04</link>
      <guid isPermaLink="true">https://hextner.com/changelog#docs-burst-limits-2026-10-04</guid>
      <pubDate>Sun, 04 Oct 2026 00:00:00 GMT</pubDate>
      <category>Docs</category>
      <description>&lt;ul&gt;&lt;li&gt;The per-plan burst rates are a soft brake, counted per Cloudflare location, so traffic spread over several connections can exceed them for a short time. Pace requests on your side. The monthly quota is the exact limit.&lt;/li&gt;&lt;li&gt;Only the descriptions changed: the plan numbers, headers, error codes and limiting behaviour are the same.&lt;/li&gt;&lt;/ul&gt;</description>
    </item>
    <item>
      <title>Console: Clearer account deletion</title>
      <link>https://hextner.com/changelog#console-account-deletion-2026-10-03</link>
      <guid isPermaLink="true">https://hextner.com/changelog#console-account-deletion-2026-10-03</guid>
      <pubDate>Sat, 03 Oct 2026 00:00:00 GMT</pubDate>
      <category>Console</category>
      <description>&lt;ul&gt;&lt;li&gt;Deleting your account now tells you the date it will be permanently erased: 30 days after you delete it. A deleted account can no longer sign in.&lt;/li&gt;&lt;li&gt;Deleting an account ends any paid plan immediately, without refund for the unused period, and the console says so before you confirm. To use a plan until its period ends, cancel it first.&lt;/li&gt;&lt;li&gt;Within the 30 days, email contact@hextner.com to ask for the account back. Plans and API keys are not restored.&lt;/li&gt;&lt;/ul&gt;</description>
    </item>
    <item>
      <title>VerifIP API 1.4.0: WHOIS from the registries, real phone line types</title>
      <link>https://hextner.com/changelog#verifip-1-4-0</link>
      <guid isPermaLink="true">https://hextner.com/changelog#verifip-1-4-0</guid>
      <pubDate>Sat, 26 Sep 2026 00:00:00 GMT</pubDate>
      <category>VerifIP API</category>
      <description>&lt;ul&gt;&lt;li&gt;&lt;code&gt;/v1/whois&lt;/code&gt; asks the regional registry that holds the address directly. &lt;code&gt;network_cidr&lt;/code&gt; is now real CIDR notation (several prefixes are joined with &quot;, &quot;), the registry’s own identifier moved to the new &lt;code&gt;network_handle&lt;/code&gt;, and &lt;code&gt;allocation_date&lt;/code&gt; is &lt;code&gt;YYYY-MM-DD&lt;/code&gt;.&lt;/li&gt;&lt;li&gt;Phone &lt;code&gt;line_type&lt;/code&gt; is classified with full numbering data, so ordinary mobiles answer &lt;code&gt;mobile&lt;/code&gt; instead of &lt;code&gt;unknown&lt;/code&gt;, and &lt;code&gt;valid&lt;/code&gt; is a full pattern check.&lt;/li&gt;&lt;li&gt;&lt;code&gt;ssl_status: valid&lt;/code&gt; no longer passes a certificate that fails validation.&lt;/li&gt;&lt;li&gt;New enum values: &lt;code&gt;blocklisted&lt;/code&gt; in &lt;code&gt;threat_categories&lt;/code&gt;, &lt;code&gt;Unknown&lt;/code&gt; for &lt;code&gt;connection_type&lt;/code&gt;, and &lt;code&gt;rdns&lt;/code&gt; in &lt;code&gt;enrichment_incomplete&lt;/code&gt;. Treat values you do not recognise as opaque.&lt;/li&gt;&lt;li&gt;The URL check echoes the URL exactly as you sent it.&lt;/li&gt;&lt;/ul&gt;</description>
    </item>
    <item>
      <title>VerifIP API 1.3.0: OpenAPI description and fairer billing</title>
      <link>https://hextner.com/changelog#verifip-1-3-0</link>
      <guid isPermaLink="true">https://hextner.com/changelog#verifip-1-3-0</guid>
      <pubDate>Fri, 25 Sep 2026 00:00:00 GMT</pubDate>
      <category>VerifIP API</category>
      <description>&lt;ul&gt;&lt;li&gt;The API describes itself: &lt;code&gt;GET /openapi.json&lt;/code&gt; and &lt;code&gt;GET /openapi.yaml&lt;/code&gt; on verifip.hextner.com, with no key needed. Generate a typed client from it.&lt;/li&gt;&lt;li&gt;Not billed: requests refused as invalid (400), unknown endpoints (404), wrong methods (405), a batch on the Free plan (403 &lt;code&gt;plan_required&lt;/code&gt;) and a publishable key used on the data API (403 &lt;code&gt;public_key_not_allowed&lt;/code&gt;).&lt;/li&gt;&lt;li&gt;Browsers can read the rate-limit and billing headers in a cross-origin &lt;code&gt;fetch()&lt;/code&gt;.&lt;/li&gt;&lt;/ul&gt;</description>
    </item>
    <item>
      <title>VerifIP API: Official language SDKs retired</title>
      <link>https://hextner.com/changelog#verifip-sdks-retired-2026-09-25</link>
      <guid isPermaLink="true">https://hextner.com/changelog#verifip-sdks-retired-2026-09-25</guid>
      <pubDate>Fri, 25 Sep 2026 00:00:00 GMT</pubDate>
      <category>VerifIP API</category>
      <description>&lt;ul&gt;&lt;li&gt;No new versions of the VerifIP language SDKs will be published. Installed versions keep working against the API, but they will not learn new fields.&lt;/li&gt;&lt;li&gt;For new code, call the HTTPS API directly with your language’s standard HTTP client, as the docs show, or generate a client from the OpenAPI description.&lt;/li&gt;&lt;/ul&gt;</description>
    </item>
    <item>
      <title>VerifIP API 1.2.0: IPv6 for every key</title>
      <link>https://hextner.com/changelog#verifip-1-2-0</link>
      <guid isPermaLink="true">https://hextner.com/changelog#verifip-1-2-0</guid>
      <pubDate>Fri, 25 Sep 2026 00:00:00 GMT</pubDate>
      <category>VerifIP API</category>
      <description>&lt;ul&gt;&lt;li&gt;Public IPv6 addresses get a score instead of a 400 on &lt;code&gt;/v1/check&lt;/code&gt;, batch, &lt;code&gt;/v1/assess&lt;/code&gt;, &lt;code&gt;/v1/whois&lt;/code&gt; and &lt;code&gt;/v1/report&lt;/code&gt;.&lt;/li&gt;&lt;li&gt;Every IP answer carries &lt;code&gt;ip_version&lt;/code&gt; (4 or 6). IPv6 answers list the sources that have no IPv6 data in &lt;code&gt;signals_unavailable&lt;/code&gt;.&lt;/li&gt;&lt;li&gt;Every spelling of an IPv4-mapped IPv6 address is answered as the IPv4 address it carries.&lt;/li&gt;&lt;/ul&gt;</description>
    </item>
  </channel>
</rss>
